DocsInstall options
Choose how to capture.
Capture runs in the macOS app, which hosts the local capture service. Add the CLI when you are integrating an SDK, coding agent, or automated workflow with it.
Choose an interface#
macOS app
Guided setup, menu-bar service controls, and the complete native capture workspace in one signed application. No terminal is required for normal use.
CLI
The capture command for SDK routing, coding-agent configuration, scripting, and automation against the app's local service.
Install the macOS app#
Download Exalto Capture below. Open the DMG, move Exalto Capture to Applications, then launch it. The app guides first-time setup and runs the local capture service while it is open.
Exalto Capture for Apple silicon
macOS 12 Monterey or later · bundled local service
The app configures capture protection, helps connect a provider or coding tool, runs the local capture service, and renders the capture workspace natively. In Notarized mode, the default, provider credentials stay on your machine and the remote notary never receives them. If you choose Witnessed mode, the notary receives each request, including the credential, to relay and vouch for it.
Install the CLI#
The shell installer supports Apple silicon Macs and x86-64 or ARM64 Linux systems. It selects the complete latest stable Runtime release and checks the archive against its published SHA-256 value. The checksum detects corruption, but is not an independent signature because it shares the archive publisher.
curl -fsSL https://capture.exalto.ai/install.sh | sh
The installer places capture in ~/.local/bin. It is a short-lived REST client for the app's local service, so capture commands work while the app is open.
Build from source#
Use Rust 1.95.0 and the toolchain file in the public runtime repository. That repository contains the protocol, desktop app and its local service, capture server, CLI, generic notary, dashboard, updater, and verification implementation. Hosted accounts, billing, admission policy, and this public website are operated separately.
git clone https://github.com/exalto-ai/capture-runtime.git
cd capture-runtime
cargo install --locked --path crates/capture --bin capture
Install the agent skill#
The CLI bundles portable instructions for finding Traces, sealing with approval, verifying packages, diagnosing operations, and protecting private evidence. Install them for Codex, Claude Code, or both. This command does not contact the local service.
capture skill install --target codex
capture skill install --target claude
capture skill install --target all
Use --skills-dir /path/to/agent/skills for another Agent Skills compatible client. Re-run with --force only after inspecting a different existing skill. Claude Code uses $CLAUDE_CONFIG_DIR/skills when that variable is nonempty and ~/.claude/skills otherwise. Restart Claude Code if its personal skills directory did not exist when the current session started.
Configuration file#
The app's first service start creates an editable config.toml at the standard configuration location. It is written once and never replaced.
| System | Default path |
|---|---|
| macOS | ~/Library/Application Support/ai.exalto.capture/config.toml |
| Linux | ~/.config/ai.exalto.capture/config.toml |
| Windows | %APPDATA%\ai.exalto.capture\config.toml |
Operate the service#
Use the command client#
capture talks to the local service's versioned loopback API. It checks service health and never opens the metadata store or vault directly. Add --json for automation. Raw Trace-list JSON includes stored prompt and output previews, so add --metadata-only before sending structured results to an agent transcript.
capture status
capture traces list --provider openai
capture --json traces list --provider openai --metadata-only
capture traces show trc-example --json
capture open
Connect a hosted account when needed#
Local capture, sealing, and verification do not require an account. Connect one to use account allowances, share a Sealed Trace, or manage the same device from hosted Settings. The rotating device credential is stored only in the local service's credential vault.
capture account connect
capture account show
capture account disconnect
A self-hosted capture server has no browser approval. Create a deployment-specific, least-privilege key in hosted Account settings and inject it into the server through CAPTURE_PLATFORM_API_KEY or the private CAPTURE_PLATFORM_API_KEY_FILE. The complete key is shown once and never belongs in config.toml, logs, or artifacts. Account connection and sharing belong to the app; a server only uses the key for hosted admission.
What configuration controls#
config.toml holds the listener addresses, an optional self-hosted notary endpoint, local storage paths, preview limits, and enabled provider routes. The app keeps captures in SQLite and filesystem storage and refuses server-only settings ([cluster], admin.auth, PostgreSQL, and S3) rather than ignoring them. Provider hostnames and API behavior remain fixed; configuration cannot direct the proxy to an arbitrary upstream host.
Turn Capture requests off in the dashboard or macOS app to keep the same provider proxy URLs while bypassing admission, the remote notary, capture storage, and evidence creation for new requests. In-flight requests keep the mode they started with. Turning capture back on initializes the notary first; if that fails, capture stays off rather than silently falling back.
Local administration and capture protection#
The loopback administration API is available to local processes without credentials, and only the app's own window may call it from a browser context. Run a capture server when administration must require sign-in.
Capture encryption is automatic. During setup, the app protects captures either with a random key stored in the system credential service, such as Keychain on macOS, or with a passphrase you enter each time the app starts.
Understand the capture lifecycle#
Request
The local proxy handles plaintext while the notary participates in the provider TLS connection without seeing application data. In Witnessed mode, the notary instead relays the plaintext exchange and signs a receipt as soon as it ends. Provider response bytes stream back to your agent as they arrive.
Commit
At end-of-stream, the proxy commits encrypted deferred state into one
.llmcapture. It does not perform the expensive final proof before returning control to your workflow.Seal later
Stopping the proxy does not invalidate a committed capture. Retry a failed or interrupted sealing attempt through its Trace; the unchanged capture remains available, though interrupted proof computation starts over.
Connect a provider#
Keep credentials where your SDK or agent already expects them, for example OPENAI_API_KEY in your shell or secret manager. Exalto Capture neither creates nor requires a .env file.
Set the SDK base URL to http://127.0.0.1:8787/openai/v1 and continue using the Responses API.
# ~/.codex/config.toml
model_provider = "capture-openai"
model = "YOUR_RESPONSES_MODEL"
[model_providers.capture-openai]
name = "Exalto Capture · OpenAI API key"
base_url = "http://127.0.0.1:8787/openai/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
supports_websockets = false
This flow is live-tested with Codex CLI. Run codex login status first and confirm that Codex reports a ChatGPT login. Codex owns and refreshes that login; the local service forwards its headers and hides every header value from the Sealed package.
# ~/.codex/config.toml
model_provider = "capture"
[model_providers.capture]
name = "Exalto Capture"
base_url = "http://127.0.0.1:8787/codex"
requires_openai_auth = true
wire_api = "responses"
supports_websockets = false
codex exec --ephemeral --skip-git-repo-check \
'Reply with exactly: hello'
Claude Code can use an Anthropic API key or its saved claude.ai login. An Anthropic API-key run looks like this:
ANTHROPIC_BASE_URL=http://127.0.0.1:8787/anthropic \
claude --bare --no-session-persistence \
-p --model YOUR_MODEL \
'Reply with exactly: hello'
For a claude.ai plan, run claude auth status first. Remove apiKeyHelper and do not set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN.
env -u ANTHROPIC_API_KEY -u ANTHROPIC_AUTH_TOKEN \
ANTHROPIC_BASE_URL=http://127.0.0.1:8787/anthropic \
claude -p 'Reply with exactly: hello'
Use the OpenAI-compatible base URL and keep OPENROUTER_API_KEY in the client environment. The evidence authenticates OpenRouter, not the vendor named in a model slug. Authorization, HTTP-Referer, and X-Title header values are hidden in the Sealed package.
curl http://127.0.0.1:8787/openrouter/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-H "HTTP-Referer: https://example.test" \
-H "X-Title: Exalto example" \
-d '{"model":"YOUR_MODEL","stream":true,"messages":[{"role":"user","content":"Reply with exactly: hello"}]}'
Set the OpenAI-compatible base URL to http://127.0.0.1:8787/deepseek, retain DEEPSEEK_API_KEY in the client environment, and continue using /chat/completions. OpenCode can use the same route.
The first local path segment selects a fixed adapter: /openai, /codex, /anthropic, /deepseek, or /openrouter. Each adapter fixes the upstream hostname and path to an explicit allowlist. The notary, not a caller-supplied URL, resolves and opens the provider connection.
Find local Traces#
Each completed provider interaction keeps its vault-encrypted capture in the selected private artifact store and gains a row in the metadata store. Use the native app, local dashboard, or live administration API.
curl "http://127.0.0.1:8788/v1/traces?query=pricing&provider=openai"
Search treats punctuation as text boundaries rather than raw full-text-search syntax. Hyphenated terms, emphasis marks, multiple words, and double-quoted phrases return matches or an empty list through the normal JSON response.
The service applies state, status, provider, event type, severity, and time filters before returning bounded results. Coding agents should discover the available filters from the live OpenAPI document instead of reimplementing them client-side.
GET /v1/traces?status=notarization_failed&limit=20
GET /v1/activity?severity=error&event_type=notarization_failed&limit=20
A Trace records its provider, request and response model when available, HTTP status, sizes, duration, state, operational status, and retained artifact facts. By default, the first 1,000 characters of the request prompt and output are indexed as plain local text. Header values, cookies, and credentials are never included. You can change the metadata path, disable full-text search, or set either preview limit to 0 in config.toml.