ForkTTY is still alpha, but agents and scripts need to know which socket calls are safe to build on. This page is the stability map for the local newline-delimited JSON-RPC socket documented in SPEC.md.
The source of truth for the advertised method set is
crates/forktty-socket/src/methods.rs; this document classifies that public
surface.
| Tier | Contract |
|---|---|
| Stable-for-alpha | Method name, required parameters, response field meaning, and error code intent should not break within an alpha line without a changelog entry and migration note. New optional fields may be added. Treat human-readable error text as diagnostic, not stable API. |
| Alpha | Public and supported, but the shape may still change between alpha releases as the feature hardens. Changes must be documented. |
| Source-only / experimental | Available only in explicit source builds or behind feature flags. Do not rely on it for release artifacts. |
| Internal | Not part of the public automation contract even if it exists in code. |
Use these first for scripts, hooks, and terminal automation:
| Area | Methods |
|---|---|
| Discovery | system.ping, system.identify, system.capabilities, system.top |
| Context | context.snapshot |
| Workspace | workspace.list, workspace.create, workspace.create_ssh, workspace.select, workspace.close |
| Surface | surface.list, surface.read_text, surface.capture_tail, surface.send_text, surface.split, surface.focus, surface.close |
| Pane tabs | pane.new_tab, pane.select_tab |
| Worktree reads | worktree.list, worktree.status |
| Notifications | notification.create, notification.list, notification.clear |
| Agent lifecycle | agent.list, agent.health, agent.resume |
| Status and logs | status.summary, metadata.set_status, metadata.list_status, metadata.clear_status, metadata.set_progress, metadata.list_progress, metadata.clear_progress, metadata.log, metadata.list_logs, metadata.clear_logs |
| Project actions | project.action.list, project.action.run |
| Topology and remotes | topology.tree, remote.list, remote.status |
These are public, tested, and user-facing, but still evolving:
| Area | Methods |
|---|---|
| Worktree mutation | worktree.create, worktree.attach, worktree.remove, worktree.merge |
| Events | events.subscribe |
| Agent lifecycle maintenance | agent.hibernate, agent.reclaim.plan, agent.reclaim |
Worktree Create and Attach are idempotent for an exact
(worktree_name, canonical_worktree_path) identity: a retry selects the
existing workspace, returns the same workspace ID, and allocates no new modeled
surface.
Same-named worktrees at different canonical paths are different identities.
Within one running ForkTTY process, these mutations share the same exclusive
transaction with GTK worktree actions and retain it through commit or complete
rollback; this is process-local coordination, not a cross-process or
distributed Git lock. Remove quiesces the exact target by suppressing
controller auto-spawn while its terminals close, and keeps that suppression
through model commit or the complete rollback restoration attempt. Terminal
respawn during rollback can itself fail; ForkTTY then records a blocking
terminal error status before releasing suppression.
- Normal JSON-RPC response lines are compact-encoded and capped at 64 MiB,
including the newline. If a result would exceed the cap, ForkTTY returns a
compact
response_too_largeerror with the original request id. notification.listreturns one oldest-to-newest page.limitdefaults to 200 and accepts 1–200; optionalbefore_idis an exclusive retained-item cursor. With no cursor, the newest page is returned. Updated notifications move to the newest page while preserving their id.- Notification create/list responses and
context.snapshotshare the same projection. Terminal metadata is retained except for binaryterminal_metadata.icon_data; context snapshots independently cap their notification projection to the newest 100 matching items while risk checks still inspect the full matching set. Hook prompt correlation remains private runtime state and does not add fields to this projection. Accepted permission/elicitation results mark only the matching in-app history read and close its desktop notification; providers without a result correlation id resolve only the newest compatible older prompt. Stale events are inert, and session cleanup or target removal clears affected correlations while preserving unrelated unread attention. - Remote rows set
connectedfrom backend readiness, not runtime inventory presence. Diagnostic runtime fields such aspid, dimensions, andshellmay remain populated whileconnectedis false. This is local terminal-I/O readiness, not an independent SSH heartbeat, network probe, or authentication check.
- Official clients and startup collision checks use one deadline-bounded
nonblocking AF_UNIX connector. A full Linux accept backlog (
EAGAIN) retries with a fresh descriptor until the deadline; timeout means occupied/foreign, never stale, and does not replace or unlink the existing socket inode. - A successful bounded connection is returned in blocking mode before normal JSON-RPC or probe reads and writes begin.
- GTK close first stops new dispatch while keeping the UI alive, then drains admitted requests and waits for the socket runtime to drop. Only afterward does ForkTTY snapshot scrollback, synchronize live cwd values, save the session, clean PTY persistence when configured, and perform the final close.
Browser methods are source-only behind the browser feature and are not shipped
in AppImage or Debian release artifacts:
browser.open, browser.navigate, browser.snapshot, browser.click,
browser.fill, browser.back, browser.forward, browser.reload,
browser.profile.list, browser.profile.create, browser.profile.delete,
browser.history.list, browser.history.search, browser.history.clear,
browser.bookmark.add, browser.bookmark.list, browser.bookmark.remove.
The terminal-core release removes the former router, task strategy, team,
workflow, feed, MCP, and managed-skill methods. Calls now return
method_not_found, and the matching CLI commands are no longer routed.
Older releases may have registered forktty mcp in Codex, Claude Code, or
Antigravity and installed the forktty-agent-orchestration skill. ForkTTY does
not rewrite external agent configuration during startup. Before upgrading, use
the older binary's forktty mcp remove --dry-run, legacy
forktty mcp remove gemini --dry-run, and forktty skills remove --dry-run,
then apply those removal commands. The former skill remover leaves marker-owned
forktty-agent-orchestration.bak-* sibling directories, which must also be
removed after inspecting their SKILL.md without following symlinks.
If the older binary is unavailable, back up the affected files and remove only entries carrying ForkTTY's ownership marker:
- Codex:
[mcp_servers.forktty]in$CODEX_HOME/config.tomlor~/.codex/config.tomlonly whenenv.FORKTTY_MCP_MANAGED = "forktty". - Claude Code:
mcpServers.forkttyin~/.claude.jsononly whenenv.FORKTTY_MCP_MANAGEDisforktty. - Antigravity: the same JSON check in
~/.gemini/config/mcp_config.json. - Legacy Gemini: the same JSON check in
~/.gemini/settings.json. - Agent Skills and Claude Code: the active
forktty-agent-orchestrationdirectory and siblingforktty-agent-orchestration.bak-*directories under~/.agents/skills/or${CLAUDE_CONFIG_DIR:-~/.claude}/skills/, only when each candidate is a real directory rather than a symlink and itsSKILL.mdcontains<!-- forktty-managed-agent-skill -->.
Leave unmarked entries and directories untouched; they are user-managed.
- Additive response fields are allowed in any tier.
- Removing a method, renaming a method, changing required parameters, or changing
the meaning of a stable-for-alpha response field requires a
CHANGELOG.mdentry and a SPEC update. - CLI wrappers,
SPEC.md, this file, andforktty-siteagent context should move together when a public method's behavior changes. - Prefer
system.identifybefore mutating calls so stale workspace or surface ids are detected early. - Prefer
context.snapshotfor agent monitoring andsurface.read_text/surface.capture_tailonly when terminal text is actually needed. context.snapshotreturns at most the newest 100 matching notifications and omits binary terminal icon data; risk flags still inspect the full matching set.