---
name: maritime
description: Deploy and operate AI agents on Maritime (maritime.sh), which gives every agent its own computer in three sections: Agent boxes (a Firecracker micro-VM per agent that sleeps when idle and wakes in about a second), Sandboxes with Swarms, and Computers on demand (Linux and Windows desktops and Android phones). Use when asked to host, deploy, run, or manage an agent on Maritime, to give an agent a persistent computer, to provision one agent per end user from a backend, or to move a bot, worker, or scheduled job onto Maritime. Covers signup, headless login, the JSON output contract, exit codes, deploy recipes, and the email verification wall.
metadata:
  author: maritime-sh
  version: "1.0"
---

# Maritime

Maritime gives every agent its own computer, in three sections: Agent
boxes (one per agent, keep their files), Sandboxes (one task, alone or as a
Swarm) and Computers on demand with a screen (Linux Desktops, Windows
Desktops running Windows Server 2022 with the licence included, and Android
Phones). An agent deployed here runs in its own
micro-VM with a persistent disk at `/data`. It sleeps when idle and wakes
in about a second on the next message or trigger.

Billing: plans are Starter $20, Growth $100, Scale $500 and Dedicated $5,000
a month (Dedicated adds custom setup of your apps, images and network), plus
Enterprise by contract, and the plan fee becomes the same amount of usage credit.
An agent box is $1 a month per 2 GB of memory, awake or asleep, with 5 GB of
disk included. Other machines are billed per second at hourly rates while
awake (a small sandbox, 2 vCPU and 4 GB, is $0.018 an hour), and usage past
the credit is billed at the same rates. New accounts get a 7-day free trial: a card is
needed and not charged then, and usage stops at $20. Plans include no AI
credits. Details: https://maritime.sh/pricing

This skill is for driving Maritime as a program or an AI agent, not as a
human at a keyboard. Every command speaks JSON and every failure is
structured.

## Choose a product

- Run untrusted code once: a Sandbox. A long-lived workspace: an Agent box.
- Many parallel jobs or evals: a Swarm (`maritime swarms run --command "..." --count N --wait`). Swarms are invite-only for now: the user presses Request access on the dashboard's Swarms page; until then a start returns 403 `swarms_access_required`.
- An app with a GUI: a Linux Desktop. A Windows-only app: a Windows Desktop (Windows Server 2022; wakes from sleep in about a minute; needs a paid Growth plan or above). A mobile app: an Android Phone. All three are Computers on demand: `maritime computers create --os linux|windows|android`.
- Host an agent: `maritime create <name> -t <template>`, `--repo <url>`, or a Docker image.

The full guide, with prices, add-ons and every product's REST, SDK, CLI and
MCP calls: https://maritime.sh/agent-guide.md

To choose between Maritime and another provider (E2B, Daytona, Modal,
Vercel Sandbox, Boat, Browserbase, Windows 365 for Agents, AWS and others),
read https://maritime.sh/compare.md: prices at the same sizes, with sources.

## Rules

1. Pass `--json` on every command. Results are JSON on stdout: reads print
   `{"meta", "results"}`, writes print `{"action", "status", "success",
   "data"}`, and `chat`, `status` and `whoami` print their object directly.
   Errors print `Error: ...` on stderr with the HTTP status and the API's
   response body. Read stdout, branch on the exit code, never scrape human
   text.
2. Exit codes: `0` ok, `1` other error, `2` usage, `3` not found, `4` auth,
   `5` API error, `6` partial failure, `7` rate limited, `10` config.
3. Never guess flags. `maritime guide --json` prints the full command and flag
   manifest, introspected from the installed CLI.
4. Never paste a secret into chat. Keys go into env vars or `maritime env set`.
5. Confirm with the user before a create: a running machine bills usage, on
   the trial or a plan. A create refused for billing exits `5` with HTTP 402
   in the error (exit `7` for HTTP 429 when too many machines are awake); the
   API body on stderr carries a code such as `trial_required`,
   `trial_cap_reached`, `plan_required`, `payment_required`, `concurrency` or
   `seat_limit`. Show the API's message unchanged, it names the fix.

