warpmetal
v0.9.0
Published
Agent-safe CLI and skill for purchasing, renewing, and managing WarpMetal VPS servers
Maintainers
Readme
WarpMetal Agent Kit
The official command-line client and portable Agent Skill for WarpMetal.
The CLI uses https://api.warpmetal.com as the API root; endpoints begin at
/health, /catalog, /orders, and so on, without a second /api prefix. It
stores generated WarpMetal credentials in a user-private state file and never
reads or stores wallet private keys or SSH private-key contents. Version 0.6
adopts this canonical root-path API. WarpMetal writes the exact credential-free
payment request, explains the next commands to an agent, validates the returned
payment artifact, and submits it without absorbing wallet custody.
Distribution
- Source and releases:
https://github.com/warpmetal/agent-kit - CLI: the unscoped public npm package
warpmetal, exposing thewarpmetalexecutable - Skill:
skills/warpmetalin the GitHub repository and bundled inside the npm package - Codex plugin: the skills-only package under
plugins/warpmetal, exposed for repository testing by.agents/plugins/marketplace.json
Keeping the skill beside the CLI gives Codex, Claude, and other Agent Skills-compatible tools one canonical set of safety instructions while the CLI remains the stable executable API.
Install
WarpMetal supports Node.js 20 and 22. The separate x402api Agent Wallet requires Node.js 22; it is not a WarpMetal package dependency. Install the published wallet CLI with the exact version WarpMetal reports:
npm install --global warpmetal
warpmetal --help
npm install --global @x402api/[email protected]
x402api help --jsonInstall the bundled skill for supported coding agents:
warpmetal agent install --target <codex|claude|all>
warpmetal agent install --target codex
warpmetal agent install --target claude
warpmetal agent install --target allwarpmetal agent install installs only the bundled WarpMetal skill; it does
not install sandbox tools or select a sandbox tool profile.
Use --scope project to install into the current repository instead of the
user-level agent directory.
The bundled skills/warpmetal directory follows the portable Agent Skills
layout. Agents that support that layout but use another installation path can
consume that directory directly; they do not need a different WarpMetal API
integration.
Codex plugin
The repository also contains a skills-only WarpMetal plugin for the public
Plugins Directory shared by Codex and ChatGPT. The plugin remains a separate
artifact from the npm CLI and requires warpmetal CLI version 0.9.0 or newer.
To test the repository marketplace after the plugin lands on main:
codex plugin marketplace add warpmetal/agent-kit --ref main
codex plugin add warpmetal@warpmetalRun the plugin-specific repository checks with:
npm run plugin:checkPublic submission materials, reviewer cases, and the owner checklist live in
submission/openai. Public publication happens through the OpenAI Platform;
the repo marketplace is only for development, testing, and direct distribution.
First commands
warpmetal login
warpmetal auth status
warpmetal health
warpmetal catalog
warpmetal models --auth-mode chatgpt_subscription
warpmetal order prepare \
--account --without-agent-boxes \
--plan agent \
--hostname codex-workspace \
--os '<exact name from warpmetal catalog>' \
--generate-ssh-key \
--jsonwarpmetal login starts WarpMetal account authorization before any SSH key or
order configuration is needed. It opens the browser approval page by default;
use --no-browser to print the page and user code without opening it. The
default session requests cli:read cli:write; --read-only requests only
cli:read. Check the current account with warpmetal auth status and revoke
the CLI session with warpmetal logout.
The CLI stores only its own rotating account session under the private
WarpMetal state directory. Account sessions are separate from browser sessions,
legacy order owner tokens and SSH credentials, and are bound to the exact
Identity and account origins that issued them. --identity-url and
--account-url accept explicit origins for testing or alternate deployments;
credentials are never sent after an HTTP redirect or reused for other origins.
If a refresh response is lost, the CLI clears the local session and requires a
new login rather than risking reuse of a rotated credential. Logout always
clears the matching local session, and reports when remote revocation could not
be confirmed.
Use warpmetal account orders and warpmetal account devices for your account's
order history and active servers; add --task <id> or --server <id> for one
item. order prepare --account binds the unpaid order to the signed-in account
and uses its verified contact. It never issues an owner token. Login and account
creation do not require SSH keys or order configuration.
New account preparation defaults to Agent Boxes and an Agent team. Supply the
selected team in --runtime-file; no provider or model is silently selected.
Use --without-team for a single small persistent box, or
--without-agent-boxes for a VPS without boxes. An explicit runtime file keeps
its existing selections. warpmetal models --json supplies published model and
authentication choices; server readiness checks still apply.
Without --account, order preparation retains the existing owner-token
workflow, including payment and SSH automation. This release adds account order
preparation and inventory, not a new account payment or runtime-execution grant.
The account scopes do not authorize charges, renewals, deletion or Fleet access.
warpmetal catalog lists VPS plans. warpmetal models reads the separate,
public Agent Teams model catalog. It never signs in to a model provider or
creates an order. Use --provider or --auth-mode api_key|chatgpt_subscription
to filter published entries; JSON preserves the catalog snapshot, provenance,
freshness state and published authentication modes.
The generated key defaults to
${WARPMETAL_HOME:-~/.config/warpmetal}/ssh/warpmetal-codex-workspace. A
collision receives a random suffix; existing keys are never overwritten. Once
checkout returns serverId, the CLI binds that ID to the identity so
warpmetal server login is the distinct SSH challenge flow for one server.
It and warpmetal runtime install can select the generated identity without
an --identity flag. Use --ssh-public-key-file instead when supplying a
user-managed public key.
WarpMetal installs the owner key for root on every supported image. The SSH
key does not encode a login username: use root@<server-ip> for an owner shell
and --ssh-user root for runtime installation, not a distribution convention
such as ubuntu.
Starting in CLI 0.8.8, runtime install --confirm INSTALL establishes managed
SSH host trust without requiring access to the VPS provider. For a server trust
epoch with no pin, the CLI runs only a harmless ssh true using the exact owner
key, trusts the first observed Ed25519 host key, stores it under the private
WarpMetal state directory, and immediately reconnects with strict checking. It
requests the Runtime bootstrap only after that strict replay succeeds. Every
later SSH and SCP operation must match the same pin; a changed key is never
silently accepted or overwritten.
The private WarpMetal state directory is the local trust domain. Back it up with the owner key: deleting it also deletes the durable pin, so the next install is a new first-use decision rather than a verified continuation.
Pass --json for structured, secret-redacted output. Use
WARPMETAL_API_URL for an alternate API origin and WARPMETAL_HOME for an
alternate state directory.
Pay through the x402api Agent Wallet
After preparing an order, request its live payment challenge:
warpmetal checkout challenge --task <taskId> --jsonOn HTTP 402 the CLI returns exact paymentTerms, the opaque challengeHandle
that WarpMetal uses for merchant-side reconciliation, the pinned
@x402api/agent-wallet-cli package contract, and argv arrays under
paymentWorkflow. It also writes an owner-only request envelope that contains
the exact checkout URL and body but no WarpMetal credential or challenge
handle. The handle is not a buyer payment identifier and is never a wallet
signing input. The published launch wallet accepts sponsored Base USDC and
sponsored Solana USDC/USDT only;
the returned terms identify compatible alternatives and confirm that the buyer
does not need ETH or SOL. x402api pays the actual network fee from its platform
treasury; the merchant tenant's active allowance controls sponsorship
admission but is not charged actual gas. Payment authority depends on execution
context:
WarpMetal can advertise any currently executable subset of those rails, from a single alternative through all three. Agent Kit requires the sponsorship and external-recipient extension bindings to match the advertised alternatives exactly, then preserves the chosen authorization artifact byte-for-byte for every pending or ambiguous retry.
Submission output includes the server-validated paymentId, confirmed, and
finalized fields when WarpMetal supplies lifecycle evidence. Retry only while
confirmation is pending. As soon as confirmed is true, stop all payment
submission—even when finalized is false—and let WarpMetal continue signed-
receipt finality while provisioning or renewal proceeds.
For an interactive initial purchase, checkout challenge may also return a
short-lived humanCheckout object. Its url and qrPayload are the same
https://pay.x402api.com/c/... bearer capability for the exact charge.
Present the exact URL as a clickable x402api handoff. If a QR is useful for
another device, encode only the identical qrPayload and explain that
scanning opens the hosted checkout without authorizing payment. x402api owns
any wallet selection or wallet-specific opening QR inside that page; never
synthesize a wallet link or encode the WarpMetal recipient address. The buyer
needs only the advertised USDC/USDT balance because x402api sponsors the native
gas. This is an alternative to the agent-wallet workflow, not a second
payment. After browser payment, run the exact
humanCheckout.afterPayment.argv status command. When the ready result asks
for ask_human_for_notification_email, ask the owner and add the optional
lifecycle-notification address they provide. Autonomous purchases and renewals
continue to use the bounded agent-wallet path.
- When a human is actively chatting with the agent, show the exact live terms and ask for confirmation immediately before authorizing and submitting.
- In an unattended run, a pre-funded dedicated wallet is standing spend authority, bounded by its maximum-payment policy and any task or operator limits. When the live terms fit those limits, authorize and submit without waiting for conversational approval.
Follow the returned commands in order. wallet setup creates an owner-only,
managed unlock file inside the x402api home directory and is safe to repeat;
it never prints the generated passphrase. X402API_WALLET_PASSWORD_FILE is an
optional x402api override for an externally managed password file. It is not a
WarpMetal variable, and WarpMetal does not create, read, or receive that file.
x402api wallet setup --json
x402api wallet list --json
x402api wallet create --name <wallet-name> \
--network <exact-challenge-network> \
--maximum-payment-atomic <exact-live-amount> --json
x402api wallet address --wallet <wallet-name> --json
x402api wallet balance --wallet <wallet-name> \
--asset <exact-challenge-asset> --json
x402api wallet funding --wallet <wallet-name> \
--asset <exact-challenge-asset> \
--target-balance-atomic <exact-live-amount> --jsonCreate a wallet only when no compatible dedicated wallet exists. The funding command reports the public payer address, QR payload, current balance, target, and exact deficit in atomic and normal six-decimal units. After the selected wallet is sufficiently funded, invoke the returned authorization and WarpMetal submission argv:
x402api payment authorize \
--wallet <wallet-name> \
--request-envelope <path-returned-by-warpmetal> \
--artifact-out <path-returned-by-warpmetal> \
--json
warpmetal checkout submit \
--task <taskId> \
--payment-artifact <owner-only-artifact-path> \
--wait \
--jsonRequire maximumPaymentAtomic to cover the live charge without exceeding the
task or operator limit. Among valid sponsored terms, honor an explicit network
or asset preference, otherwise prefer an already funded compatible wallet,
then the first compatible term in live challenge order. Never switch terms
after authorization.
If funding is short in an interactive conversation, tell the human the exact
top-up in normal and atomic units, the network, stablecoin and contract/mint,
and the payer wallet's public receiving address. The returned
paymentWorkflow.fundingWorkflow provides safe address and balance argv plus a
presentation contract: render that public address as both a QR code and
copyable text. The human sends the token to that wallet address, never to the
token contract/mint or WarpMetal's payment recipient, and never sends ETH or
SOL for a sponsored payment. In an unattended run, use a preconfigured refill
or escalation mechanism or stop with funding_required.
Autonomous renewal and refill
Configure renewal only with explicit bounds. This example allows at most 12 renewals, enforces a 30 USDC per-payment ceiling and a 360 USDC cumulative budget, and activates a human notification recipient after server authorization:
warpmetal renewal configure \
--server <serverId> \
--renew-before-days 3 \
--maximum-payment-atomic 30000000 \
--maximum-renewals 12 \
--maximum-total-spend-atomic 360000000 \
--allowed-network eip155:8453 \
--allowed-asset 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--wallet <dedicated-wallet> \
--email [email protected] \
--jsonNo email verification is required: the saved owner credential or an SSH-derived
server token authorizes the change. WarpMetal queues a branded transactional
advisory identifying the server, why the address was added, and a link that
removes only that address. Up to five active addresses may be attached
to one server. If none exists, renewal configure returns email_required
before changing policy. Supply --email, or deliberately continue with
--without-email-notifications; the latter does not enable signed refill-email
workflows. A recurring unattended agent can then run:
warpmetal notifications add --server <serverId> --email [email protected] --json
warpmetal notifications list --server <serverId> --json
warpmetal notifications remove --server <serverId> --recipient <recipientId> --json
warpmetal notifications events --server <serverId> --events renewal.due,server.ready --json
warpmetal notifications disable --server <serverId> --jsonAfter provisioning, warpmetal order status includes the structured
ask_human_for_notification_email next action until a recipient is active or
the human explicitly opts out. Public CLI output contains only masked addresses.
warpmetal renewal due --all --json
warpmetal renewal run --all-due --jsonInside policy, the CLI returns the exact Agent Wallet authorization and submit
argv. If balance is insufficient, refillWorkflow is returned only when the
server has an active notification recipient. Run its argv with the
returned X402API_NOTIFICATION_URL environment value. x402api wallet
notify-refill signs an opaque subscription reference and wallet-produced
balance fields; it cannot choose an email address. WarpMetal verifies the
wallet signature and current on-chain balance before emailing every active
human recipient the network, stablecoin, public wallet address, required minimum top-up,
and a locally generated QR encoding only that wallet address. The address is
also repeated as copyable text. The human may transfer more than that minimum;
the renewal policy—not the refill target—remains the spending authority.
The agent never sends a partial x402 payment. If no active recipient refill path
exists, it reports funding_required. If a previous payment is pending or
ambiguous, it reconciles the saved attempt and never signs a second payment.
The x402api Agent Wallet is a separate, merchant-neutral executable. Install
its matching x402api-pay skill with x402api skill install --output <agent-skill-directory>/x402api-pay --json.
Do not use x402api pay, payment submit, or payment reconcile for WarpMetal:
checkout requires the private WarpMetal owner token, so x402api authorizes and
WarpMetal submits. WarpMetal keeps --payment-signature-file for another
compatible external signer.
Security boundary
- Order and access tokens are never printed; they are written to
${WARPMETAL_HOME:-~/.config/warpmetal}/state.jsonwith user-only permissions where the platform supports POSIX modes. - The CLI passes an SSH private-key path directly to
ssh-keygen; it never reads the private key. - WarpMetal applies key-only OpenSSH configuration on initial provisioning and every OS reload. Password and keyboard-interactive login are disabled; never request, store, or expect a VPS login password.
- The CLI writes x402api-compatible request envelopes and accepts validated
x402api payment artifacts or a compatible external
PAYMENT-SIGNATUREfile. Wallet key management and signing remain outside this package. - Destructive or state-changing commands require explicit confirmations and generate idempotency keys by default.
- Runtime bootstrap credentials remain memory-only. Manual installation asks for one only after the first host key has been pinned and strictly reverified; automatic reload bootstrap is rendered directly into provider-bound cloud-init. Signed supervisor bundles are checksum- and signature-verified.
- Each agent gets a distinct SSH key forced into exactly one sandbox. Token-free connection profiles pin the VPS host key and contain no owner credential or private-key material.
- Sandboxes use the fixed runtime image and fixed sizes. Persistent is the default; temporary sandboxes require explicit confirmation and permanently delete their workspace after 15 minutes to 24 hours.
sandbox action --action refresh_image --confirm refresh_image --waitexplicitly replaces one sandbox's root filesystem with the current immutable production image. It briefly disconnects active sessions but preserves the external workspace, lifetime, and start time. The wait completes only when the observed digest and generation both match the accepted target.- Guarded reload powers the server off first. Runtime-enabled reload requires a second acknowledgment because all sandbox workspaces are erased. WarpMetal places the approved signed Runtime bootstrap in reload cloud-init automatically; wait for Runtime readiness, then refresh pinned sandbox connection profiles. Only a locally recorded reload operation that succeeds and reports an owner-host-key refresh opens one new managed trust epoch; failed or ambiguous reloads retain the old pin and never permit replacement. Erased workspaces are never described as recoverable.
- New agent-enabled candidate orders and Runtime-enabled reloads pass the closed nested-sandbox opt-in inside verified provider cloud-init. The signed Runtime bundle installs the exact-path AppArmor policy for the neutral image's immutable Bubblewrap helper; this needs no follow-up customer SSH key and adds no public order field or CLI flag. VPS-only cloud-init is unchanged. Existing enrolled hosts use reload/reprovision; the CLI does not claim a silent in-place policy repair command.
- Runtime reports a new or replaced sandbox generation as running only after a
fixed, credential-free inner-Bubblewrap oracle proves nested namespaces, an
inherited read-only view of the outer Agent Box's already isolated procfs,
an allowed workspace write, empty Linux capability sets,
no-new-privileges, and protected-root write denial. Failure stops the container before access grants or tool setup advance.
For a Runtime-enabled reload, no separate installation command is part of the successful path:
warpmetal server reload \
--server <serverId> --confirm ERASE --power-off-first \
--acknowledge-agent-runtime-reset --wait --json
warpmetal runtime get --server <serverId> --wait --json
warpmetal sandbox access refresh \
--server <serverId> --sandbox <sandboxId> --grant <grantId> \
--connection-file <profile-path> --confirm REFRESH --wait --jsonThe successful reload records a new operation-bound owner SSH trust epoch. Verify the replacement host key before using owner SSH; sandbox access remains strictly pinned through each refreshed connection profile.
Agent Runtime example
warpmetal runtime enable --server <serverId> --json
warpmetal runtime install \
--server <serverId> \
--ssh-user root \
--confirm INSTALL \
--wait \
--json
warpmetal sandbox create \
--server <serverId> \
--name planner \
--size small \
--wait \
--json
warpmetal sandbox action \
--server <serverId> \
--sandbox <sandboxId> \
--action refresh_image \
--confirm refresh_image \
--wait \
--json
warpmetal sandbox access keygen \
--output ~/.ssh/warpmetal-planner \
--confirm GENERATE \
--jsonRegistered sandbox tools
WarpMetal can apply only registered, immutable tool profiles. These commands use the owner credential already stored in the private WarpMetal state file; they do not accept a bearer token on the command line or permit a caller-supplied URL, shell command, environment, or artifact override.
warpmetal tools list --server <serverId> --json
warpmetal tools install --server <serverId> --sandbox <sandboxId> --profile <profileId> \
[--idempotency-key <key>] [--wait] [--timeout-seconds <n>] --json
warpmetal tools status --server <serverId> [--wait] [--timeout-seconds <n>] --jsontools install posts only the selected registered profileId. Waiting is
bounded: ready exits 0, failed or cancelled exits 5, and a timeout exits 8.
JSON output contains public profile, operation, and receipt metadata only.
Successful non-wait installs and status inspections exit 0 while reporting the
accepted or current state; exit 8 is reserved for an actual --wait deadline
timeout.
Codex is a released automatic tool profile when the public
/agent-tool-profiles endpoint advertises it as available. WarpMetal installs
the exact registered artifacts when selected at order time or through
tools install. Claude Code uses the released claude-code automatic tool
profile under the same public availability gate. Claude Managed Agents are separate:
claude-managed-ant is an install-only CLI profile. Installing ant does not
authenticate a worker and does not activate Managed Agents. Cursor CLI remains
manual and unavailable as an automatic profile until separately qualified later.
Gemini CLI remains manual.
An order --runtime-file may add the closed optional setup intent beside its
sandboxes array:
{
"sandboxes": [
{ "name": "codex-worker", "size": "small" },
{ "name": "claude-worker", "size": "small" },
{ "name": "managed-worker", "size": "small" }
],
"setup": {
"version": 1,
"sandboxProfiles": [
{ "sandboxName": "codex-worker", "profileId": "codex" },
{ "sandboxName": "claude-worker", "profileId": "claude-code" },
{ "sandboxName": "managed-worker", "profileId": "claude-managed-ant" }
]
}
}Only those fields are accepted. Each setup entry must name a sandbox in the same file and a registered profile ID.
Install a standard sandbox SSH alias
Use a separate keypair and access grant for each sandbox. After the grant is
applied, install its token-free profile as a concrete OpenSSH alias:
warpmetal sandbox access install-ssh \
--connection-file <profile-path> \
--identity <sandbox-private-key-path> \
--alias <alias> \
--json
ssh <alias>
ssh -t <alias> codex
ssh <alias> codex exec '<task>'
ssh -t <alias> claude
ssh <alias> claude -p '<task>'
ssh -t <alias> agent
ssh <alias> agent -p '<task>'
ssh -t <alias> gemini
ssh <alias> gemini -p '<task>'Authenticate Codex or Claude Code inside the sandbox after its selected profile
is ready. The public /agent-tool-profiles response is authoritative for
availability and checkout selection. Claude Code uses the claude-code
automatic tool profile. Claude Managed Agents are
separate: claude-managed-ant is an install-only CLI profile. Installing ant
does not authenticate a worker and does not activate Managed Agents. Cursor CLI
remains manual and unavailable as an automatic profile until separately
qualified later. Install and authenticate Cursor CLI or Gemini CLI inside the
sandbox. Provider credentials are sandbox-owned and remain in its
persistent home; WarpMetal does not perform provider login or receive them.
The alias is local-only. It prepends a managed include to ~/.ssh/config and
uses the profile's pinned host key plus the sandbox identity. It never uses or
exposes the VPS owner management key. The server-side forced gateway maps that
identity to only its assigned sandbox, cannot open a host shell, and retains
ClearAllForwardings yes together with agent and X11 forwarding denial.
An exact reinstall is safe and unchanged. If an authenticated access refresh produces a new profile, refresh the profile first and then explicitly replace the local alias:
warpmetal sandbox access refresh \
--server <serverId> --sandbox <sandboxId> --grant <grantId> \
--connection-file <profile-path> --confirm REFRESH --wait --json
warpmetal sandbox access install-ssh \
--connection-file <profile-path> \
--identity <sandbox-private-key-path> \
--alias <alias> --confirm REFRESH --jsonRemove only that managed alias and pin with explicit confirmation; unrelated SSH configuration is preserved:
warpmetal sandbox access remove-ssh --alias <alias> --confirm REMOVE --jsonCodex Desktop's remote-connections contract
discovers concrete aliases from ~/.ssh/config, requires ssh <alias> to
work, and starts the remote app server through the login shell. Install Codex
inside the sandbox and ensure Codex is on the login-shell PATH before choosing
the alias in Codex Desktop.
The tested Cursor Remote SSH path is incompatible with this boundary because
it requests dynamic forwarding, which WarpMetal deliberately denies. Do not
weaken sandbox forwarding controls to make the IDE connect. Use the supported
Cursor CLI interactively with
ssh -t <alias> agent or in
headless mode with
ssh <alias> agent -p '<task>' instead.
Use the official Gemini CLI installation guide
before running ssh -t <alias> gemini, or use its documented
headless mode with
ssh <alias> gemini -p '<task>'. Gemini's optional Docker or Podman sandbox is
normally unavailable inside the WarpMetal sandbox because no host
container-engine socket is exposed; run Gemini directly inside the existing
outer sandbox and choose its approvals yourself.
On the first install in a server trust epoch, JSON output includes
hostKeyTrust.state: "trusted_first_use" and the safe Ed25519 fingerprint.
Later installs report "matched". First-use trust protects continuity after
that observation, but it cannot detect an active attacker on the first
connection. Provider-console host-key pre-enrollment remains an optional
higher-assurance alternative when it is available.
Installation gives pre-existing Docker containers exact liveness checks and
tracks common container-runtime processes without collecting application
configuration. The signed installer uses crun for its private rootless Podman
engine, refuses package removals or changes to an installed container stack,
and checks minimal liveness metadata after package installation and again
immediately before registration. Safety refusals have no force bypass; review
the reported runtime_* code instead of changing or restarting a third-party
runtime automatically. With --json, that code is returned as structured
error.code. A pending reboot and legacy preview Podman state are separate
maintenance operations, not implicit install steps.
See skills/warpmetal/references/runtime.md for the complete lifecycle,
cleanup, access-grant, and strict host-key connection workflow.
Release status
The package is published at
https://www.npmjs.com/package/warpmetal. The source is publicly visible but
remains UNLICENSED; choose an explicit license before describing the project
as open source or inviting third-party reuse.
