Server & task queue
hipmmcode serve runs a direct-connect HTTP + WebSocket server, so remote clients — web apps, phones, other machines — can drive full agent sessions. It speaks the same stream-json control protocol as the SDK host, plus a fire-and-forget async task queue.
hipmmcode serve # 127.0.0.1:7777, auto-generated auth token
hipmmcode serve --port 9000 --auth-token S3CR3T
hipmmcode serve --host 0.0.0.0 --port 7777 # non-loopback binds print a security warningOn start it writes a discovery lockfile to ~/.hipmmcode/direct-connect.json (host, port, token) so local clients can find it. All requests authenticate with Authorization: Bearer <token>.
Interactive sessions (WebSocket)
POST /sessions → { "session_id": "…", "workspace_id": "…", "ws_url": "…" }
GET /sessions/{id} → session status + work_dir + workspace_id
DELETE /sessions/{id} → remove the session and terminate every interactive terminal it owns
WS /sessions/{id}/subscribe → bidirectional stream-json
POST /threads/{id}/review → enqueue a read-only structured review
GET /threads/{id} → Thread summary
GET /threads/{id}/items → cursor-paginated Turn/Item events
GET /health → server status + task countsOver the WebSocket you send user turns and control requests (set_model, interrupt, permission responses) and receive streamed events — text deltas, tool cards, results — exactly like the stdio SDK host. Disconnect and reconnect-resume the same session. One thread has one execution owner: a concurrent second subscription receives 409, and detached turns targeting the same tenant/workspace/thread run FIFO.
POST /threads/{id}/review accepts optional focus, provider, model, max_turns, and max_budget_usd. It exposes only read-oriented tools; mutating Bash commands reach the normal approval bridge and fail closed. The resulting reviewOutput item contains normalized findings with priority, confidence, absolute file path, and line range.
Each session gets a workspace_id that scopes its long-lived resources (notably exec_command PTY sessions). Idle-swept, deleted, and finished sessions have their PTYs terminated automatically; DELETE /sessions/{id} reports how many were killed.
Async task queue
Submit work, hang up, collect the result later — built for "send a task from your phone, read the answer whenever":
# submit (connection can drop immediately)
curl -X POST http://127.0.0.1:7777/tasks \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"prompt": "audit the repo for TODOs and write a report to todos.md"}'
# → { "task_id": "task_…", "status": "queued" }
# check progress / result whenever
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:7777/tasks/task_…
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:7777/tasks # list allSubmission fields
| Field | Description |
|---|---|
prompt (required) | The task |
work_dir | Working directory for the run |
provider / model | Override the channel/model for this task |
max_turns | Cap tool-use iterations |
max_budget_usd | Hard spend ceiling for the task |
webhook | URL that receives a POST with the full task record on completion |
dangerously_skip_permissions | Allow mutating tools unattended (see below) |
Task record
GET /tasks/{id} returns: status (queued → running → completed / error / interrupted), result (final text), is_error, live progress (steps — completed tool calls — plus last_activity and its timestamp), created_at / finished_at, and the effective settings.
Semantics worth knowing
- Detached — the task runs in the background regardless of your connection.
- Persistent — tasks are saved to disk and reloaded on server restart (7-day retention). A task caught mid-run by a restart reloads as
interrupted. - Fail-closed permissions — with nobody attached, any permission prompt is denied by default; the denial is visible in the task record. Pass
dangerously_skip_permissions: truefor autonomous tool use — only on servers you trust end-to-end. - Webhook — on completion the full record is POSTed to your
webhook, so you don't need to poll.
Membership gateway
Share one upstream credential (e.g. Codex or xAI OAuth on the host) with teammates who each get their own quota, without handing out the raw API key:
# Host: start serve with membership endpoints enabled
hipmmcode serve --gateway --auth-token S3CR3T
# or pure gateway (membership only):
hipmmcode serve --gateway-only
# Admin: create a member + one-time join code
hipmmcode member create --name alice --quota 1000000
# print activation code → give to Alice
# Member machine:
hipmmcode join <activation-code>
# then use hipmmcode as usual; requests are signed to the gatewayUseful admin subcommands: member list, member show, member set-quota, member disable, member delete. Members can inspect their own usage with member self-service commands after join. See hipmmcode member --help / hipmmcode join --help for the full surface.
The Claude subscription bridge (anthropic-claude) is not available as a gateway upstream — only channels that expose a reusable HTTP credential.
Security notes
- Default bind is loopback. To expose it, prefer an SSH tunnel or a reverse proxy with TLS; a raw
--host 0.0.0.0bind means anyone with the token can run shell commands as your user. - The auth token gates every route. Rotate by restarting with a new
--auth-token. - Workspace containment: set
HIPMMCODE_WORKSPACE_ROOT=/pathto reject any requestedcwdoutside that directory (canonicalized — symlink escapes are rejected too). Unset, the historical arbitrary-cwd behavior is preserved for local use. - Multi-tenant identity:
HIPMMCODE_TENANT_IDlabels every resource the server creates (defaults tolocal-server); interactive terminal sessions are only reachable by their owning tenant/workspace/session, and quota limits apply per level (HIPMMCODE_PTY_PER_AGENT/_PER_THREAD/_PER_WORKSPACE/_PER_TENANT/HIPMMCODE_MAX_PTY_SESSIONS). - Scoped persistence: app events are stored through
ThreadStore; the local implementation keys platform files by tenant/workspace/thread and uses an advisory lock for cross-process monotonic sequences. Legacy unscoped JSONL remains readable. - Encrypted credentials: set a high-entropy
HIPMMCODE_MASTER_KEY(32+ characters) to store MCP OAuth credentials in the encrypted scoped backend and migrate an existing owner-only JSON token on first read.