Skip to main content

Tenuo governance for Claude Code — warrants, hooks, MCP proxy, and Cloud lifecycle

Project description

Tenuo for Claude Code

Tenuo governance for Claude Code: every agent tool call is checked against a signed warrant (hook → authorizer), with a receipt on each decision, including under --dangerously-skip-permissions.

Install: pip install tenuo-claude-code — CLI commands tenuo-claude and tenuo-admin. You do not need to clone this repo to use the tool.

Licensed under Apache-2.0. PyPI: pypi.org/project/tenuo-claude-code

Prerequisites

  • Python ≥ 3.10
  • Docker (runs the authorizer container)
  • Claude Code

Local mode — no Tenuo Cloud account. Cloud modecloud.tenuo.ai tenant (Cloud mode; skip if you are local-only).

If you want to… Start here
Install and run on your machine Use the tool (PyPI)
Clone, hack, or run the sample project Build from source
Review for security / platform Security
Implementation depth docs/DETAILS.md

Use the tool (PyPI)

Five steps. All commands run in one project directory that contains tenuo.yaml.

1. Install

pip install tenuo-claude-code

2. Create a project folder

mkdir my-project && cd my-project
mkdir workspace    # sandbox — files Claude may read per policy

3. Add policy — save as tenuo.yaml in this folder:

name: my-project
sandbox: ./workspace
mode: enforce
enforce:
  Read: "subpath:{sandbox}"
  Bash: "shlex:ls,pwd,echo,date"
default: deny

Or download the starter file (no git clone):

curl -fsSL https://raw.githubusercontent.com/tenuo-ai/claude-governance/main/tenuo.yaml.example -o tenuo.yaml

4. Initialize and start — pick one:

# Manual
tenuo-claude init      # warrant + Claude hooks + MCP wiring
tenuo-claude up        # authorizer in Docker — expect "Local mode (no Cloud)"
tenuo-claude verify    # confirm policy matches authorizer
# Or wizard (same end state; runs check + init + up + verify)
tenuo-claude onboard --local

5. Use Claude Code

Open Claude Code in my-project/ (same directory as tenuo.yaml).

Day to day

When Command
Start work (authorizer down or warrant expired) tenuo-claude up
You edited tenuo.yaml tenuo-claude refresh
Something broken tenuo-claude check
See decisions tenuo-claude audit
Stop authorizer tenuo-claude down

Generated files (do not commit): .state/ (keys, warrant), .claude/settings.json (hooks).

All commands

Command Does
init Mint warrant, wire hooks and .mcp.json
up / down Start / stop authorizer
refresh Re-apply tenuo.yaml (restarts authorizer if up)
check Preflight: deps, credentials, wiring drift
verify [--deep] Policy self-test against the authorizer
status Warrant, posture, Cloud summary
onboard Interactive local or Cloud setup wizard
bench [--json] Per-tool-call overhead
audit [--tail N] Receipt trail
revoke Revoke session warrant

Docs (no source required): Policy · Cloud mode · docs/DETAILS.md


Build from source

For hacking on the CLI, running the reference demo from git, or using ./bin/tenuo-claude instead of a PyPI install.

git clone https://github.com/tenuo-ai/claude-governance.git
cd claude-governance

uv venv && uv sync && chmod +x bin/tenuo-claude
source .venv/bin/activate   # Windows: .venv\Scripts\activate

Run commands via the repo launcher or editable install:

./bin/tenuo-claude --help
# or: uv run tenuo-claude --help
# or: pip install -e . && tenuo-claude --help

Reference demo (sample policy, sandbox, presentation runbook):

cd demo
tenuo-claude bootstrap --local   # check → init → up → verify
tenuo-claude demo                # optional scripted tour

Open Claude Code in demo/. See demo/README.md.

Re-run tenuo-claude init or refresh after switching Python venvs — hooks pin sys.executable in .claude/settings.json.

Contributors: CONTRIBUTING.md.


Policy (tenuo.yaml)

One file drives the warrant, authorizer routes, hooks, and MCP proxy. The minimal example is enough to start; expand as needed:

name: my-project
sandbox: ./workspace
mode: enforce
enforce:
  Read:  "subpath:{sandbox}"
  Bash:  "shlex:ls,pwd,echo,date"
  WebFetch:
    domains: ["api.github.com", "*.githubusercontent.com"]
default: deny
subagents:
  analyst:
    tools: [Read, Grep, Glob]
mcp:
  downstream: ./your_mcp_server.py
  enforce:
    read_file: "subpath:{sandbox}"
  • enforce — allowed and argument-checked.
  • audit — harness tools from bundled list (extend with audit_extra:).
  • default: deny — everything else blocked with a receipt.
  • mode: audit — receipt allow/deny without blocking (rollout).
  • subagents:DETAILS.md.

Cloud overlays (tenuo.yaml.cloud.example, tenuo.yaml.advanced.example) — download from this repo or use tenuo-claude init --cloud / --advanced.

Cloud mode

Requires a cloud.tenuo.ai tenant. Root-signed session warrants, central audit stream, fleet revocation (~30s SRL sync).

Two keys, two files (runtime never sees the admin key):