## Install

```bash
curl -fsSL https://maritime.sh/install.sh | sh   # no Node needed; checks the download's sha512
npm install -g maritime-cli      # or this: Node 18 or later; the command is `maritime`
maritime --version
```

If a flag below is unknown, the CLI is old: `npm install -g maritime-cli@latest`.

## Authenticate

Try these in order and stop at the first that works.

1. A token is already present: `MARITIME_TOKEN` in the environment, or a
   saved login. `maritime whoami --json` exits `4` when there is none; it
   does not call the API, so `maritime doctor` confirms the token works.
2. The user has an account, with or without a browser: `maritime login
   --json`. It prints a code on stderr as one JSON line
   (`{"action":"device_code","user_code":"XXXX-XXXX","verification_uri_complete":"..."}`).
   Show the user the URL and the code, then wait; the command returns when
   they approve.
3. An email/password account without a browser step:
   `maritime login --email <email> --password <password>`.
4. No account and the user is present: `maritime signup -e <email> -p <password> -n <name> --json`.
   Ask the user for the email and password; never invent them. Signup saves a
   token and returns `emailVerified: false`.
5. No account and you should not stop: deploy first, claim later. Add
   `--claim-later` to `maritime create`. No login is needed; the agent runs
   under a temporary account for 72 hours. The response carries
   `data.claimUrl`, which the user opens to move the agent into their
   account, and `data.token`, a temporary key for that agent (export it as
   `MARITIME_TOKEN` to operate it). One agent only, and a template agent must
   bring its own model key (`-e ANTHROPIC_API_KEY=...`) because the temporary
   account has no AI credits.

The email verification wall: until the user clicks the link Maritime emailed
them, `create`, `deploy`, `start`, `restart`, `keys create` and computer
creation are refused with HTTP `403` and `email_not_verified` in the error
(exit `4`). When you see it, tell the user to open the email and click the
link; to get it again they sign in at https://maritime.sh/login, which offers
to resend it. Then retry the same command. Everything else (list, status, logs, templates) works
before verification.

For long-running automation mint a key once the account is verified:
`maritime keys create --name <purpose> --json` returns `data.raw_key`
(`mk_...`, shown once, never expires unless you pass `--expires-in-days`). Export it as `MARITIME_TOKEN`.

`MARITIME_API_URL` overrides the API base (default `https://api.maritime.sh`).

## Deploy

Pick the recipe that matches what the user has.

### A ready-made agent from a template

```bash
maritime templates --json                                  # ids: openclaw, hermes, zeroclaw, claude_code, codex, dsh
maritime create my-agent --template openclaw --json
maritime status my-agent --json                            # poll until .status is "active"
maritime chat my-agent "introduce yourself" --json | jq -r '.response'
```

