Reference

Detail that the README deliberately leaves out. For the command and flag listing, see cli.md; for the behavioural rules an agent should follow, see the agent skill.

Input leases

Every HTTP input and signal identifies its actor. Non-human actors acquire a lease before acting.

LeaseWho it is forWhat it guarantees
sharedseveral agents each submitting complete chunksthe runtime serializes each request, so bytes from two requests never interleave
exclusiveone automated actor across a multi-step interactionno other automated actor may write until it is released, expires, or a human preempts it
nonea personinput is always accepted, and immediately revokes a non-human exclusive lease

A human may also take an exclusive lease for a longer manual takeover. Leases use monotonic TTL deadlines, can be renewed, and disappear on release, expiry or preemption. Browser input from the stock page is identified as human:local-ui, so opening the window and typing preempts an agent without any further ceremony.

Secret input mode

While a session is in secret input mode it publishes nothing derived from the typed bytes:

Every non-human actor is refused input, signals and leases for the duration.

Any actor may enter secret mode — raising the shield is the safe direction. Only a human actor may leave it, and leaving waits for the session to fall quiet so the echo of what was just typed is not released as publication resumes. Entry and exit are both events, and the stock page marks the state unmistakably.

HTTP API

api serve --mode local (the default) binds 127.0.0.1. --mode lan binds all interfaces for a trusted IPv4 network and publishes this machine’s LAN address. There is no TLS and no Internet exposure built in.

Public for discovery: /health, /openapi.json, and the standalone JSON Schemas under /schemas/. Everything under /v1 requires Authorization: Bearer ... and never accepts a credential in a query string.

Callers can:

Domain responses are AFDATA envelopes and pass through AFDATA redaction on the way out.

The OpenAPI document is committed and drift-tested against the code:

afterminal api export --directory openapi --force

Delivery

Delivery is hosted by Agent-First UI, which owns the browser process and disposable profile for window, the outer page and attention policy for link, and the registry entry for session. The upstream UI credential stays private inside the CLI. --port always names the bearer-protected API, never the delivery.

For link, AFUI applies its global attention.idle_timeout_s and attention.grace_period_s policy, including the warning and the renew action. The terminal page’s once-per-second refresh only keeps its own session list current; it does not choose the URL’s lifetime.

In attach mode (ui --api-url), the running API issues a separate private UI capability. The CLI keeps that capability alive behind the delivery and revokes it when the delivery ends; the server-side idle timeout on it is crash cleanup, not the person-facing lifetime. ui --api-url resolves no frontend locally — the machine serving that runtime decides which page it serves.

Override contract

ui_api_version is 3. A frontend may supply templates/page.html.j2, style.css and assets/**, each independently; a file it does not supply is afterminal’s.

Two things are not the frontend’s:

A frontend afterminal cannot load ends the command with ui_frontend_unusable and opens no window; it is never a quietly substituted built-in page. AFUI_SAFE_MODE=1 ignores every override.

Scope

The runtime has no agent-first-ui dependency and does not know application or task-completion semantics. Higher-level controllers decide what terminal output means.