feat(cli,nodejs): add daemon process with ocap daemon CLI#843
Open
feat(cli,nodejs): add daemon process with ocap daemon CLI#843
Conversation
…tils Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…patch The system console vat manages a REPL loop over an IO channel, dispatching CLI commands (help, status, launch, terminate, subclusters, listRefs, revoke) and managing refs in persistent baggage. Refs use a monotonic counter (d-1, d-2, ...) since crypto.randomUUID() is unavailable under SES lockdown. Cross-vat errors are serialized via JSON.stringify fallback for reliable error reporting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add startDaemon() which boots a kernel with a system console vat listening on a UNIX domain socket IO channel. The kernel process IS the daemon — no separate HTTP server. Includes socket channel fix to block reads when no client is connected, flush-daemon utility, and e2e tests for the full daemon stack protocol. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the 'ok' CLI that communicates with the kernel daemon over a UNIX domain socket using newline-delimited JSON. Uses yargs for command definitions with --help support on all commands. Supports three input modes: file arg (ok file.ocap method), stdin redirect (ok launch < config.json), and pipe (cat config.json | ok launch). Relative bundleSpec paths in launch configs are resolved to file:// URLs against CWD. Ref results are output as .ocap files when stdout is not a TTY. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement a two-tier access model: unauthenticated daemon-tier commands (help, status) and privileged ref-based dispatch via .ocap capability files. Self-ref dispatch bypasses kernel round-trip for the console root object. Fix kref leaks, improve socket channel reliability with stale connection detection and client-side retry.
…rect JSON-RPC daemon
Replace the system-console-vat architecture with direct JSON-RPC over Unix
socket. The old flow routed CLI commands through IOChannels and a REPL vat;
the new flow sends JSON-RPC requests directly to kernel RPC handlers.
- Add RPC socket server and daemon lifecycle to @ocap/nodejs under ./daemon
export path, reusing RpcService and rpcHandlers from the kernel
- Simplify CLI: ok.ts sends JSON-RPC commands, daemon-entry.ts boots kernel
and starts the daemon socket server
- Move libp2p relay from @ocap/cli to @metamask/kernel-utils under ./libp2p
export path, breaking the cli<->nodejs dependency cycle
- Remove @ocap/cli devDep from packages that only used the binary; use
yarn run -T ocap for workspace-wide binary access
- Delete system-console-vat and related IOChannel/ref plumbing
- makeKernel now returns { kernel, kernelDatabase }
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Preserve kernel state across restarts (resetStorage: false) - Clean up stale socket files before listen - Add socket-based shutdown RPC with PID+SIGTERM fallback - Stop daemon before flushing state in begone handler - Narrow sendCommand retry to ECONNREFUSED/ECONNRESET only - Replace bare socket probe with getStatus RPC ping - Use JsonRpcResponse from @metamask/utils with runtime validation - Extract shared readLine/writeLine into socket-line.ts - Document 6 known limitations in CLI readme Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge the standalone `ok` binary into the existing `ocap` CLI as nested `daemon` subcommands (start, stop, begone, exec), removing the need for two separate entry points. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n.sock Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…od to --force Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…p eslint disables Move n/no-process-env exemption for cli package to eslint config, replace process.exit() calls with process.exitCode to allow pending I/O to complete, and simplify daemon-entry.ts error handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Guard the shutdown function with a stored promise so concurrent calls from RPC shutdown, SIGTERM, and SIGINT coalesce into a single handle.close() instead of throwing ERR_SERVER_NOT_RUNNING. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| const { kernel, kernelDatabase } = await makeKernel({ | ||
| resetStorage: false, | ||
| logger, | ||
| }); |
There was a problem hiding this comment.
Daemon creates in-memory database, no state persistence
High Severity
The makeKernel call in daemon-entry.ts omits dbFilename, which causes makeSQLKernelDatabase to default to DEFAULT_DB_FILENAME = ':memory:' — an ephemeral in-memory SQLite database. All kernel state is lost when the daemon process stops, contradicting the PR's purge --force command which promises to "delete all persisted state." Additionally, deleteDaemonState assumes the DB lives at ~/.ocap/kernel.sqlite, a file that will never exist.
Additional Locations (1)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Adds a long-running daemon process to the OCAP kernel, managed via new
ocap daemonCLI subcommands. The daemon spawns as a detached child process, exposes the kernel's RPC service over a Unix domain socket (~/.ocap/daemon.sock), and auto-starts on firstexecinvocation.Supersedes #842, and defers the introduction of its notion of a "console vat" and repl / IO functionality to a later date.
New CLI commands
ocap daemon start— start the daemon (or confirm it is already running)ocap daemon stop— gracefully shut down the daemonocap daemon purge --force— stop the daemon and delete all persisted stateocap daemon exec [method] [params-json]— send a JSON-RPC call to the daemon (defaults togetStatus)Kernel changes
makeKernel()now returns{ kernel, kernelDatabase }and accepts optionalsystemSubclustersifDefinedutility moved fromkernel-agentstokernel-utilsstartRelaymoved fromclitokernel-utils/libp2pNew modules
@ocap/nodejs/daemon— daemon orchestration (startDaemon,deleteDaemonState,startRpcSocketServer, socket line protocol)@ocap/cli/commands/daemon*— CLI-side daemon client, spawner, and command handlersNote
High Risk
Introduces a new local JSON-RPC daemon that can execute kernel RPC methods (including arbitrary SQL via
executeDBQuery) over a Unix socket and adds process-management/spawn logic, which increases security and operational risk if misused or misconfigured.Overview
Adds a detached, long-running daemon that runs the kernel and exposes its RPC surface over a Unix domain socket (
~/.ocap/daemon.sock), plus newocap daemon start|stop|purge --force|execcommands that can auto-spawn the daemon and issue JSON-RPC requests.Introduces
@ocap/nodejs/daemon(socket line protocol, JSON-RPC socket server withshutdowninterception, and state purge helper), updatesmakeKernel()to return{ kernel, kernelDatabase }(and accept optionalsystemSubclusters), and adjusts tests accordingly (including new end-to-end coverage for the socket protocol).Refactors shared pieces by moving
startRelayto@metamask/kernel-utils/libp2p(and updating callers/tests) and movingifDefinedinto@metamask/kernel-utils, along with dependency and script invocation updates (e.g.,yarn run -T ocap ..., ESLint/LavaMoat allowances).Written by Cursor Bugbot for commit e10fe79. This will update automatically on new commits. Configure here.