Machine
Machines: an always-on computer for agents that should never sleep.
box = noclick.Machine.from_name("support-box", create_if_missing=True, size="medium", region="eu",
max_monthly_usd=120)
support = noclick.Agent.from_name("support", create_if_missing=True, instructions="...",
harness="claude_code", model_connection="claude", machine=box)
print(box.exec("df -h /").stdout)An agent on a machine runs its harness there instead of in a sandbox per conversation: nothing is reaped when it goes quiet, and there's no per-minute sandbox charge, only the machine's flat monthly price. Each conversation gets its own container on the machine, so threads never see each other's files. Model and tool calls go through NoClick's credential proxy with temporary keys: your real keys are never on the machine. NoClick manages its image and updates, restarts it if it fails (rebuilding it on a new host from its last backup if it must), and attached volumes outlive it.
class MachineInvite-only beta.
An always-on computer of a fixed size in one region, billed a flat monthly price (a thirtieth
of it a day while it exists, running or stopped). Agents created with machine run their harness
on it, each conversation in a container of its own; exec, files and expose reach the
machine itself.
- Like every live object, it also has hydrate(), refresh() and raw.
| id | string | |
| name | string | |
| size | MachineSizeName |
|
| cpu | number | null | vCPUs (hardware threads). |
| memoryGb | number | null | |
| diskGb | number | null | |
| region | RegionName | null | The region it runs in, fixed when it was created. |
| status | MachineStatus | |
| statusReason | string | null | Why it's stopped or failed, or why it restarted. |
| monthlyUsd | number | null | What it costs a month, in US dollars, running or stopped. |
| maxMonthlyUsd | number | null | The most you agreed it may cost a month. |
| network | boolean | string[] | null | What its own commands may reach: |
| volumes | Record<string, string> | The volumes it mounts: |
| agentCount | number | null | How many agents run on it. |
| image | string | null | The NoClick-managed image it runs, with its harness versions. |
| restarts | number | null | How many times it restarted after failing, ever. |
| lastRestartAt | Date | null | |
| userId | string | null | |
| createdAt | Date | null | |
| files | MachineFiles | |
| ports | MachinePort[] | The ports it serves. |
| consoleUrl | string | null | This machine in the developer console (null off the hosted API). |
sizesstatic
static sizes(options?: { client?: NoClick }): Promise<MachineSize[]>What a machine can be, smallest first.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
Each size's name (what size= takes), its processors, memory and disk,
its monthly_usd and about how many conversations can work on it at once.
createstatic
static create(name: string, options: MachineCreateOptions): Promise<Machine>Start an always-on machine called name (unique to its user; a taken name throws Conflict
with existingId), refused with PriceExceeded if its size costs more than maxMonthlyUsd. An
account's first machine needs its company vetted by NoClick (ActionRequired until it's approved).
One of Machine.sizes(); small by default.
"small")Where it runs (regions()), for good; omitted, your account's default region, else us-east.
Volumes it attaches, by absolute path: each conversation sees a volume as it was when its turn started and saves its writes when the turn ends.
What the machine's own commands may reach: true (anywhere the machines usage policy allows: no mail
ports, mining pools or private addresses) or a list of hosts (HTTPS to them, "*.github.com" for
subdomains, and name lookups).
The most its size may cost a month; above it nothing starts (PriceExceeded).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
The machine, provisioning until it's ready (running).
fromNamestatic
static fromName(
name: string,
options?: CallOptions & Partial<MachineCreateOptions> & {
createIfMissing?: boolean;
},
): MachineA lazy reference to the machine called name. With createIfMissing (and maxMonthlyUsd) it's
started on first use, and an existing machine whose size, volumes or network differ is changed to
match (a new size restarts it); its region is fixed, so one elsewhere throws Conflict
naming its region.
One of Machine.sizes(); small by default.
Where it runs (regions()), for good; omitted, your account's default region, else us-east.
Volumes it attaches, by absolute path: each conversation sees a volume as it was when its turn started and saves its writes when the turn ends.
What the machine's own commands may reach: true (anywhere the machines usage policy allows: no mail
ports, mining pools or private addresses) or a list of hosts (HTTPS to them, "*.github.com" for
subdomains, and name lookups).
The most its size may cost a month; above it nothing starts (PriceExceeded).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
A machine that loads (or is started, or brought in step with your definition) the first time it's used. Nothing is sent yet.
fromIdstatic
static fromId(machineId: string, options?: CallOptions): MachineA lazy reference to a machine by id.
A machine that loads the first time you read a field. Nothing is sent yet.
getstatic
static get(machineId: string, options?: CallOptions): Promise<Machine>Load a machine by id now; an unknown id raises noclick.NotFound.
The machine, loaded.
liststatic
static list(options?: ReadOptions & { limit?: number }): Promise<Machine[]>The current user's machines (the account's own outside asUser, or those userFilter covers).
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
Every matching machine, newest first, fetched page by page.
listPagestatic
static listPage(options?: ReadOptions & PageOptions): Promise<Page<Machine>>One page of machines; pass nextCursor back as cursor.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
A page whose data holds the machines and whose next_cursor is None on the last page.
exec
exec(
command: string,
options: ExecOptions & { background: true },
): Promise<Operation<ExecResult>>Run a shell command on the machine itself (not in a conversation's container): timeoutS is 60
by default, at most 90; { background: true } returns an Operation, for up to an hour.
Return at once with an Operation whose wait() resolves to the ExecResult.
Seconds before the command is stopped: 60 by default, at most 90, or 3600 with background.
What the command printed and how it exited, or with background=True an Operation
whose wait() gives that result.
expose
expose(port: number, options?: { public?: boolean }): Promise<MachinePort>Serve port at an HTTPS URL on NoClick's domain: private (an API key with the machines scope, which the
app never sees) unless public.
falseThe port's url.
closePort
closePort(port: number): Promise<void>Stop serving port; its URL stops answering.
agents
agents(): Promise<JsonObject[]>The agents that run on it, as their API rows (Agent.fromId(row.id) for the object).
Each Agent, loaded.
update
update(
changes: {
name?: string;
size?: MachineSizeName;
volumes?: Record<string, VolumeRef>;
network?: boolean | string[];
maxMonthlyUsd?: number;;
},
): Promise<this>Rename it, change its size, volumes, network or price ceiling. New volumes and network apply without a
restart (each conversation's from its next turn). A larger size restarts it once running turns finish
(updating); the new price applies from the next day. A smaller size moves a running machine to a new host,
since no host shrinks a disk in place: its user's home is copied over and each conversation loads its files
from where they're saved, a longer restart (what's on its disk must fit the smaller one; a move that fails
leaves it on its old host).
This machine, updated.
restart
restart(): Promise<Operation<Machine>>Restart it now (running turns fail as interrupted); its disk and volumes are kept and a machine.restarted
event follows. Resolves to the machine.
An Operation whose wait() gives the machine, running again.
stop
stop(): Promise<this>Stop it: its agents take no turns until start(). It's still charged.
This machine, stopped.
start
start(): Promise<this>Start a stopped machine. One stopped because the balance couldn't pay it is charged what it owes first
(PaymentRequired while it can't).
This machine, provisioning until it's running.
delete
delete(): Promise<void>Delete it with its disk (attached volumes stay); refused with Conflict while agents run on it.
MachineSizeinvite-only beta
interface MachineSizeInvite-only beta. One of Machine.sizes(): its processors, memory, disk and flat monthly price.
| name | MachineSizeName | What |
| cpu | number | vCPUs (hardware threads), as hosts sell them. |
| memoryGb | number | |
| diskGb | number | The machine's own disk. |
| monthlyUsd | number | Its price per month in US dollars, whatever it runs and whether it's busy. |
| workingConversations | number | About how many coding-agent conversations can work on it at the same moment. |
| raw | JsonObject | The response JSON exactly as the API sent it. |
MachinePortinvite-only beta
interface MachinePortInvite-only beta. A port a machine serves; a private one asks for an API key with the machines
scope, a public one answers anyone.
| port | number | |
| url | string | |
| public | boolean | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
MachineFilesinvite-only beta
class MachineFilesInvite-only beta. machine.files: read and write files on the machine's own disk.
write
write(
path: string,
data: string | Uint8Array | ArrayBuffer | Blob,
): Promise<void>Write data (bytes, or text as UTF-8) to path (relative paths are under /home/).
read
read(path: string): Promise<Uint8Array>Read the file at path; a missing file raises noclick.NotFound.
The file's bytes, exactly as stored.