CLI and SDK
Rent GPU machines from a terminal with the nodelodge command, or from your own code with the TypeScript and Python SDKs.
The nodelodge command and the SDKs for TypeScript and Python call the Node Lodge API with an API key. They find a Node Lodge Secure machine, launch a session with a maximum cost, give you the SSH command and stop the session.
Before you start
- In the console, open Keys and create a key with the scopes
workloads:read,workloads:writeandbilling:read. - Set its Spending limits (per session and total). Node Lodge refuses any session that would go past one.
- Have an SSH key pair ready. See SSH keys.
Every session reserves its maximum cost on your organization credit at launch, as its budget. It is billed for the real time it runs, never past the budget. See Billing.
Command line
Requires Node.js 22 or newer.
Install
mkdir -p ~/.local/bin && cd ~/.local/bin
curl -fsSLO https://nodelodge.com/downloads/nodelodge.mjs
curl -fsSLO https://nodelodge.com/downloads/nodelodge.mjs.sha256
sha256sum -c nodelodge.mjs.sha256 && mv nodelodge.mjs nodelodge && chmod +x nodelodge
On macOS, check with shasum -a 256 -c nodelodge.mjs.sha256. Make sure ~/.local/bin is on your PATH.
Log in
nodelodge login
Paste the key when asked. It is checked, then saved readable by you only, in your configuration folder (~/.config/nodelodge on Linux, ~/Library/Application Support/nodelodge on macOS, %APPDATA%\nodelodge on Windows). The key is never typed on the command line, so it stays out of your shell history. In CI, set NODELODGE_API_KEY instead. nodelodge logout removes the saved key.
Find a machine
nodelodge offers --min-vram 48
nodelodge offers --gpu H100 --min-gpus 2
Filters: --gpu <model>, --min-gpus <n>, --min-vram <GB>, --max-price <USD per hour>, --all (machines out of stock too). Offers are listed cheapest first, with their specs, hourly price and location.
Launch, connect, stop
nodelodge balance
nodelodge launch 3f0c8f5e-8c3a-4f39-9a8e-2d9b4c1e7a10 --max-cost 20 --allow 203.0.113.7
nodelodge status 9b2d6a1e-1f5c-4a8e-9a77-3c0f2e6d4b21 --wait
nodelodge raise-budget 9b2d6a1e-1f5c-4a8e-9a77-3c0f2e6d4b21 --max-cost 40
nodelodge stop 9b2d6a1e-1f5c-4a8e-9a77-3c0f2e6d4b21
--max-costis required: the most the session may cost, in USD. It is reserved on your credit, and the session stops before it is spent. Add--hours <n>to stop it after n hours.--environment <id>picks the environment,jupyterlabby default: data-center machines runjupyterlab.raise-budgetraises the budget of a running session to a new--max-cost, within the limits of the key.--allowis the public IPv4 address you connect from, or a range up to /24. Only it can reach the machine over SSH.- The SSH key is read from
~/.ssh/id_ed25519.pub(thenid_ecdsa.pub,id_rsa.pub). Pass another with--ssh-key <file>. It opens this session only and is not saved on your account. status --waitwaits until the machine runs, printing each launch step as it starts, then prints itssshcommand. With--json, only the session object is printed, with itslaunchfield.statusalone lists your live sessions,status --endedyour ended ones.stopends the session: billing stops and the machine and its disk are deleted. Copy your results off the machine first.
Add --json to any command to get the session objects, for scripts:
id=$(nodelodge launch "$OFFER" --max-cost 20 --allow "$MY_IP" --json | jq -r .id)
nodelodge status "$id" --wait --json | jq -r '.ssh.host'
Exit codes: 0 done, 1 refused by Node Lodge (the reason and its code are printed), 2 invalid command line.
TypeScript SDK
Requires Node.js 22 or newer.
npm install https://nodelodge.com/downloads/nodelodge-sdk.tgz
import { ConflictError, NodeLodge, PaymentRequiredError } from '@nodelodge/sdk';
const nl = new NodeLodge({ apiKey: process.env.NODELODGE_API_KEY ?? '' });
const { items } = await nl.offers.list({ minVramGb: 48, bookableOnly: true });
try {
const session = await nl.sessions.launch({
offerId: items[0].id,
maxCostCents: 2000,
sshPublicKey: 'ssh-ed25519 AAAA... you@laptop',
allowedCidr: '203.0.113.7',
});
let s = await nl.sessions.get(session.id);
while (!s.ssh) {
await new Promise((r) => setTimeout(r, 10_000));
s = await nl.sessions.get(session.id);
}
console.log(`ssh ${s.ssh.user}@${s.ssh.host}`);
// ... run your job ...
await nl.sessions.stop(session.id);
} catch (err) {
if (err instanceof ConflictError) console.error(err.code, err.message); // API_KEY_LIMIT
else if (err instanceof PaymentRequiredError) console.error('Add credit in Billing.');
else throw err;
}
Amounts are in cents. nl.sessions.raiseBudget(id, 4000) raises the budget of a running session. launch takes an optional environmentId, and nl.environments.list({ offerId }) lists what a Community machine can run. nl.account.funds() returns the credit available for a new session.
Python SDK
Requires Python 3.10 or newer.
pip install https://nodelodge.com/downloads/nodelodge-0.2.0-py3-none-any.whl
import os
import time
from nodelodge import ConflictError, NodeLodge, PaymentRequiredError
with NodeLodge(os.environ["NODELODGE_API_KEY"]) as nl:
offer = nl.offers.list(min_vram_gb=48, bookable_only=True).items[0]
try:
session = nl.sessions.launch(
offer.id,
max_cost_cents=2000,
ssh_public_key=open(os.path.expanduser("~/.ssh/id_ed25519.pub")).read().strip(),
allowed_cidr="203.0.113.7",
)
while (s := nl.sessions.get(session.id)).ssh is None:
time.sleep(10)
print(f"ssh {s.ssh.user}@{s.ssh.host}")
# ... run your job ...
nl.sessions.stop(session.id)
except ConflictError as e: # API_KEY_LIMIT
print(e.code, e.message)
except PaymentRequiredError:
print("Add credit in Billing.")
Models are typed with snake_case fields, for example offer.price_per_hour_cents and session.max_cost_cents. nl.sessions.raise_budget(session.id, 4000) raises the budget of a running session. launch takes an optional environment_id, and nl.environments.list(offer_id=...) lists what a Community machine can run.
Sessions in both SDKs
A session has the same fields in both SDKs (camelCase in TypeScript, snake_case in Python):
| Field | Meaning |
|---|---|
status |
booked, starting, running, stopping, ended or failed. |
maxCostCents |
The budget: the most the session can cost. |
costSoFarCents |
Billed so far, the final charge once ended. |
heldCents |
The part of the budget still reserved on your credit. |
ssh |
Host, user and port once the machine runs. |
stopsAt |
When the session stops at the latest. |
kind |
session, or reservation for a machine booked as a reservation. |
launch |
While the session starts, its launch steps in order (ordered, allocated, booting, verifying on data-center machines, ready), each done, active or pending. Null once it runs. The step under way: currentLaunchStep(session) in TypeScript, session.launch_step in Python. |
What both SDKs do for you
- Retries: reads and launches are retried on network errors,
429and5xx, with exponential backoff, andRetry-Afteris honored. A launch is sent with an idempotency key, so a retry never starts two sessions. Stopping and raising a budget are not repeated after a failure that may have reached Node Lodge: check the session withgetinstead. - Typed errors:
AuthenticationError(401),PaymentRequiredError(402),PermissionError(403),NotFoundError(404),ConflictError(409),RateLimitError(429),ServerError(5xx),NetworkErrorandTimeoutError. Each API error has a stablecodeand a message you can show to a person. - A failed start costs nothing: if the machine cannot start, the session fails, nothing is billed and its budget is released.
- Sessions and reservations: on an account that books data-center machines as reservations (
RESERVATION_REQUIRED),launch,get,listandstopwork the same way, andkindisreservation. - Your key stays private: it is sent only to Node Lodge over HTTPS, and never appears in an error message.
To drive sessions from an AI agent instead, see Use Node Lodge from an AI agent (MCP).