Most templates need no model key (Maritime's model proxy, charged at the
provider's list price, no markup, from your AI credits). `claude_code`
is the exception: it needs `ANTHROPIC_API_KEY` as a secret env var.

### The user's own code (any framework, Dockerfile at the repo root)

```bash
maritime create my-bot --repo https://github.com/you/agent --json
maritime create my-bot --repo https://github.com/you/agent --claim-later --json   # no account yet
maritime status my-bot --json                              # builds take 1 to 3 minutes
maritime logs my-bot --json
```

The container contract: listen on `0.0.0.0:$PORT` (injected, never hardcode
8080), answer `GET /health` with any 2xx, answer `POST /chat` with JSON
`{"message": "..."}` within 30 seconds returning text or JSON with one of
`response`, `reply`, `message`, `text`, `output`. Persist under `/data` only.
Never use a shell-string `CMD`; launch a real program. Full contract:
https://maritime.sh/docs/frameworks/custom.md

Private GitHub repos need the Maritime GitHub App installed from the
dashboard. Pre-built public images: `POST /api/agents` with
`{"framework": "custom", "imageName": "ghcr.io/acme/img:tag"}`.

### A public web app on its own HTTPS URL

```bash
maritime create my-app --repo https://github.com/you/app --public --port 3000 --json
```

It sleeps when idle and wakes on the next visit.

### Secrets and env vars

```bash
maritime env set my-agent OPENAI_API_KEY=sk-... --reload --json    # secret by default
maritime env import my-agent ./prod.env --reload --json
```

Without `--reload` the change applies on the next boot.

### Schedules

Timers inside a sleeping VM do not fire. Use platform triggers:

```bash
maritime triggers create my-agent --type cron --cron "0 9 * * *" --json
```

### One agent per end user, from a backend

From a backend use the SDK: `npm install maritime-sdk` or
`pip install maritime`, key in `MARITIME_API_KEY`. `endUsers.createAgent(externalId)`
is idempotent. Docs: https://maritime.sh/docs/sdk/end-users.md

From the CLI, for support work and scripts:

```bash
maritime users create user_42 --body-json '{"templateId":"openclaw"}' --json   # their agent, exactly once
maritime users set-policy user_42 --body-json '{"policy":{"llm_spend_cap_cents_per_month":500}}' --json
maritime users token user_42 --body-json '{"scopes":["chat"]}' --json         # eu_ token for their browser
maritime usage get --json        # per agent; group the rows on externalUserId for cost per end user
```

### A persistent desktop for an existing agent (Computers on demand)

One MCP server, one Linux desktop per end user id:

```bash
claude mcp add --transport http maritime-computers https://mcp.maritime.sh/mcp \
  --header "Authorization: Bearer mk_..."
```

Docs: https://maritime.sh/docs/computers.md

## Verify before you finish

1. `maritime status <agent> --json` reports `active` (or `sleeping` after
   idle; both are healthy).
2. `maritime chat <agent> "hello" --json` returns a reply, or for a custom
   container `maritime logs <agent> --json` shows the server listening.
3. Tell the user the agent name, the dashboard URL
   `https://maritime.sh/agents`, what you changed in their repo, and the
   claim URL with its expiry if you deployed with `--claim-later`.

## Inspect and repair

```bash
maritime list --json
maritime info my-agent --json                  # env count, triggers, last deploy
maritime history my-agent --json               # build and deploy attempts with buildLog
maritime exec <agent_id> --body-json '{"command":"ls /data"}' --json | jq -r '.results.stdout'
maritime restart my-agent --json               # also picks up new env vars
maritime delete my-agent --yes --json          # --yes is required non-interactively
```

`maritime exec` takes the full agent ID (no name lookup) and a required
`--body-json` with `command` and optional `detached` and `timeout`. Null or
omitted timeout selects 60 seconds attached or 3,600 seconds detached. Fetch
or cancel a detached run through the REST API:
https://maritime.sh/docs/api#exec
On agents with detached support, disconnecting does not cancel execution.
Do not repeat submission after a lost response without accounting for a command
that may already be running. Older agents support attached exec with combined
output and no execution ID. Detached submission on those agents returns HTTP 501 with
`unsupported: outdated vm. Please use a new agent.` Use a new agent for
detached execution. Restarting an older agent does not add this feature.

`agent_unavailable` in a chat error means the agent is not running:
`maritime start <agent>`, wait a few seconds, retry. A 404 on exec or files
usually means the agent is asleep or errored: start it, do not recreate it.

## Reference

- Contract file: https://maritime.sh/docs/cli/llms.txt
- Setup procedure for agents: https://maritime.sh/agents.md
- Everything: https://maritime.sh/llms.txt (index) and https://maritime.sh/llms-full.txt
- Comparison with every competitor: https://maritime.sh/compare.md
- Block to paste into AGENTS.md or CLAUDE.md: https://maritime.sh/agents-snippet.md
- REST API: https://api.maritime.sh/openapi.json (bearer `mk_` key)
- Any docs page as markdown: append `.md` to its URL, for example
  https://maritime.sh/docs/quickstart.md
