# Continuous execution

Run recoverable conversations, host persistent work, and attach clients with zot continuous.

`zot continuous` is zot's experimental persistent execution layer. It records model requests and tool calls before and after execution so interrupted work can recover from its last committed boundary. Ordinary interactive, print, JSON, and RPC workflows are unchanged.

Use it when a conversation should outlive its terminal, multiple clients should share the same history, or a job needs explicit recovery after a restart. Unlike ordinary session transcripts, the continuous store is the authority for queued prompts, execution state, approvals, and results.

> **Experimental**
>
> Store formats, Go APIs, and the host protocol are provisional. Use a zot build that includes `zot continuous`, check `zot continuous --help`, and back up stores before upgrading. Recovery is not a guarantee of exactly-once external effects. An interrupted command may already have changed files or contacted another service.

## Run without a daemon

```shell
zot continuous run "summarize the README" --store ./continuous-store --tools read,glob
zot continuous run "now list every TODO" --store ./continuous-store --tools read,glob
zot continuous run --resume --store ./continuous-store --tools read,glob
```

`run` submits a prompt to the workspace's root conversation, executes its work, and prints the final answer. Reusing the store and workspace continues the same conversation. `--resume` continues interrupted work without submitting another prompt. Use `--workspace <id>` to select an explicit workspace identity and `--json` to stream JSON-line events.

Ordinary engine flags such as `--provider`, `--model`, `--reasoning`, `--tools`, `--cwd`, and `--ext` configure execution. Provider credentials are required for model requests, just as in ordinary zot. Session flags such as `--continue` and `--session`, and mode flags such as `--print`, do not apply here.

For integrations that may retry a submission, supply a stable `--request-id`:

```shell
zot continuous run "review the latest changes" --store ./continuous-store --workspace main --request-id review-001 --tools read,glob
```

Retrying with the same request ID returns the original submission instead of admitting another prompt while its deduplication record is retained. Use a new ID for new work. Deduplication does not make arbitrary tool effects idempotent.

## Host work independently of clients

Start the host in one terminal:

```shell
zot continuous serve --store ./continuous-store --tools read,glob
```

Submit from another terminal:

```shell
zot continuous attach "summarize the README" --socket ./continuous-store/host.sock --workspace main
zot continuous attach --follow --socket ./continuous-store/host.sock --workspace main
```

`serve` owns the store, recovers interrupted runs according to policy, and executes queued work across conversations. It holds the provider credentials and tool configuration. `attach` connects to the host, submits an optional prompt, waits for its answer, and exits. `--follow` keeps streaming committed entries until interrupted. `--json` emits JSON-line output.

Closing or interrupting a client only detaches it, it does not cancel admitted host work. Interrupting the host stops serving and leaves interrupted work recoverable.

The default local endpoint is `<store>/host.sock`, a mode `0600` Unix socket on macOS and Linux. On Windows, that path identifies a private named pipe derived from the absolute path. The same `--socket` syntax works on both. Use `--socket <path>` on `serve` to choose a different endpoint.

## Attach the interactive TUI

```shell
zot --continuous ./continuous-store/host.sock --continuous-workspace main
```

The status bar identifies the attached host. Prompts go to the host, and committed history, partial assistant text, tool progress, and waiting states appear in the TUI. Multiple views of the same workspace receive each other's updates even while idle. Closing the TUI detaches without cancelling host work.

The host store replaces local session persistence. New workspace roots use the host's provider, model, and reasoning defaults. Explicit client `--provider`, `--model`, or `--reasoning` selections can configure a new root, but opening an existing root does not replace its configuration. The CLI host supports one provider at a time, with model overrides within that provider.

A dropped watch reloads committed history and resumes automatically. New TUI prompts wait until the history snapshot and replacement watch are restored, so a fast answer is not mistaken for historical context. A disconnected host connection is not automatically redialed, reconnect the TUI to resume. The initial view loads the newest history page, not necessarily the entire conversation.

Go integrations using `AttachedDriver` replay missed committed tool results and assistant messages before reporting completion, even if the submission settled while its watch was disconnected. If those commits are no longer retained, the driver restores a fresh transcript snapshot instead of replaying the individual events.

