# geth `geth` is a personal, local-first mesh runtime for scripts, devices, databases, documents, blobs, pipes, and future multi-user collaboration. This project is not the Ethereum `geth` client. The project and executable are still named `geth`. ## One Binary There is one executable: `geth`. It has daemon mode and control mode: ```sh geth init geth daemon run geth daemon service install geth status geth node id geth resource list geth cas add ./file ``` The daemon owns local identity, the Iroh endpoint, trust state, resource registry, module router, local metadata store, and synchronized data structures. Most non-daemon commands talk to the daemon through a local Unix socket at `$GETH_HOME/run/geth.sock`. The daemon can also install itself as a user service: ```sh geth daemon service install geth daemon service status geth daemon service uninstall ``` The bootstrap service managers are systemd user units on Linux, launchd user agents on macOS, and per-user scheduled tasks on Windows. These are user-level services, not system services. ## Transport And SSH All remote node-to-node geth communication is designed to happen over Iroh only. SSH is not a geth transport backend, and there is no SSH fallback transport. The default node config uses Iroh's default relay policy for practical connectivity; set `[iroh].relay_mode = "disabled"` for local-only/offline development. Named custom relay maps can be selected with `relay_mode = "custom"` and `relay_map = ""`. Iroh local-network discovery is enabled by default with `[iroh].local_discovery = true`. SSH keys are used as admin trust anchors and ecosystem integration points. OpenSSH, FIDO, and YubiKey-backed keys can sign geth trust objects through canonical geth envelopes with explicit namespaces such as `geth.keychain.v1@geth.local`. Future SSH proxying may carry SSH protocol bytes over authorized Iroh streams, but the geth transport remains Iroh. SSH certificate request and renewal flows are managed as geth metadata. A node can create a certificate request, another machine can approve it and receive an explicit `ssh-keygen -s ...` command suitable for a CA key or YubiKey-backed CA, and the resulting `-cert.pub` can be imported for distribution. Certificate and key revocation entries are tracked locally and can be exported as JSONL or as an OpenSSH KRL specification file or a binary OpenSSH KRL generated through `ssh-keygen -k`. `geth ssh cert sync ` and `geth ssh revocation sync ` pull certificate-flow and revocation metadata from an authorized peer over Iroh. ## MVP Features The bootstrap implementation provides: - `geth init` - `geth daemon run` - `geth daemon service install|uninstall|start|stop|status|print` - `geth status` - `geth node id` - `geth peer export [--out ]` - `geth peer import ` - `geth peer list` - `geth peer ping ` - `geth peer auth-check ` - `geth resource list` - `geth resource create ` - `geth keychain init [--admin-key ]` - `geth keychain status` - `geth secret status` - `geth secret create ` - `geth secret rotate ` - `geth secret bearer create --capability ` - `geth secret bearer list` - `geth secret bearer revoke ` - `geth auth explain ` - `geth auth grant [--grant-id ]` - `geth auth revoke ` - local filesystem CAS commands: `add`, `get`, `fetch`, `hash`, `has`, `pin`, `unpin`, `cleanup`, `list` - local CAS tree objects describe file trees and are stored as CAS blobs - local file-root commands: `geth cas root add/list/scan` - local file conflict metadata commands: `geth cas conflict record/list/resolve` - local DB resource registration: `geth db add ` and `geth db status ` with schema and `crsql_changes` metadata; the DB crate and daemon can extract typed local `crsql_changes` batches through `geth db changes ` for future sync - local SQLite-backed KV commands: `geth kv create/set/get`; `kv set` accepts `--subject ` to exercise local capability checks for non-local callers; `geth kv sync ` pulls authorized remote updates - local JSON document commands: `geth document create/status/set/get`; `geth document sync ` pulls authorized remote JSON state - local daemon-lifetime pubsub snapshots: `geth pubsub pub/sub`; `geth pubsub pub --node ` publishes to an authorized peer - SSH certificate flow metadata: - `geth ssh cert request --public-key --principal ` - `geth ssh cert requests` - `geth ssh cert approve --ca-key ` - `geth ssh cert import --cert ` - `geth ssh cert list` - `geth ssh cert sync ` - `geth ssh revocation add ` - `geth ssh revocation list` - `geth ssh revocation export --out [--format jsonl|openssh-krl-spec|openssh-krl]` - `geth ssh revocation import [--format jsonl|openssh-krl-spec]` - `geth ssh revocation sync ` - pipe registry/connect commands: `geth pipe listen ` and `geth pipe connect [--node ]` `geth peer export/import/list` is for untrusted peer-card exchange. Peer cards include the Iroh EndpointID plus currently known relay/direct addresses. `geth peer ping ` uses the local daemon's Iroh endpoint to dial an imported peer card and exchange a signed candidate-only peer-card ping. `geth peer auth-check ` sends a protected Iroh control request: the remote daemon verifies that the caller's signed peer card binds the actual Iroh EndpointID before reducing resource-local auth ops. `geth cas fetch ` uses the same protected Iroh control path to request a blob from a peer. The remote daemon only returns bytes when the caller has `cas.fetch` on `resource:cas:local`, and the caller verifies that the bytes hash to the requested BLAKE3 CAS hash before storing them locally. This is the bootstrap transfer path; future work will move provider/fetch behavior to `iroh-blobs`. `geth ssh cert sync ` requires `ssh_cert.sync` on `resource:ssh:certs` at the peer. `geth ssh revocation sync ` requires `ssh_revocation.sync` on `resource:ssh:revocations`. Both commands merge authorized peer metadata into the local store for offline listing and later approval/signing workflows. While the daemon is running, it also performs a background live-sync tick for known peers every 30 seconds. Live-sync stores per-peer high-water cursors in local metadata so repeated ticks request only newer SSH certificate-flow and revocation records. Named KV stores participate in the same live-sync loop once they exist locally: manual `geth kv sync ` and background ticks require `kv.read` on the remote `resource:kv:` and import only remote entries that are not older than the local value. Remote pubsub publish uses the protected Iroh control path too. The remote peer requires `pubsub.publish` on `resource:pubsub:` before recording the message in its local daemon-lifetime ring buffer. Pubsub remains lossy and is not durable storage. Remote pipe connect uses the same protected Iroh control path and requires `pipe.connect` on `resource:pipe:`. The current prototype records a remote connection attempt and whether a listener exists; byte streaming and forwarding are still future work. Document sync is a bootstrap JSON last-writer-wins path before Automerge: manual `geth document sync ` and background live-sync require `document.read` on `resource:document:` and import only state that is not older than the local document timestamp. Importing or pinging a peer card never grants capabilities by itself. When `[iroh].local_discovery = true`, the daemon also advertises and discovers signed peer cards on LAN using a geth-specific mDNS TXT payload. That payload is candidate metadata only; all geth node-to-node requests still run over Iroh. Other command groups exist as explicit stubs: `ssh proxy`. ## Resource Modules Everything meaningful is modeled as a resource. Planned resource kinds are: - `db`: SQLite/cr-sqlite synchronization - `kv`: Iroh Documents backed key-value stores - `pipe`: dumbpipe-like byte streams over Iroh; the bootstrap has a local daemon registry only - `document`: Automerge documents over Iroh streams - `pubsub`: lossy notifications, not authoritative storage; the bootstrap keeps only an in-memory daemon-lifetime ring buffer - `cas`: content-addressed blob storage and distribution - `ssh-proxy`: authorized SSH proxy/admin access over Iroh Authorization is resource-scoped and capability-based. Bearer secrets may grant specific resource capabilities but do not create trusted node identity. The auth evaluator supports scoped KV write grants such as `kv.write_prefix:apps/foo/` for `kv.write_key:apps/foo/config` explain checks. `geth kv set --subject ` enforces those local grants for test callers; the local node/agent still has owner access for local administration. ## Local State If `GETH_HOME` is set, geth uses it. Otherwise it uses an OS-specific data directory. The bootstrap layout is: ```text $GETH_HOME/ geth.sqlite config.toml identity/agent.ed25519 identity/iroh.ed25519 cas/blobs/ run/geth.sock ``` ## Quick Start In one shell: ```sh export GETH_HOME="$(mktemp -d)" cargo run -p geth -- init cargo run -p geth -- daemon run ``` In another shell: ```sh export GETH_HOME="" cargo run -p geth -- status cargo run -p geth -- node id echo "hello geth" > /tmp/hello-geth.txt cargo run -p geth -- cas add /tmp/hello-geth.txt cargo run -p geth -- cas list ``` ## Authorization Direction The MVP defines the split between: - keychain: SSH-rooted users, devices, nodes, agents, and endpoint bindings - auth: resource-local signed authorization operations and capability grants - secrets: resource master secrets, epochs, envelopes, and bearer access The current code does not implement Keyhive, BeeKEM, strong forward secrecy, or post-compromise security. It leaves room for future local-first, replicated auth logs and BeeKEM/CGKA-style group key evolution.