cc-relay
An adaptive interrupt layer for Claude Code and Codex. Relay intercepts tool calls via hooks, learns from your approval history, and automatically decides what to let through — only interrupting you when a real decision is needed, and sending a desktop notification so you're never left wondering why the task stalled.
The key idea: other permission tools use static rules or call an LLM on every action. Relay tracks your actual approval rate per action type and adapts over time. After you approve git commit ten times, it stops asking. High-risk operations always interrupt — everything else gets quieter as you use it.
Why cc-relay
| Static allowlists | LLM classifier | cc-relay | |
|---|---|---|---|
| Setup | Manual rule maintenance | API key required | Zero config |
| Learns from you | No | No | Yes |
| Cost per decision | Free | ~$0.001/call | Free |
| Adapts to your workflow | No | No | Yes |
| Works offline | Yes | No | Yes |
How it works
The agent is about to execute a tool (Write, Bash, Edit, shell command, etc.)
↓
PreToolUse hook fires → relay hook pre
↓
Look up historical approval rate + assess risk level
↓
allow → tool executes immediately, auto-recorded as approved
interrupt → tool pauses or is blocked, desktop notification sent, client asks for your decision
↓
User confirms → agent continues, PostToolUse marks record as approved
User rejects → session ends
↓
Stop hook fires → marks pending records as rejected + sends completion notification
↓
History accumulates → same action type gets quieter over time
Decision logic
| Condition | Result |
|---|---|
| High-risk (delete files, force push, drop table, system paths) | Always interrupt |
| Low risk, effective weight < 4 | Auto-approve (no baseline needed) |
| Low risk, effective weight ≥ 4, approval rate ≥ 90% | Auto-approve |
| Medium risk, effective weight < 7 | Interrupt to build baseline |
| Medium risk, effective weight ≥ 7, approval rate ≥ 85% | Auto-approve |
| Everything else | Interrupt |
Approval rates use exponential time decay (half-life: 7 days) — recent decisions carry more weight than old ones. If you start rejecting an action you previously always approved, the weighted approval rate drops quickly and Relay starts interrupting again within days. Old approvals fade naturally, so the system never gets permanently locked into auto-approve.
| Action type | Description | Risk |
|---|---|---|
file_write:system |
Write to /etc/, /usr/, etc. |
High |
file_write:config |
Write to .env, .yaml, .toml, etc. |
Medium |
file_write:code |
Write to regular code files | Medium |
bash_write:git |
git commit / push / merge | Medium |
bash_write:package_manager |
pip / uv / npm installs | Medium |
bash_write:shell |
mv / cp / chmod and other shell ops | Medium |
file_delete |
rm, drop table, and other deletions | High |
bash_read / file_read |
Read-only operations | Low |
Installation
Relay supports both Claude Code and Codex. Add the MCP server to your agent config; on first startup, Relay installs hooks for both clients:
- Claude Code hooks:
~/.claude/settings.json - Codex hooks:
~/.codex/config.toml
Claude Code global config — add to the mcpServers field in ~/.claude.json:
{
"mcpServers": {
"relay": {
"type": "stdio",
"command": "uvx",
"args": ["cc-relay@latest"]
}
}
}
Codex global config — add to ~/.codex/config.toml:
[mcp_servers.relay]
type = "stdio"
command = "uvx"
args = ["cc-relay@latest"]
Restart your agent. Relay starts as an MCP server and runs --install-all behavior automatically, so both Claude Code and Codex hooks are kept up to date.
Uninstall
uvx cc-relay --uninstall-all
Notification support
Relay sends two types of desktop notifications. Text auto-switches based on system language (Chinese, English, Japanese, Korean).
- Interrupt: when an action needs your approval — prompts you to return to the terminal
- Completion: when the agent finishes responding — so you know the task is done even if you stepped away
| Platform | Implementation | Notes |
|---|---|---|
| macOS | osascript |
Built-in, works out of the box |
| Linux | notify-send |
Requires desktop environment (default on Ubuntu/GNOME) |
| Windows | plyer |
Works out of the box |
MCP tools
Once installed, Relay works automatically. You can also call these tools directly inside Claude Code or Codex:
| Tool | Description |
|---|---|
relay__get_stats_tool |
View approval statistics for all action types |
relay__get_recent_decisions_tool |
View recent decision history for a specific action type |
relay__reset_action_type_tool |
Clear history for an action type and rebuild baseline |
CLI
# Install / uninstall both Claude Code and Codex hooks
uvx cc-relay --install-all
uvx cc-relay --uninstall-all
# Advanced: manage one client only
uvx cc-relay --install
uvx cc-relay --install-codex
uvx cc-relay --uninstall
uvx cc-relay --uninstall-codex
# View recent decisions for an action type (default 20)
uvx cc-relay --history bash_write:git
uvx cc-relay --history file_write:code 50
# Clear all history for an action type
uvx cc-relay --reset bash_write:git
Known limitations
Relay hooks do not fire in --dangerously-skip-permissions mode (that mode bypasses the hook mechanism entirely).
Codex PreToolUse hooks cannot pause for an inline approval prompt. When Relay blocks a Codex action, the agent must stop and wait for you; if you explicitly approve the exact action and the agent retries it, Relay flips the recent rejected record to approved and lets that retry through.
Local development
git clone https://github.com/solost23/cc-relay
cd cc-relay
uv sync
uv run pytest
uv run mcp dev cc_relay/server.py
Metadata
Release files for cc-relay 0.3.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cc_relay-0.3.4.tar.gz | 72.7 kB | Without provenance | Details for cc_relay-0.3.4.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cc_relay-0.3.4-py3-none-any.whl | Python 3 | none | any | Details for cc_relay-0.3.4-py3-none-any.whl |
Total release size: 90.8 kB
Release files / cc_relay-0.3.4.tar.gz
| Download URL | cc_relay-0.3.4.tar.gz |
|---|---|
| Size | 72.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f3b0d4593c897b8a11daa98c9227eb79db1c06ff7d0a9ca8457b031e3cd95208
|
|
BLAKE2b-256 checksum How to use checksums |
78c38243eccc4ad5148c9179be50775b05f52052ddef70bc61a41fdd469f55f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / cc_relay-0.3.4-py3-none-any.whl
| Download URL | cc_relay-0.3.4-py3-none-any.whl |
|---|---|
| Size | 18.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
754de6da8fd932d0f2174b5a4337a426cf886e949e32056f12e9e6e997d4f592
|
|
BLAKE2b-256 checksum How to use checksums |
99147d9c6926db8f623e74f674f68eaf9f85239d36d0fa59e119eb867dae981a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for cc-relay 0.3.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.