Compaction belongs to the host. Local `/compact` is unavailable while attached, manual compaction uses the host protocol's `conversation.compact` method. Attached `/swarm` agents run as owned conversations on the host rather than local agent subprocesses.

## Send files and images

CLI clients can repeat `--file`:

```shell
zot continuous attach "review these files" --socket ./continuous-store/host.sock --workspace main --file ./notes.txt --file ./screenshot.png
```

The TUI can send explicitly selected files and clipboard images. The client reads them and transfers their bytes, so the host does not need access to the client's filesystem. Attachments provide prompt context, not workspace uploads. Directory references and ordinary paths in prose do not transfer directory trees or implicitly read files.

A submission accepts up to 16 attachments and 1 MiB of combined decoded file and image bytes. Supported content is UTF-8 text plus PNG, JPEG, GIF, and WebP images. Unsupported binary files and mismatched image types are rejected. The selected model must support vision to interpret images. Attachment-aware clients refuse transfers to older hosts that do not advertise support.

## Recovery and interruption

Inspect interrupted work while the host is stopped:

```shell
zot continuous recover --dry-run --store ./continuous-store
zot continuous run --resume --store ./continuous-store --tools read,glob
```

Recovery follows each tool's stored replay contract and rechecks authorization. Read-only tools such as `read` and `glob` can be replayed. Unsafe tools such as `bash`, `write`, and `edit` are not blindly repeated after an unknown outcome. Idempotent tools require receiver-enforced operation keys, and reconcilable tools must establish whether an effect completed before execution can resume.

The scheduler collects finished invocations and checks for follow-up task phases before reporting idle. Recovery does not stop between committed phases just because a handler finished. Work waiting for approval or blocked on an unresolved dependency still needs that condition resolved before it can continue.

Choose startup recovery policy on the host:

| Flag | Behavior |
| --- | --- |
| `--recover safe` | Default. Resume automatic recovery actions and leave actions requiring inspection blocked. |
| `--recover all` | Also proceed by reporting interrupted unsafe calls as errors, not by repeating them. |
| `--recover none` | Leave interrupted work waiting for an explicit recovery decision. |

A model request may be sent again after interruption, and the provider may have charged for the earlier attempt. An unsafe tool may have acted before its result was committed. Inspect the actual files or external service before deciding what to do next.

## Inspect work and decide approvals

Store-management commands operate without provider credentials. They acquire the store's exclusive writer lock, so stop `serve` or any active `run` before using them against that store. Connected integrations can inspect a live host through its protocol instead.

```shell
zot continuous status --store ./continuous-store
zot continuous conversations --store ./continuous-store --limit 100
zot continuous tasks <conversation-id> --store ./continuous-store
zot continuous inspect <task-id> --store ./continuous-store
zot continuous usage <conversation-id> --store ./continuous-store
zot continuous approvals <conversation-id> --store ./continuous-store
zot continuous decide <approval-id> --allow --scope call --reason "reviewed" --store ./continuous-store
zot continuous abort <conversation-id> --store ./continuous-store
```

Use IDs returned by the listings, not the workspace name. Pending approvals survive restarts. `decide` records an allow or deny decision, and the next execution step continues the parked run. `abort` records abort intent rather than promising to undo an effect. Use `--include-background` when aborting a task tree should include background work.

Status and conversation listings emit JSON. `--after <id>` continues a paginated listing. `search`, `budget`, `prompts`, `outbox`, and `retain` provide additional inspection and management, see `zot continuous --help`. Retention removes auxiliary records, it does not physically erase journal history or reclaim its log bytes.

## Choose a store backend

The journal backend is the default. Choose SQLite when creating a store:

```shell
zot continuous serve --store ./sqlite-store --backend sqlite --tools read,glob
```

Both backends use local exclusive writer fencing and keep committed history. SQLite runs through an embedded WebAssembly runtime, with no system SQLite library or C toolchain requirement. Existing stores are detected from their files. `--backend` is accepted by `run`, `serve`, and `import`, and must match an existing store.

