ACP and SSH reference
All clients connect to one host-local Salaam service. They share session IDs, accepted attempts, approvals, child results and event history. Closing a client detaches it; explicit cancellation and service shutdown are separate commands.
Terminal and SSH
Section titled “Terminal and SSH”Bare sal, sal tui, and sal attach SESSION_ID in a TTY open the Salaam TUI. See controls, themes and recovery. --plain keeps the line interface; redirected/piped attachment remains scriptable. No UI owns a Pi worker.
sal service startsal session create --cwd /absolute/path/to/projectsal attach SESSION_ID# Another terminal may observe or explicitly take control:sal attach SESSION_ID --observesal attach SESSION_ID --takeoverCtrl-C or Ctrl-D detaches the interactive attachment. A hard-killed controller’s lease lasts up to 15 seconds; wait for expiry or use explicit takeover. Approvals can be answered by an observer from the same trusted OS account. CLI text is sanitized for terminal control characters; model text is not executable authorization.
For another computer, install the pinned checkout and CLI on the execution host, configure its provider there and start its service. SSH reaches that same host/account and state directory:
sal remote USER@HOST --remote-bin /absolute/path/to/sal \ --session SESSION_ID --state /absolute/path/to/salaam-statessh USER@HOST 'sal session inspect SESSION_ID --state /absolute/path/to/salaam-state'Use an absolute installed sal path if the remote noninteractive shell does not include its npm bin directory in PATH. Workspace and state paths are on the execution host. Copying a state directory to another computer does not connect to its existing worker. This path uses SSH authentication and no public Salaam listener.
ACP v1 stdio
Section titled “ACP v1 stdio”Configure an ACP client’s agent subprocess command as:
{ "command": "/absolute/path/to/sal", "args": ["acp", "--state", "/absolute/path/to/salaam-state"]}Add --local to the adapter arguments to open your desk session in the editor’s project folder, the same session salaam opens in a terminal there (see Editors). Add --coding instead to create guarded coding sessions in an owned copy. The service must already be running with --coding-root; commands additionally require its proven execution backend. A session/new caller may explicitly select _meta["salaam.dev/coding"]; load/resume retain the saved session’s original authority.
The service must already be running. The adapter uses newline-delimited UTF-8 JSON-RPC on stdin/stdout; diagnostics use stderr. It negotiates protocol version 1. Its tested subset follows the official initialization, session setup, prompt lifecycle, permission and stdio transport contracts, checked on 2026-10-17. ACP v2 draft behavior is not advertised.
| Method | Behavior |
|---|---|
initialize |
Returns version 1, supported capabilities and no separate authentication methods for this local OS-account client |
session/new |
Creates/provisions a Salaam session and returns the same session ID the CLI uses |
session/load |
Loads a session and replays its entire imported active-branch conversation in pages before responding |
session/resume |
Connects to that session without replaying existing conversation messages |
session/prompt |
Accepts text and resource references through durable logical submission IDs; returns after the attempt settles |
session/update |
Sends committed message/tool updates; permission presentation can occur while a tool is waiting |
session/request_permission |
Presents the exact operation, target/value/version, digest and approval revision; offers allow-once/reject-once |
session/cancel |
Explicitly journals cancellation before requesting abort; unknown external outcomes stay unknown |
session/set_mode |
Desk sessions only: review, accept edits, auto or full access (full access confirms first) |
session/set_config_option |
Desk sessions only: the same choice as the mode option; returns every option |
The adapter sends committed transcript chunks and normalized live tool start/finish updates, deduplicating tool identities when the transcript catches up. Volatile token previews remain TUI-only. It advertises no image/audio/embedded-resource prompt capability, additional directories, client terminal/filesystem execution, model selection or dynamic MCP connections. Modes and the /rewind command are offered only for desk sessions. Use mcpServers: []; nonempty server lists are rejected. Resource links become prompt references and do not cause the adapter to fetch arbitrary resources. New/load/resume use an absolute cwd, matching the saved session directory when reconnecting. The checked-in independent client fixture proves this subset; a named editor’s UI is a separate integration observation.
Loading a running session can observe and answer approvals without taking control. Prompting acquires the normal controller lease and fails if another controller owns it. _meta: {"salaam.dev/takeover": true} requests an explicit takeover. Leases renew every five seconds. Losing the ACP process leaves the daemon and current work alive; reconnect to the same session rather than creating another session.
For a retryable logical prompt, provide a fresh UUID once and retain it across retries:
{ "jsonrpc": "2.0", "id": 42, "method": "session/prompt", "params": { "sessionId": "SESSION_ID", "prompt": [{ "type": "text", "text": "Review the staging report" }], "_meta": { "salaam.dev/requestId": "LOGICAL_UUID" } }}The transport request ID 42 is not the logical submission identity. Salaam fsyncs the exact logical input before sending it and retains its acceptance receipt in STATE/acp-requests. Reusing the logical UUID with different text or another session conflicts. Without this metadata, each new prompt request is new logical work. A new load/resume retries unresolved journal records before accepting more work. After an interrupted service attempt, use a new logical UUID and _meta: {"salaam.dev/continuesAttemptId": "INTERRUPTED_ATTEMPT_ID"} with an explicit new instruction; resuming alone never replays the old attempt.
Permission replies are correlated to the exact persisted binding. Malformed, expired or mismatched replies cannot grant execution. Concurrent replies serialize their durable outbox writes. A disconnected approver leaves decisions pending. A cancelled permission response from a controlling client requests explicit session cancellation; it never counts as permission to execute.
Editors
Section titled “Editors”To set up Zed and use your desk session in an editor, see Editors.
Operator attention
Section titled “Operator attention”ACP carries the service’s durable inbox entries in session/update metadata salaam.dev/inbox with a textual attention summary. _salaam/inbox/list accepts an optional pagination offset. _salaam/inbox/ack accepts the exact item ID, expected revision and stable request ID; the source session must already be connected and its controller acquired. Acknowledgement never decides a permission or retries work. Normal operation-bound session/request_permission remains the approval path.
These are Salaam ACP extensions. Inbox acknowledgement does not approve an operation or retry work. See jobs and inbox.
Durable outcomes and cancellation receipts
Section titled “Durable outcomes and cancellation receipts”ACP errors carry a bounded typed failure in data["salaam.dev/failure"] with its
logical prompt, session and attempt IDs where available. Token-limit and refusal
outcomes preserve max_tokens and refusal; partial text does not turn them into
success. Attempts saved before durable outcome verification remain unverified
rather than being replayed automatically.
Clients can advertise _meta["salaam.dev/executionFeatures"] with
{"failures":1,"cancellationReceipts":1,"toolSemantics":1} during initialization.
This namespace is separate from the existing prompt-receipt capability. For an
idempotent cancellation, send session/cancel with
_meta["salaam.dev/cancellationId"] (a UUID) and
_meta["salaam.dev/targetRequestId"] (the original logical prompt ID). The daemon
records the stop before aborting work, including when cancellation arrives before
the prompt itself. Retrying the same cancellation preserves its original target.
Opted-in clients receive durable salaam.dev/cancellationReceipt update metadata.
requested is an accepted stop intent; confirmed requires observed settlement
and reconciled effects; unknown preserves uncertainty about owned resources or
external effects. Loading the same session replays these receipts. Closing an ACP
client detaches; it does not cancel work. Session revocation is a separate boundary.
Tool calls preserve their read/search/edit/delete/execute kind on live and replayed
updates. Locations identify actual guarded workspace files; repository snapshots
do not invent editable source paths.