A remote SSH agent that lets autonomous agents securely authenticate using keys that never leave your devices.
The SSH private keys stay encrypted on your phone, unlocked with a WebAuthn
passkey. A local daemon exposes an SSH_AUTH_SOCK, and when something needs to
sign, it wakes your phone with a push notification to authorize the request.
[!WARNING] Early work in progress.
Run the app and an isolated development daemon:
pnpm dev
The daemon listens on 127.0.0.1:19345, while Vite listens on
127.0.0.1:5173. Use an HTTPS reverse proxy to open the Vite server on the
phone, add it to the Home Screen, and launch it from there.
Development pairing state and the VAPID key persist in the ignored .dev
directory. Press Ctrl-C to stop both processes.
Install the pinned toolchain and JavaScript dependencies, then build the frontend and release server in the required order:
mise install
pnpm install --frozen-lockfile
pnpm build:production
The resulting target/release/agent-witness binary contains the complete Vite
application and does not need packages/app/dist at runtime. Production
deployments should terminate TLS in front of its HTTP listener.
Configure separate Sentry projects for the daemon and browser application. The server embeds the public frontend DSN in the HTML response at runtime, so the frontend build contains no environment-specific configuration:
sentry_backend_dsn = "https://public@example.ingest.sentry.io/1"
sentry_frontend_dsn = "https://public@example.ingest.sentry.io/2"
Both SDKs send errors, structured logs, and traces when their DSN is configured.
Tracing uses a 1.0 sample rate.
Pairing remains process-local when state_path is omitted. Configure a state
file to retain the server identity and paired client across restarts:
state_path = "/var/lib/agent-witness/state.json"
control_socket = "/run/agent-witness/control.sock"
control_socket_mode = "0600"
The state file is atomically replaced with mode 0600 and contains only the
client credential hash. Clear the current pairing through the running daemon:
agent-witness pairing clear
70 commits
Hacker News (1)
TypeScript
51.6%
Rust
46.1%
CSS
1.7%
A remote SSH agent that lets autonomous agents securely authenticate using keys that never leave your devices.
The SSH private keys stay encrypted on your phone, unlocked with a WebAuthn
passkey. A local daemon exposes an SSH_AUTH_SOCK, and when something needs to
sign, it wakes your phone with a push notification to authorize the request.
[!WARNING] Early work in progress.
Run the app and an isolated development daemon:
pnpm dev
The daemon listens on 127.0.0.1:19345, while Vite listens on
127.0.0.1:5173. Use an HTTPS reverse proxy to open the Vite server on the
phone, add it to the Home Screen, and launch it from there.
Development pairing state and the VAPID key persist in the ignored .dev
directory. Press Ctrl-C to stop both processes.
Install the pinned toolchain and JavaScript dependencies, then build the frontend and release server in the required order:
mise install
pnpm install --frozen-lockfile
pnpm build:production
The resulting target/release/agent-witness binary contains the complete Vite
application and does not need packages/app/dist at runtime. Production
deployments should terminate TLS in front of its HTTP listener.
Configure separate Sentry projects for the daemon and browser application. The server embeds the public frontend DSN in the HTML response at runtime, so the frontend build contains no environment-specific configuration:
sentry_backend_dsn = "https://public@example.ingest.sentry.io/1"
sentry_frontend_dsn = "https://public@example.ingest.sentry.io/2"
Both SDKs send errors, structured logs, and traces when their DSN is configured.
Tracing uses a 1.0 sample rate.
Pairing remains process-local when state_path is omitted. Configure a state
file to retain the server identity and paired client across restarts:
state_path = "/var/lib/agent-witness/state.json"
control_socket = "/run/agent-witness/control.sock"
control_socket_mode = "0600"
The state file is atomically replaced with mode 0600 and contains only the
client credential hash. Clear the current pairing through the running daemon:
agent-witness pairing clear
Hacker News (1)
70 commits
TypeScript
51.6%
Rust
46.1%
CSS
1.7%