Prompt an agent remotely.
Send Claude Code or Codex on your box a prompt from your machine or from any script, follow what it does as it happens, and interrupt it. The run lives on the box, not in a terminal, so nothing depends on your laptop staying open.
Prompt the agent
prized prompt --provider claude "fix the failing tests in app/ and run them again"This starts a headless run of Claude Code on the box (claude -p, in your home directory), streams its events to your terminal as they happen, and exits when the agent is done. Nothing runs in a tmux session and nothing is installed on the box beyond three small helper scripts on the first prompt.
| Command | What it does |
|---|---|
prized prompt --provider claude "…" | Run Claude Code on the default box and follow it. --provider codex runs Codex. |
prized prompt box-a7f3 --provider codex --cwd app "…" | Run on a named box, in ~/app (--cwd is relative to your home, or absolute). |
prized prompt --provider claude --model opus --effort high "…" | Pick the model and the reasoning effort (low, medium, high). |
prized prompt --provider claude --continue "…" | Continue the provider's newest session on the box instead of starting a fresh one. |
prized prompt --provider claude --auto "…" | Let the agent edit and run commands without approvals. See Approvals. |
prized prompt --provider claude --detach "…" | Start the run and print its id; follow it later with prized events. |
prized prompt --provider claude --queue "…" | When a run is in progress, queue this prompt behind it instead of refusing. |
cat brief.md | prized prompt --provider claude - | Read the prompt from stdin. |
prized prompt ls | Every run on the box, newest first (at most 50), with its state. |
prized events --follow | Follow the run in progress (or show the newest); --run pr_… picks one, --after N starts after event N. |
prized interrupt | Stop the run in progress (TERM to its process group, KILL after 5 s); --run pr_… stops a specific one. |
- Output: the agent's text plainly, each tool call and result as one dim line, and a last line with the run's verdict and event count.
-vadds the provider's system events. - Exit code: 0 when the run ends cleanly, 1 when the provider reports an error, exits non-zero, or the run was interrupted, 130 on Ctrl-C, which also interrupts the run on the box (
prized events --followleaves the run alone on Ctrl-C). - The prompt travels to the box as a file (
prompt.txt), never on a command line, so it does not show up in the box's process list or shell history. - A suspended box wakes for
prized prompt;prized events,prized prompt lsandprized interruptdo not wake one.
Sign in first
The agent runs as you, on the box, with the sign-in already there. Before the first prompt, hand your credentials over:
prized agents handoff claude codexprized prompt refuses with provider_not_signed_in when the box has no sign-in for the provider (Claude Code: ~/.claude/.credentials.json or CLAUDE_CODE_OAUTH_TOKEN in a login shell; Codex: ~/.codex/auth.json). What travels is in Credentials; the interactive alternative is Agents.
Approvals
By default the agent can edit files but not act freely: Claude Code runs with --permission-mode acceptEdits (commands it wants to run are denied, since a headless run cannot ask you), and Codex runs in its workspace-write sandbox. --auto lifts both (claude --dangerously-skip-permissions, codex --dangerously-bypass-approvals-and-sandbox), which is what a prompt like "run the tests and fix them" needs.
--automeans no approvals at all: the agent runs any command and edits any file your account on the box can, with your credentials and your synced projects in reach, for as long as the run lasts. Use it for work you would let the agent do unattended, and interrupt it when it strays.
Continuity
Every run records the provider's session id as soon as the stream names it. --continue starts the next run with --resume <that id> (Claude Code) or codex exec resume <id> (Codex), so the agent keeps its context: "now also update the docs" works. The newest session of the same provider on the box is the one continued; prized prompt ls --json shows each run's sessionId and, for a continued run, resumedFrom. With no earlier session on the box, --continue refuses (exit 5, no_session_to_continue on the API) rather than quietly starting a fresh run; drop the flag for that.
One run at a time, and a queue
A box runs one prompt at a time. A second prized prompt while one is in progress answers prompt_in_progress; with --queue the text is queued instead and runs as soon as the current run ends, continuing its session. Two commands exist on the box itself for this, so a setup script or any shell there can drive the agent:
queuePrompt "then run the linter and fix what it finds"
stopAgentqueuePrompt appends to the queue (from its arguments, or from stdin with none); stopAgent interrupts the run in progress. Both are installed to ~/.prized/bin on the first prompt, with a line in ~/.profile that puts them on the PATH of login shells. A queued prompt with no run in progress waits for the next prized prompt to finish; an interrupted run does not drain the queue.
A prompt queued with --queue (or queue: true) keeps its own provider, model, effort, working directory and --auto; one queued with queuePrompt inherits them from the run it follows. A queued prompt with --continue continues its provider's newest session as of the moment it runs (nothing to continue is recorded as a failed run, the reason in its stderr). Without --continue, a queued prompt of the same provider as the run it follows continues that run's session (or, when that run never named one, the session it was itself continuing); a different provider starts fresh.
Where a run lives on the box
Everything about a run is a directory on the box, so it survives a pause, rides a snapshot, and can be read with ls and tail -f:
File in ~/.prized/prompts/<run id>/ | Contents |
|---|---|
prompt.txt | The prompt as given. |
meta.json | Provider, model, reasoning effort, and whether --auto was on. |
cmd, next | The provider command line for this run, and the one a continuation uses. |
cwd, pid, started_at, exit | The working directory, the process group id, the start time, the exit code when done. |
events.jsonl | The provider's raw event stream (claude --output-format stream-json, codex exec --json), appended as it happens. |
stderr.log | The provider's stderr. |
session | The provider's session or thread id, once seen. |
resume, parent | For a continued run, the session it resumed; for a queued one, the run it followed. |
interrupted | Present when the run was stopped through prized interrupt or stopAgent. |
~/.prized/prompts/active names the run in progress; ~/.prized/prompts/queue/ holds queued prompts, one directory each (prompt.txt, plus the request's own meta.json, cmd, next and cwd when it was queued from the CLI or the API).
Run directories are never deleted for you.
rm -r ~/.prized/prompts/pr_…on the box when you are done with one.
JSON and JSON Lines
--json on prized prompt prints the started run as one object and does not follow. --jsonl follows and prints one normalized event per line: this is the one command, with prized events --jsonl, that prints more than one JSON document, because a live stream has no end to wait for.
{"seq": 7, "type": "tool_use", "text": "Let me run the suite.", "tool": {"name": "Bash", "input": {"command": "npm test"}}, "raw": {…}}| Field | Meaning |
|---|---|
seq | The event's line number in events.jsonl, from 1. Paging and --after use it; a page holds up to 200 events or 1 MiB, whichever comes first, and always at least one. |
at | The provider's timestamp when the line carries one. |
type | system, assistant, tool_use, tool_result, result, error, or raw for a line the mapping does not know. |
text | The readable content: the agent's text, a command, a tool's output, the final answer, an error (capped at 8 KiB). |
tool | For tool events, {name, input}; Codex's are command_execution, file_change, mcp_tool_call (server/tool), web_search. |
raw | The provider's line as written. |
A run object (prized prompt --json, prized prompt ls --json, prized events --json) has id, provider, model, reasoningEffort, auto, status (running, done, failed, interrupted), exitCode, pid, cwd, startedAt, finishedAt, sessionId, resumedFrom, parent, eventCount, prompt.
The edge API
The same surface is HTTP, for scripts and agents that hold a CLI token and have no prized installed. The token and base URL are found as for running commands:
export PRIZED_TOKEN=dcp_…
EDGE=$(curl -s -H "Authorization: Bearer $PRIZED_TOKEN" https://api.prized.dev/api/v1/me | jq -r .edge.url)| Route | Body or query | Answer |
|---|---|---|
POST /prompts | {provider, prompt, model?, reasoningEffort?, cwd?, continue?, queue?, auto?} | 202 prompt.started: run (as above, status: running), or 202 prompt.queued: queued, active |
GET /prompts | prompt.list: runs[] newest first (at most 50), active (the id in progress, or null) | |
GET /prompts/{runId} | prompt.status: run with the full prompt, stderr (last 4 KiB), stderrTruncated | |
GET /prompts/{runId}/events?after=&limit= | after (a seq, default 0), limit (1 to 1000, default 200; a page also stops at 1 MiB) | prompt.events: run, events[], next, finished; pass next as the following after |
GET /prompts/{runId}/events?follow=1 | or Accept: text/event-stream | Server-Sent Events: event: prompt per event, then event: done with {run, next} when the run has ended |
POST /prompts/{runId}/interrupt | prompt.interrupted: id, wasRunning, signal (TERM, or KILL when TERM was not enough) | |
POST /prompts/interrupt | The same, for the run in progress |
Every route is under $EDGE/v1/box/{box}/ with the token as the bearer. POST /prompts wakes a suspended box; the others answer box_not_running.
# start a run and follow it as SSE
curl -s -X POST "$EDGE/v1/box/box-a7f3/prompts" -H "Authorization: Bearer $PRIZED_TOKEN" -H "Content-Type: application/json" -d '{"provider":"claude","prompt":"fix the failing tests","cwd":"app"}'
curl -sN "$EDGE/v1/box/box-a7f3/prompts/pr_3f9c0a1b2d4e/events" -H "Authorization: Bearer $PRIZED_TOKEN" -H "Accept: text/event-stream"
# or page through the events, then continue the conversation
curl -s "$EDGE/v1/box/box-a7f3/prompts/pr_3f9c0a1b2d4e/events?after=0&limit=200" -H "Authorization: Bearer $PRIZED_TOKEN" | jq '.events[] | select(.type=="assistant") | .text'
curl -s -X POST "$EDGE/v1/box/box-a7f3/prompts" -H "Authorization: Bearer $PRIZED_TOKEN" -H "Content-Type: application/json" -d '{"provider":"claude","prompt":"now update the docs","continue":true}'
# stop whatever is running
curl -s -X POST "$EDGE/v1/box/box-a7f3/prompts/interrupt" -H "Authorization: Bearer $PRIZED_TOKEN"Errors
A failed request answers {"ok": false, "error": {"code", "message"}}. On top of the shared codes (unauthorized, not_found, box_not_running, invalid_path, payload_too_large, rate_limited, box_unreachable, exec_failed), these routes add:
| HTTP | error.code | Meaning |
|---|---|---|
| 400 | invalid_provider | provider is not claude or codex. |
| 400 | prompt_required | prompt is missing or blank. |
| 400 | invalid_request | A bad model shape, reasoningEffort outside low/medium/high, a newline in cwd, bad JSON. |
| 409 | prompt_in_progress | A run is in progress; the message names it. Queue behind it, or interrupt it. |
| 409 | provider_not_signed_in | The provider has no sign-in on the box; run prized agents handoff <provider>. |
| 409 | provider_not_installed | The provider's CLI is not on the box's login PATH. |
| 409 | no_session_to_continue | continue: true with no earlier run of the provider that recorded a session. |
From the CLI these are exit 6 (CONFLICT) for a run in progress and exit 5 (CHECK_FAILED) with the hint for the rest.
Limits
| What | Limit |
|---|---|
| Runs in progress per box | 1 (others queue or are refused) |
| Prompt size | 512 KiB |
| Events per page | 200 by default, 1000 at most, or 1 MiB, whichever first (one event of any size is always delivered; a single event over 32 MiB cannot be) |
| Runs listed | 50, newest first (older directories stay on the box) |
Event text | 8 KiB (the raw line is whole) |
| Requests per token, per box | As for the edge API |
Compared with prized agents run
prized agents run starts the agent interactively in a tmux session you attach to: it asks you for approvals, you type into it, and it stays open. prized prompt is the headless form: one prompt in, a stream of events out, a verdict at the end, and an API for scripts. Both use the same sign-in on the box, and both keep working when your laptop is closed.
Something unclear or out of date?
Agents
Start a coding agent, close the laptop, and let it work. An agent is an ordinary process on a machine you already pay for, so nothing it does is metered.
Codex remote
Add your box as an SSH host in the ChatGPT desktop app and Codex runs its tasks on the box, with every edit syncing back to your Mac as it lands. One command sets the connection up.