Strict durability is the default for writes. The journal backend requires explicit `--durability process` on Windows, there is no automatic downgrade:

```powershell
zot continuous serve --store ./continuous-store --durability process --tools read,glob
```

Process durability is not a promise that the newest acknowledged writes survive power loss. Use local filesystems, network filesystems are unsupported. Keep the store private, it contains conversation and tool data.

## Back up, restore, and transfer history

The backup CLI is journal-only. Stop the writer before backing up:

```shell
zot continuous backup ./history.zotbackup --store ./continuous-store
zot continuous verify-backup ./history.zotbackup
zot continuous restore ./history.zotbackup --store ./restored-store
zot continuous verify --store ./restored-store
```

Backups preserve the complete committed journal prefix, not just a transcript projection. Archives must be outside the source store and must not already exist. Restore requires a new directory. Destination parents must exist. Archives are private data, not encrypted or authenticated packages, and referenced external artifacts are not bundled. Interrupted processes may leave incomplete destinations, verify them before use.

On Windows, add `--durability process` to journal `backup` and `restore`. `verify` and `verify-backup` are read-only and reject `--durability`.

For an open store, Go integrations can call `(*journal.Store).Backup(ctx, archive, opts)` or `(*sqlite.Store).Backup(ctx, destination)` without stopping the writer. SQLite's online backup creates a consistent database snapshot at a new filesystem path, not a SQLite URI. It reserves a mode `0600` file before copying and refuses existing destinations. These APIs do not add SQLite support to the backup CLI. Never copy a live SQLite database file as a substitute for an online backup.

Import and export bridge ordinary session transcripts:

```shell
zot continuous import ./old-session.jsonl --store ./continuous-store
zot continuous export <conversation-id> --store ./continuous-store --format session --output ./projection.zotsession
```

Import is explicit and bounded to 4 MiB and 10000 rows. Export is a snapshot-consistent projection, not a full store backup. Original session files and exported projections are not recovery authorities after import.

## Remote access and authorization

A local socket without a token file grants admin access to connected clients. Restrict access to trusted processes. TCP listeners require a token file, and non-loopback listeners also require TLS:

```shell
zot continuous serve --store ./continuous-store --listen 0.0.0.0:7443 --token-file ./host-tokens.txt --tls-cert ./server.pem --tls-key ./server-key.pem --tools read,glob
zot continuous attach "summarize the README" --address zot.example.com:7443 --tls-ca ./ca.pem --token-file ./client-token.txt --workspace main
```

The host token file contains one `<token> <role>` pair per line. Roles are `read`, `submit`, `approve`, and `admin`. Tokens must be at least 16 characters, use randomly generated secrets rather than example values. On Unix, the token file must not be accessible to group or other users. A client token file supplies its token as the first whitespace-separated value.

TLS uses a minimum of version 1.3. `--tls-client-ca` on the host optionally requires client certificates in addition to tokens. Loopback TCP may be plaintext, but still requires tokens. Do not expose an unauthenticated endpoint or treat a workspace ID as an authorization boundary.

## Repository-scoped workers

```shell
zot continuous worker --root project=./project --root library=./library --ledger ./worker-ledger.jsonl --environment desktop
```

`worker` serves the remote tool protocol as newline-delimited JSON on stdin/stdout. It exposes `read`, `write`, `edit`, `glob`, and `bash`. Each tool call carries `{repo, args}`, where `repo` names a shared root and `args` contains the ordinary tool arguments. Unknown repositories are refused. Optional `--token` requires a matching hello handshake. `--ledger` persists operation lookup state across restarts.

This is a worker endpoint for a host integration, not a model-running daemon or automatic worker discovery. Go hosts can connect through `WorkerClient` and register `RemoteTool` instances. A lost connection leaves an unknown outcome until lookup or reconciliation establishes what happened. The reference worker does not schedule work across machines.

EOF or interruption closes the worker's streams and stops serving. File tools check paths against the selected root. Bash jail checks are best-effort accident prevention, not a security boundary. Only connect trusted hosts, and protect any relay or network transport separately.
