@smartledger.technology/openai-claw
v0.7.3
Published
A Claude Code clone powered by OpenAI gpt-5-nano
Maintainers
Readme
openai-claw
An auditable AI agent CLI. Every tool action is recorded, signed with a post-quantum (NIST FIPS-204 ML-DSA-65) key, hashed into a deterministic Merkle tree, and optionally Bitcoin-timestamped via OpenTimestamps — independently verifiable by anyone with a small standalone audit-side package (~11 kB) and standards-compliant tooling (
ots verify). No trust required in the runtime agent, the model provider, or the operator.
A Claude-Code-style TypeScript CLI agent powered by OpenAI's gpt-5-nano (or any chat-completions-compatible model) — but the audit story is the actual product.
$ claw audit verify session.attest.json --proofs ./proofs
Claw audit verification
Cryptography
✓ format ✓ leafContinuity ✓ merkleRoot
✓ ML-DSA-65 signature ✓ sessionAlignment ✓ anchorDigest
Identity
publicKeyId: TSR2Wtuvy-3Ls1Ov
suiteId: ml-dsa-65
leafCount: 6
merkleRoot: 545fde095bf6ee9a682a602f69212d1feaf5169cc0cff9aa200e78511c3dbbdf
OpenTimestamps proofs
✓ sample-session.alice.ots v1 sha256, 237 bytes, pending
✓ sample-session.bob.ots v1 sha256, 235 bytes, pending
✓ sample-session.finney.ots v1 sha256, 256 bytes, pending
Result
✓ Claw-side audit trail is valid
✓ OpenTimestamps proofs are well-formedAudit quickstart
The audit story is reproducible in five commands. The full reproducible demo (with committed fixtures) lives in examples/audit-demo. The protocol and threat model are described in the whitepaper, No Trust in the Agent.
npm install -g @smartledger.technology/openai-claw
claw attest init # one-time: generate a PQ keypair
claw -p "write a hello world script" # session is signed automatically
claw attest anchor <session-id> # submit digest to OpenTimestamps
claw attest export-ots <session-id> --out ./proofs # standards-compliant .ots files
claw audit verify <session-id> --proofs ./proofs # one beautiful commandFor independent verification with no claw runtime:
npm install @smartledger.technology/openai-claw-verify # ~11 kB
# then call verifyAttestation() against any sidecar
# For the Bitcoin side, use the standard client. The timestamped message is the
# canonical JSON of the signed header, which never exists as a file — so pass
# the digest (it is `anchor.digest` in the sidecar) rather than a target file:
ots verify -d $(jq -r .anchor.digest <session-id>.attest.json) proofs/<session-id>.alice.otsWhat is proven
- The session existed at or before a Bitcoin block time. The sha256 of the signed attestation header is submitted to three independent OpenTimestamps calendars and becomes Bitcoin-anchored within ~3 hours.
- The leaves match the deterministic Merkle root. Recomputing the root from the leaves matches the value the signature was made over.
- The Merkle root was signed by the local ML-DSA-65 identity. Post-quantum (NIST FIPS-204) signature verifies under the public key embedded in the sidecar.
- The
.otsfiles are independently parseable by the standard OpenTimestamps tool — claw is not in the verification path. - The audit-side package verifies without trusting the runtime agent.
@smartledger.technology/openai-claw-verifyhas zero dependency on claw, OpenAI, or the model. - That every MCP tool call was preceded by an attachment, an advertisement and a consent record. When the agent uses an
mcp__<server>__<tool>capability,mcp_attach,mcp_tool_offeredandpermission_decisionleaves — carrying the server fingerprint, the tool schema hash and the consent decision — are signed into the same Merkle tree ahead of the call. ThemcpProvenancecheck is structural: it proves those leaves exist in that order. See "What is not proven" for the limit.
What is not proven
This honesty is what makes the project defensible:
- The AI's answer was correct. Verification proves the agent acted as the sidecar says. It does not prove the text was true.
- The user intended every action the AI took. Verification proves what happened, not what was wanted.
- The terminal environment was clean. If the local machine was compromised at the time of the session, the attestor could have been fed false data — the signature would still verify.
- The model was honest internally. Verification covers the I/O boundary. It says nothing about model alignment, hallucination, or intent.
- Bitcoin block confirmation, immediately. Initial OTS proofs are pending — they become Bitcoin-confirmed after the calendars' daily merge (~3 hours). Run
ots upgrade <file>.otsafter that to fetch the completed proof, thenots verify -d <digest> <file>.ots. Confirming the block itself needs a Bitcoin node;claw attest export-otsprints the exact commands with the digest filled in. - That an MCP tool call's provenance leaves describe that call. Leaves store payload hashes, so the verifier cannot read them: it confirms an
mcp_attach, anmcp_tool_offeredand apermission_decisionprecede each MCP call, but not that they refer to the same server and tool, nor that the consent was granted rather than refused. Binding them by content requiressession.jsonto record MCP events too — tracked for a follow-up. - Anything about the transcript, unless you supply it. The signature covers leaf hashes, not session text.
claw audit verifyonly reportssessionAlignmentwhen the matchingsession.jsonis present; without it, a verified sidecar says a session of that shape occurred, not what was in it.
Comparison
| Capability | Claude Code | OpenAI Codex-style tools | Aider | openai-claw | | -------------------------- | :---------: | :----------------------: | :---: | :---------: | | Agent CLI | yes | yes | yes | yes | | Tool use | yes | yes | yes | yes | | Persistent session log | yes | partial | yes | yes | | Signed session log | no | no | no | yes | | Deterministic Merkle root | no | no | no | yes | | Post-quantum signature | no | no | no | yes | | OpenTimestamps export | no | no | no | yes | | Bitcoin-verifiable | no | no | no | yes |
To our knowledge, this is the first npm-published AI agent CLI with signed Merkle session attestations and standards-compliant OpenTimestamps export. Please open an issue if you have a counter-example — we'd genuinely like to hear about it.
Audit architecture
user prompts tool calls tool results assistant text
\ | | /
+---------- leaves ------+-+-------------+
|
v
deterministic Merkle root
|
v
ML-DSA-65 (NIST FIPS-204, post-quantum)
|
v
sha256(canonical-JSON(header))
|
+---------------+--------------+
v v v
alice.btc bob.btc finney
calendar calendar calendar
\ | /
+--- daily merge into Bitcoin ----+
|
v
Bitcoin block
(~3 hours later)The runtime agent (claw) and the audit-side verifier (@smartledger.technology/openai-claw-verify) are deliberately separate packages so an auditor never installs the thing they're auditing.
| Surface | Package | Size | Job |
|---|---|---|---|
| Runtime agent | @smartledger.technology/openai-claw | ~111 kB | Run the agent, produce signed sidecars |
| Audit-side verifier | @smartledger.technology/openai-claw-verify | ~11 kB | Recompute Merkle, verify signature, check anchor digest |
| Crypto primitives | @smartledger/crypto | ~484 kB | ML-DSA-44/65/87, dual-stack ECDSA |
| OTS chain proof | opentimestamps-client (Python) | external | Pull the Bitcoin block attestation, prove inclusion |
Attestation commands
claw attest init generate a fresh ML-DSA-65 keypair
claw attest status suite, key id, file path
claw attest pubkey print the base64 public key
claw attest anchor <id> [--all] submit header digest to OTS calendars
claw attest export-ots <id> [--out=DIR] write standards-compliant .ots files
claw verify <id> [--strict] verify a single session by id
claw audit verify <sidecar|id> [--proofs=DIR]
unified report: crypto + anchor + .ots
claw identity show fingerprint, suite, file path
claw identity fingerprint just the fingerprint
claw identity export-public base64 public keyThe private key lives in ~/.openai-claw/keys/attestor.json at mode 0600. Treat it like ~/.ssh/id_ed25519 — it is your signing identity and is not recoverable from the public key. Back it up off-machine.
Resumed sessions (--continue) currently skip attestation and preserve any existing sidecar; see the roadmap below.
Agent capabilities
Alongside the audit story, claw is a full coding agent — competitive surface with Claude Code, Codex-style CLIs, and Aider:
- Interactive UI — ink-based TUI by default; pass
--no-tuifor the readline REPL fallback. Streaming output,Ctrl-Cto abort a turn. - Core tools —
Read,Write,Edit,Bash,Grep(ripgrep),Glob,LS,WebFetch,WebSearch,Task,TodoWrite, plus background-shellBashOutput/KillShell - Permission system —
ask/acceptEdits/bypassPermissions/planmodes; allowlist + denylist viasettings.json. "Always" / "save" answers scope to the described key (e.g.Bash(npm:*)) rather than the bare tool name. - Subagents —
Tasktool spawns an isolated agent. Built-ingeneral-purpose/exploreplus a frontmatter-driven registry. Optionalisolation: "worktree"runs the subagent in a temp git worktree and returns a sanitized diff (sensitive paths like.env,*.pem,id_rsaare redacted). - Plan mode — read-only investigation, no mutations until approved
- Hooks —
PreToolUse/PostToolUse/UserPromptSubmit/Stop/SessionStart/SessionEnd/PreCompact/SubagentStop/Notificationshell hooks (exit 2 = block) - Project trust gate — the first time you open a repo whose
.claw/defines hooks, MCP servers, or agent/skill definitions, claw prompts before honoring them and remembers your answer. Agent and skill text reaches the model's system prompt, so it is gated the same as code execution. - Skills — Markdown skill files with frontmatter, invoked as
/skill-name - Persistent memory —
MEMORY.mdindex + per-entry frontmatter files - Sessions — every run is saved under
~/.openai-claw/projects/<slug>/sessions/;--continue,/sessions,/forkrestore or branch them - Context compaction — older turns are summarized as the conversation approaches the model's context window
- Semantic index (RAG) —
/indexembeds the working tree withtext-embedding-3-small; the agent can query via theSemantictool - Cost tracking — per-turn cost is logged to
cost.logand surfaced via/costand the optional dashboard - MCP — stdio and streamable-HTTP MCP clients; remote tools wrapped as
mcp__<server>__<tool> - Plugins —
claw install <git-url>/claw uninstall <name>/claw plugins [list|search|trust|untrust] - Auto-PR —
claw pr "<task>"runs the agent in an isolated git worktree, commits, pushes and opens a draft PR. Your working tree is never touched, and the run is attested like any other session. - Dashboard —
claw dashboardserves a loopback-only web UI for cost, sessions, evals - Notifications — desktop notifications for long-running tools and session completion
- Self-review —
/reviewasks the agent to critique the current branch's diff - Evals —
npm run evalruns 14 scenario-based regression cases against the agent in sandboxed repos (real model calls, so it costs money) - Shell escape — prefix any input with
!to run it directly in the shell - One-shot mode —
claw -p "your prompt"runs once and prints the answer
Install
npm install -g @smartledger.technology/openai-clawYou'll also want ripgrep for the Grep tool:
sudo apt install ripgrep # Debian/Ubuntu
brew install ripgrep # macOSFor audit verification with the standard OTS tool:
pipx install opentimestamps-client
# or:
python3 -m venv /tmp/ots-venv && /tmp/ots-venv/bin/pip install opentimestamps-clientConfigure
The only required setting is your OpenAI API key:
export OPENAI_API_KEY=sk-...Optional environment overrides:
| Variable | Purpose |
| -------- | ------- |
| OPENAI_CLAW_MODEL | Model to use (default gpt-5-nano) |
| OPENAI_BASE_URL | Alternative API base (Azure, vLLM, OpenRouter, …) |
| OPENAI_CLAW_SEARCH_PROVIDER | duckduckgo (default) or tavily |
| TAVILY_API_KEY | API key for Tavily web search |
| OPENAI_CLAW_MCP_ENV_PASSTHROUGH | Extra env var names to expose to MCP servers (comma-separated) |
| OPENAI_CLAW_STRICT_TOOLS | Set to 0 to disable strict-mode tool schemas |
Persistent settings live in ~/.openai-claw/settings.json and (per project) <workdir>/.claw/settings.json. Project settings win.
Security model
What the sandbox actually is, so you can judge it:
- Tool permissions. Rules match a key:
Read,Bash(npm:*),WebFetch(example.com). A shell command carrying an operator (;,&&,|, backticks,$( ), redirection) never gets a reusable prefix key — it is keyed exactly and re-prompts every time, so approvinggit statuscannot also approvegit status; curl … | sh. Deny rules are checked against every command in a chain and against the command's basename, soBash(rm:*)also stops/bin/rm. - MCP subprocesses get a filtered environment. Only what a server needs to run (
PATH,HOME, locale, …) plus whatever its ownenvblock declares.OPENAI_API_KEYand everything else in your shell is withheld; widen it deliberately withOPENAI_CLAW_MCP_ENV_PASSTHROUGH. - Project-level hooks and MCP servers need trust. The first run in a directory that declares them prompts; the answer is remembered in
trustedProjects. Non-interactive runs deny. - Plugin MCP servers need a second, explicit step.
claw installnever registers them — it prints what they would run.claw plugins trust <name>registers them,claw plugins untrust <name>removes them. This is separate because plugin servers land in user settings and so apply to every project. - A project cannot write to your system prompt without consent.
.claw/agents/*.mdand.claw/skills/*/SKILL.mdare loaded only after the trust prompt — an agent definition's description otherwise reaches the model through the Task tool catalog before you type anything. - The dashboard binds loopback only. It serves whole transcripts with no authentication.
Not in scope: claw does not sandbox the filesystem or network of the commands you approve. Approving a command runs it with your privileges.
Use
Start the TUI in any project directory:
cd ~/some-project
clawOne-shot:
claw -p "summarize what this repo does in one paragraph"A typical interactive turn looks like:
> fix the typo in src/server.ts around line 42
▸ Read src/server.ts
▸ Edit src/server.ts
@@ -42,1 +42,1 @@
- cosole.log("starting server");
+ console.log("starting server");
Fixed: `cosole` → `console` on line 42.
● openai-claw model=gpt-5-nano tokens=4127 $0.0003Parallel tool calls (e.g. reading ten files at once), background bash shells, slash commands (/sessions, /fork, /index, /review, …), and persistent sessions all work as you'd expect.
If claw attest init has been run, every session — one-shot, REPL, or TUI — writes a signed sidecar automatically.
Project layout
src/
├── index.ts CLI entry (run, install, pr, dashboard, attest, verify, audit, identity)
├── agent.ts tool-calling loop + streaming
├── client.ts OpenAI SDK wrapper (retry, error classification)
├── config.ts config loading + settings.json merging + file lock
├── trust.ts per-project trust prompt for hooks/MCP
├── session.ts save/load/list/fork sessions
├── cost.ts model pricing + cost.log writer/reader
├── subagent.ts Task tool runner + worktree isolation + diff redaction
├── attest/ attestation surface
│ ├── identity.ts ML-DSA-65 keypair, on-disk mode 0600
│ ├── attestor.ts live event collection + signing
│ ├── anchor.ts OpenTimestamps calendar HTTP client
│ ├── ots-file.ts spec-compliant .ots serialization
│ ├── runtime.ts SessionAttestor — UI-agnostic wrapper
│ └── index.ts facade re-exporting from openai-claw-verify
├── tools/ Read, Write, Edit, Bash (fg+bg), Grep, Glob, LS,
│ WebFetch, WebSearch, Task, TodoWrite, Semantic
├── permissions/ ask/allow/deny + interactive prompt
├── memory/ listMemories/writeMemory + compaction.ts
├── hooks/ shell hooks driven by settings.json
├── skills/ SKILL.md loader
├── commands/ /slash commands
├── mcp/ stdio + streamable-HTTP MCP clients
├── rag/ embeddings-based semantic index
├── plugins/ plugin installer + registry
├── autopr/ `claw pr` orchestrator
├── self-review/ `/review` skill
├── notifications/ desktop notifications
├── eval/ evals harness
├── web/ `claw dashboard` HTTP server
└── ui/ tui/ (ink) + repl.ts (readline)
packages/openai-claw-verify/ audit-side verifier (separately published)
├── src/leaf.ts canonical JSON, sha256
├── src/merkle.ts deterministic binary Merkle tree
├── src/verify.ts signature + Merkle + anchor checks
└── src/types.ts Attestation, AnchorProof, VerifyReportRoadmap
| Version | Theme | Highlights |
|---|---|---|
| 0.5.0 | Auditor Experience | claw audit verify, claw identity, reproducible demo fixtures |
| 0.6.0 | MCP Attestation | per-MCP-tool provenance (mcp_attach, mcp_tool_offered, mcpProvenance) signed into the Merkle tree; strict-mode tool schemas + dispatch-layer arg validation |
| 0.7.0 | Automation | auto-anchor batching, anchor-on-save, retry queue, configurable calendars |
| 0.8.0 | SmartLedger Interop | GDAF envelope wrapping, ChainSimple alternate anchor, Legal Token Protocol metadata, optional BSV publication |
Differences from Claude Code
- Powered by OpenAI's API, not Anthropic's — so no anthropic-prompt-caching, no extended thinking. Prompt caching is approximated via cache-friendly system prompts and tracked in cost accounting.
- Web search defaults to scraping DuckDuckGo HTML (rate-limited and fragile); set
OPENAI_CLAW_SEARCH_PROVIDER=tavilyfor production use. - Permission model is simplified — allowlist patterns support
ToolorBash(prefix:*), but not full glob semantics. - Auditability is the differentiator. Claude Code logs to disk; openai-claw signs, Merkle-hashes, and Bitcoin-anchors.
Author
Gregory J. Ward, CTO, SmartLedger.Technology
License
MIT — see LICENSE.
