{"id":50930576,"url":"https://github.com/farchanjo/merkle","last_synced_at":"2026-06-17T03:32:25.846Z","repository":{"id":359897369,"uuid":"1247927481","full_name":"farchanjo/merkle","owner":"farchanjo","description":"Local-first MCP vault for Claude Code — LLMs hold opaque handles, operators approve every reveal, every access leaves a BLAKE3 hash. Rust 2024 / DDD + Hexagonal.","archived":false,"fork":false,"pushed_at":"2026-05-24T01:14:50.000Z","size":1315,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-24T02:27:36.407Z","etag":null,"topics":["argon2id","audit-log","blake3","claude-code","cryptography","ddd","ed25519","hexagonal-architecture","local-first","mcp","model-context-protocol","rust","rust-2024","secrets","secrets-management","security","spec-driven-development","sqlite","vault","xchacha20-poly1305"],"latest_commit_sha":null,"homepage":"https://github.com/farchanjo/merkle","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/farchanjo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-24T00:58:43.000Z","updated_at":"2026-05-24T01:14:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/farchanjo/merkle","commit_stats":null,"previous_names":["farchanjo/merkle"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/farchanjo/merkle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farchanjo%2Fmerkle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farchanjo%2Fmerkle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farchanjo%2Fmerkle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farchanjo%2Fmerkle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/farchanjo","download_url":"https://codeload.github.com/farchanjo/merkle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farchanjo%2Fmerkle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34433085,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argon2id","audit-log","blake3","claude-code","cryptography","ddd","ed25519","hexagonal-architecture","local-first","mcp","model-context-protocol","rust","rust-2024","secrets","secrets-management","security","spec-driven-development","sqlite","vault","xchacha20-poly1305"],"created_at":"2026-06-17T03:32:23.541Z","updated_at":"2026-06-17T03:32:25.818Z","avatar_url":"https://github.com/farchanjo.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Merkle\n\n\u003e The gate between context and credential. Every access leaves a hash.\n\n[![CI](https://img.shields.io/badge/CI-passing-brightgreen)](#)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)\n[![MSRV](https://img.shields.io/badge/MSRV-1.85-orange)](https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html)\n[![MCP](https://img.shields.io/badge/MCP-2025--11--25-purple)](https://modelcontextprotocol.io/specification)\n\n`Merkle` is a local-first MCP vault that mediates between LLM context and secret\nstorage. It issues opaque handles by default; plaintext only crosses the MCP\ntransport when the human operator explicitly authorizes a Reveal via slash command\nand — for high-sensitivity secrets — Out-of-Band Confirmation.\n\nThe project is named after Ralph Merkle (Merkle puzzles 1974, Merkle trees), whose\nconstructions underpin the audit-chain integrity model.\n\n\u003e [!NOTE]\n\u003e **Status: Pre-alpha.** Architecture is fully specified; Rust implementation is in\n\u003e progress. See [`docs/arch/`](docs/arch/README.md) for the canonical specification\n\u003e (20 ADRs, 48 CUE schemas, 9 Gherkin features, 9 Rego policies, 43 SLO YAML, 2\n\u003e TLA+ models).\n\n---\n\n## Why Merkle?\n\n| Property | What it means |\n|:---|:---|\n| **LLMs hold handles, not secrets** | The MCP transport sees `vault://acme/password/db-admin`, never the plaintext |\n| **Operator approval for every Reveal** | No autonomous decryption by the LLM; slash command required |\n| **OOB Confirmation for high-sensitivity material** | A separate channel (companion device, desktop notification, terminal prompt) signs every Reveal challenge with Ed25519 |\n| **Tamper-evident audit log** | BLAKE3 hash chain with synchronously-pinned head; truncation, removal, and reordering are detectable |\n| **Local-first** | No cloud dependency — SQLite + OS keychain + `age` backups |\n| **Static binary** | One `cargo build --release`; zero runtime installation |\n\n---\n\n## Architecture at a glance\n\nSix bounded contexts collaborate to keep secrets safe:\n\n```mermaid\nflowchart LR\n    IdentityAndSealing[Identity and Sealing]\n    SecretStorage[Secret Storage]\n    AccessMediation[Access Mediation]\n    AuditCompliance[Audit and Compliance]\n    BackupRecovery[Backup and Recovery]\n    PolicyPermissions[Policy and Permissions]\n\n    IdentityAndSealing --\u003e|unwraps| SecretStorage\n    SecretStorage --\u003e|resolved by| AccessMediation\n    AccessMediation --\u003e|emits events to| AuditCompliance\n    SecretStorage --\u003e|snapshotted by| BackupRecovery\n    PolicyPermissions --\u003e|governs| AccessMediation\n    PolicyPermissions --\u003e|governs| SecretStorage\n    AccessMediation --\u003e|chains entries via| AuditCompliance\n```\n\n**Driving ports:** MCP Adapter (`rmcp` SDK), CLI Adapter (`clap`), Companion Socket\n(axum over Unix domain socket).\n\n**Driven ports:** Storage (SQLite WAL), Keychain (cross-OS via `keyring`), Crypto\n(XChaCha20-Poly1305 + BLAKE3 + Argon2id + Ed25519 + X25519 + `age`), OOB Notifier.\n\n**Process topology** — Vault Agent daemon + thin MCP Adapter per client window\n(same pattern as `ssh-agent` and `gpg-agent`):\n\n```mermaid\nflowchart TD\n    subgraph Claude Code Window 1\n        CC1[Claude Code]\n        MCP1[MCP Adapter stdio]\n    end\n    subgraph Claude Code Window 2\n        CC2[Claude Code]\n        MCP2[MCP Adapter stdio]\n    end\n    subgraph Agent Process\n        VA[Vault Agent daemon]\n        DBC[SQLite single writer]\n        BG[Background Workers backup / reaper]\n    end\n    CS[Companion Socket Unix socket]\n\n    CC1 --\u003e MCP1\n    CC2 --\u003e MCP2\n    MCP1 --\u003e|JSON-RPC| CS\n    MCP2 --\u003e|JSON-RPC| CS\n    CS --\u003e VA\n    VA --\u003e DBC\n    VA --\u003e BG\n```\n\nSee [`docs/arch/README.md`](docs/arch/README.md) for the full architecture model,\nbounded-context narratives, and the recommended reading order for newcomers.\n\n---\n\n## Quick start\n\n### Prerequisites\n\n- **Rust 1.85+** — install via [rustup](https://rustup.rs)\n- **SQLite 3.35+** — bundled via `rusqlite` (no system install required)\n- **OS keychain** — macOS login keychain, Linux Secret Service (GNOME Keyring or\n  KWallet), or Windows Credential Manager. Headless/CI uses passphrase fallback.\n- **Claude Code** with MCP support enabled\n\n### Build\n\n```sh\ngit clone https://github.com/farchanjo/merkle.git\ncd merkle\ncargo build --release\n# Binary at target/release/merkle\n```\n\n### Initialize the vault\n\n```sh\nmerkle init\n```\n\nThe interactive wizard walks through seven steps: database path, config path,\nSecurity Profile (`relaxed` / `balanced` / `paranoid`), Master Key generation,\nRecovery Key display and confirmation, and optional service registration.\n\n\u003e [!WARNING]\n\u003e The **Recovery Key** is displayed exactly once during `merkle init`. Record it\n\u003e offline immediately — printed document, offline password manager, or hardware\n\u003e security token. Without it, disaster recovery is impossible if the OS keychain\n\u003e is lost.\n\nAfter init completes, verify the recovery key while the vault is still empty:\n\n```sh\nmerkle verify-recovery-key\n```\n\n### Start the agent\n\nIf you chose not to register with the OS service manager during init:\n\n```sh\nmerkle agent \u0026\n```\n\n### Put your first secret\n\n```sh\nmerkle put \\\n  --namespace personal \\\n  --category password \\\n  --name example \\\n  --value '{\"password\":\"change-me\"}' \\\n  --sensitivity low\n```\n\n### Pair a companion device (optional)\n\nA Companion Device provides a cryptographically bound second factor for\n`sensitivity=high` Reveals via Ed25519 signature:\n\n```sh\nmerkle device pair\n# Displays QR code + pairing code for the companion app\nmerkle device list   # confirm enrollment\n```\n\nSee [`docs/arch/integrations/onboarding.md`](docs/arch/integrations/onboarding.md)\nfor the full enrollment ceremony and challenge signing protocol.\n\n### Hook up Claude Code\n\nAdd the MCP server entry to `~/.claude.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"merkle\": {\n      \"command\": \"/usr/local/bin/merkle\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"MERKLE_PROFILE\": \"balanced\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Code or run `/mcp restart merkle`, then verify:\n\n```\nAsk Claude: \"Call vault.doctor and show me the full result.\"\n```\n\nExpected: `\"sealed\": false` when the agent is running and unsealed.\n\n\u003e [!NOTE]\n\u003e For full slash command configuration (`/merkle-reveal`, `/merkle-show`,\n\u003e `/merkle-rollback`, `/merkle-doctor`) and the Operator Confirmation flow, see\n\u003e [`docs/arch/integrations/claude-code-wiring.md`](docs/arch/integrations/claude-code-wiring.md).\n\n---\n\n## Reveal model\n\nMerkle enforces a two-flag authorization model for every `vault.reveal` call:\n\n| Flag | Set by | Channel | Required for |\n|:---|:---|:---|:---|\n| `slash_command` | Claude Code client | MCP session context | All sensitivities |\n| `oob_ack` | OOB Notifier | Distinct OS channel | `sensitivity=high` |\n\nThe LLM cannot set either flag through tool call arguments — both are injected by\nindependent channels outside the model's control. See\n[ADR-0011](docs/arch/adr/0011-slash-only-reveal-with-oob-for-high-sensitivity.md)\nfor the full decision rationale and decision tree.\n\n---\n\n## Documentation\n\n| Area | Location |\n|:---|:---|\n| Architecture overview | [`docs/arch/README.md`](docs/arch/README.md) |\n| Canonical vocabulary | [`docs/arch/glossary.md`](docs/arch/glossary.md) |\n| Decisions (20 ADRs) | [`docs/arch/adr/`](docs/arch/adr/) |\n| Domain narratives (6 bounded contexts) | [`docs/arch/domain/`](docs/arch/domain/) |\n| CUE schemas (48 types) | [`docs/arch/schemas/`](docs/arch/schemas/) |\n| API contracts (OpenAPI + AsyncAPI) | [`docs/arch/integrations/`](docs/arch/integrations/) |\n| Rego policies (9 files, 123 tests) | [`docs/arch/policies/`](docs/arch/policies/) |\n| Acceptance scenarios (9 Gherkin features) | [`docs/arch/specs/features/`](docs/arch/specs/features/) |\n| Threat model | [`docs/arch/threat-model/`](docs/arch/threat-model/) |\n| SLOs (43 YAML) | [`docs/arch/slo/`](docs/arch/slo/) |\n| Formal models (2 TLA+) | [`docs/arch/formal/`](docs/arch/formal/) |\n| Operations + runbooks | [`docs/arch/operations/`](docs/arch/operations/) |\n| Onboarding walkthrough | [`docs/arch/integrations/onboarding.md`](docs/arch/integrations/onboarding.md) |\n| Claude Code wiring | [`docs/arch/integrations/claude-code-wiring.md`](docs/arch/integrations/claude-code-wiring.md) |\n\n**Reading order for newcomers:** glossary → domain narratives → ADRs in numeric order\n→ Structurizr workspace → CUE schemas → Rego policies → Gherkin features →\nthreat model → SLOs + operations.\n\n---\n\n## Development\n\n### Common `just` commands\n\n| Command | Description |\n|:---|:---|\n| `just build` | Compile all workspace crates in release mode |\n| `just test` | Run the full test suite via `cargo nextest` |\n| `just spec` | Run the spec validation gate (`spec validate --lane full`) |\n| `just doctor` | Run `merkle doctor` against the local dev vault |\n| `just lint` | `cargo clippy --all-targets --all-features` |\n| `just fmt` | `cargo fmt --all -- --check` |\n\n### Adding a new ADR\n\n1. Copy `docs/arch/adr/0000-template.md` to `docs/arch/adr/NNNN-\u003cslug\u003e.md`.\n2. Fill in `status: proposed`, `date`, `deciders`.\n3. Complete all sections; link related ADRs in **More Information**.\n4. Submit a merge request — the CI spec validation gate will verify the MADR\n   structure automatically.\n\n### Spec validation gate\n\nEvery code change touching a new behavior must update the corresponding artifact\nunder `docs/arch/` (CUE schema, Gherkin scenario, OpenAPI/AsyncAPI spec, ADR if\narchitectural). The `spec validate` gate enforces this in CI:\n\n```sh\nspec validate --lane fast    # ~1.5 s — CUE vet, DDD-role header, OpenAPI lint\nspec validate                # ~10 s  — fast + Structurizr, markdownlint, format\nspec validate --lane full    # CI     — full + Conftest (Rego), Vale, TLC (TLA+)\n```\n\nSee [ADR-0018](docs/arch/adr/0018-full-coverage-validation-as-architectural-contract.md)\nfor the full validation contract.\n\n---\n\n## Security\n\nSee [SECURITY.md](SECURITY.md) for vulnerability reporting, response SLAs, and\nscope.\n\nCross-reference: [`docs/arch/threat-model/`](docs/arch/threat-model/) for the STRIDE\nmodel and trust boundary analysis.\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n---\n\n## License\n\nApache-2.0. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarchanjo%2Fmerkle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffarchanjo%2Fmerkle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarchanjo%2Fmerkle/lists"}