/docs/quickstart

Quick start

Five steps, on macOS, from nothing to a sandboxed and recorded Claude Code session.

Install both binaries#

Install nd7 and nd7-exec with one cargo command.

cargo install --locked --git https://github.com/nd7-dev/nd7-core

That single command installs both programs into ~/.cargo/bin. They must stay side by side, because nd7 run finds nd7-exec by looking beside itself and refuses to start if it is missing or writable by anyone but you.

Check that it worked#

nd7 --help lists the commands; nd7-exec on its own prints usage.

nd7 --help
nd7-exec

nd7 --help prints record, verify, enroll, ship, run, hook-prefix, allow and deny. nd7-exec prints its own usage and exits 2, which is the expected result outside a session.

Run Claude Code inside the sandbox#

Change into your project and start the session there.

cd your-project
nd7 run claude

The directory you are in is the project: the one place the agent may write from the start. Before Claude Code starts, nd7 run prints one line naming the session:

nd7 run: session 41287 under nd7's policy; a sandbox the program applies itself is refused

Let the agent write somewhere else, mid-session#

From another terminal, grant a path while the session is still running.

nd7 allow ~/data
nd7 deny  ~/data

The next Bash command already runs under the new rules — no restart, no signal. Grants reach Bash commands but not the Write and Edit tools, which run inside the claude process.

Turn on the audit log#

Register nd7 record as a hook in ~/.claude/settings.json for every project, or in the project's own .claude/settings.json.

{
  "hooks": {
    "SessionStart":       [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 5 }] }],
    "UserPromptSubmit":   [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 5 }] }],
    "PreToolUse":         [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 5 }] }],
    "PostToolUse":        [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 5 }] }],
    "PostToolUseFailure": [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 5 }] }],
    "Stop":               [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 5 }] }],
    "SessionEnd":         [{ "hooks": [{ "type": "command", "command": "nd7", "args": ["record"], "timeout": 1 }] }]
  }
}

nd7 run sets up the sandbox but does not register the recorder, so this is a separate, one-time step. Afterwards, check a session's hash chain:

ls ~/.local/state/nd7/sessions/
nd7 verify <session-id>

Each directory under ~/.local/state/nd7/sessions/ is one session, named after Claude Code's own session id; that name is the <session-id> argument.

Next#

Updated . This page as Markdown · Source on GitHub.