Key File Used by
Runtime (Quick Connect) .state/cloud.env tenuo-claude up, hooks
Admin ~/.tenuo/admin.env tenuo-admin setup once
pip install tenuo-claude-code
cd my-project                 # your tenuo.yaml lives here

mkdir -p .state ~/.tenuo
curl -fsSL https://raw.githubusercontent.com/tenuo-ai/claude-governance/main/cloud.env.example -o .state/cloud.env
curl -fsSL https://raw.githubusercontent.com/tenuo-ai/claude-governance/main/admin.env.example -o ~/.tenuo/admin.env
# Edit .state/cloud.env — TENUO_CONNECT_TOKEN from cloud.tenuo.ai → Quick Connect → Authorizer Only
# Edit ~/.tenuo/admin.env — tenant-admin API key

tenuo-claude init --cloud
tenuo-admin setup
tenuo-claude up
tenuo-claude verify

Re-run tenuo-admin setup when Cloud capabilities change. Re-run tenuo-claude refresh for local policy edits.

Optional approval gates: DETAILS.md.

How it works

Architecture

tenuo.yaml  →  init/up  →  warrant + authorizer + hooks + MCP proxy
                                    ↓
              native tools (PreToolUse hook)  |  MCP tools (proxy)
                                    ↓
                         authorizer → allow / deny → receipt

Claude hits the MCP proxy (not your downstream server) and the PreToolUse hook for native tools. Both paths use the same warrant and authorizer.

More: docs/DETAILS.md

Security

Tenuo works alongside Claude Code permissions — it does not replace managed settings. You still deploy hooks; Tenuo adds a signed session warrant, a local authorizer on every tool call, and a receipt per decision. Policy is one file (tenuo.yaml).

vs. Claude Code permissions

Claude Code permissions Tenuo warrant
Policy Allow/ask/deny in settings Signed credential; Cloud chains to tenant root
Expiry Until edited Session TTL (~1h); up refreshes
Revocation Edit rules; sessions may keep prior allowances Revoke warrant id → ~30s SRL sync (Cloud)
Evidence Optional hook logs Signed receipt per call; Cloud audit stream
Delegation Project/user tool policy Per-role child warrant; session is the ceiling
--dangerously-skip-permissions Bypasses Claude prompts* Warrant still enforced

*Managed settings can disable bypass (disableBypassPermissionsMode).

Cloud audit

With Tenuo Cloud, session warrants chain to your tenant root. Allow, deny, spawn, and approved exceptions appear in one audit log. Revoke a warrant id from status or the dashboard without touching the laptop.

Authorization receipts in Tenuo Cloud

Admin and runtime keys stay split: tenuo-admin setup (once) vs tenuo-claude up (daily). Runtime refuses to start if an admin key is in the environment.

Rollout

  1. Pilot on one project — init, up, verify (or the demo/ sample).
  2. mode: audit — real allow/deny in receipts, hook does not block. Review WOULD-DENY, tune policy, then mode: enforce.
  3. Fleet — managed-settings hooks, Cloud warrants, team tenuo.yaml via MDM. Help: team@tenuo.ai.

Scope and fail-closed

Governance covers agent tool calls (Read, Bash, MCP, subagent spawns), not interactive ! shell in the Claude TUI (Map vs Territory). Missing or broken tenuo.yaml denies every call until restored.

Keys and credentials in .state/ must be owner-only (0600 in a 0700 directory). The authorizer container mounts only .state/authorizer/ — not holder keys or cloud.env. PoP signing stays in the hook on the host.

Report vulnerabilities: SECURITY.md. Implementation depth: docs/DETAILS.md.

Performance

Run tenuo-claude bench after up. On a typical laptop, Tenuo authorization is ~1–3 ms per call; command hooks add ~100–200 ms (mostly process startup). Use bench --json on your machines.

Enterprise

Fleet rollout (managed settings, team policy in git, Cloud Quick Connect): team@tenuo.ai.

This repo

PyPI package source (src/tenuo_claude_code/). Build from source · CONTRIBUTING.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tenuo_claude_code-0.1.2.tar.gz (49.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tenuo_claude_code-0.1.2-py3-none-any.whl (52.0 kB view details)

Uploaded Python 3

File details

Details for the file tenuo_claude_code-0.1.2.tar.gz.

File metadata

  • Download URL: tenuo_claude_code-0.1.2.tar.gz
  • Upload date:
  • Size: 49.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tenuo_claude_code-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8c0bf0d9b5fc94ff5a4d1e6fde0a28dc3d281745540823b98e709bf5540c4f66
MD5 fe15f6b182813c8510c85d946b4c8074
BLAKE2b-256 26ac4fb878299aedb3c18d2f35372e175c9b4130d4ddd3d36802fb2f67f5f564

See more details on using hashes here.

File details

Details for the file tenuo_claude_code-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: tenuo_claude_code-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 52.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tenuo_claude_code-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 93b3cea4a6ff279aa9c966b06e6bd9aa1b6026eee7b8926c25fe8a30abd3b12c
MD5 90fb2b2110af5fa9e1bc7aa93c144ba8
BLAKE2b-256 abb602fa976ab6a52cf639be68fbb05d19e0962b0832960b138787643d34ff61

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page