{"id":34856503,"url":"https://github.com/kenryu42/claude-code-safety-net","last_synced_at":"2026-01-13T20:54:26.600Z","repository":{"id":330471312,"uuid":"1122873619","full_name":"kenryu42/claude-code-safety-net","owner":"kenryu42","description":"A Claude Code plugin that acts as a safety net, catching destructive git and filesystem commands before they execute.","archived":false,"fork":false,"pushed_at":"2026-01-08T18:38:34.000Z","size":588,"stargazers_count":687,"open_issues_count":2,"forks_count":26,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-01-08T22:15:39.535Z","etag":null,"topics":["claude","claude-code","claude-code-plugin","destructive-commands","security"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kenryu42.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-25T17:52:57.000Z","updated_at":"2026-01-08T21:27:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kenryu42/claude-code-safety-net","commit_stats":null,"previous_names":["kenryu42/claude-code-safety-net"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/kenryu42/claude-code-safety-net","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenryu42%2Fclaude-code-safety-net","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenryu42%2Fclaude-code-safety-net/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenryu42%2Fclaude-code-safety-net/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenryu42%2Fclaude-code-safety-net/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kenryu42","download_url":"https://codeload.github.com/kenryu42/claude-code-safety-net/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kenryu42%2Fclaude-code-safety-net/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["claude","claude-code","claude-code-plugin","destructive-commands","security"],"created_at":"2025-12-25T20:01:54.281Z","updated_at":"2026-01-13T20:54:26.594Z","avatar_url":"https://github.com/kenryu42.png","language":"TypeScript","readme":"# Claude Code Safety Net\n\n[![CI](https://github.com/kenryu42/claude-code-safety-net/actions/workflows/ci.yml/badge.svg)](https://github.com/kenryu42/claude-code-safety-net/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/github/kenryu42/claude-code-safety-net/branch/main/graph/badge.svg?token=C9QTION6ZF)](https://codecov.io/github/kenryu42/claude-code-safety-net)\n[![Version](https://img.shields.io/github/v/tag/kenryu42/claude-code-safety-net?label=version\u0026color=blue)](https://github.com/kenryu42/claude-code-safety-net)\n[![Claude Code](https://img.shields.io/badge/Claude%20Code-D27656)](#claude-code-installation)\n[![OpenCode](https://img.shields.io/badge/OpenCode-black)](#opencode-installation)\n[![Gemini CLI](https://img.shields.io/badge/Gemini%20CLI-678AE3)](#gemini-cli-installation)\n[![License: MIT](https://img.shields.io/badge/License-MIT-red.svg)](https://opensource.org/licenses/MIT)\n\n\u003cdiv align=\"center\"\u003e\n\n[![CC Safety Net](./.github/assets/cc-safety-net.png)](./.github/assets/cc-safety-net.png)\n\n\u003c/div\u003e\n\nA Claude Code plugin that acts as a safety net, catching destructive git and filesystem commands before they execute.\n\n## Contents\n\n- [Why This Exists](#why-this-exists)\n- [Why Use This Instead of Permission Deny Rules?](#why-use-this-instead-of-permission-deny-rules)\n- [What About Sandboxing?](#what-about-sandboxing)\n- [Prerequisites](#prerequisites)\n- [Quick Start](#quick-start)\n  - [Claude Code Installation](#claude-code-installation)\n  - [OpenCode Installation](#opencode-installation)\n  - [Gemini CLI Installation](#gemini-cli-installation)\n- [Commands Blocked](#commands-blocked)\n- [Commands Allowed](#commands-allowed)\n- [What Happens When Blocked](#what-happens-when-blocked)\n- [Testing the Hook](#testing-the-hook)\n- [Development](#development)\n- [Custom Rules (Experimental)](#custom-rules-experimental)\n  - [Config File Location](#config-file-location)\n  - [Rule Schema](#rule-schema)\n  - [Matching Behavior](#matching-behavior)\n  - [Examples](#examples)\n  - [Error Handling](#error-handling)\n- [Advanced Features](#advanced-features)\n  - [Strict Mode](#strict-mode)\n  - [Paranoid Mode](#paranoid-mode)\n  - [Shell Wrapper Detection](#shell-wrapper-detection)\n  - [Interpreter One-Liner Detection](#interpreter-one-liner-detection)\n  - [Secret Redaction](#secret-redaction)\n  - [Audit Logging](#audit-logging)\n- [License](#license)\n\n## Why This Exists\n\nWe learned the [hard way](https://www.reddit.com/r/ClaudeAI/comments/1pgxckk/claude_cli_deleted_my_entire_home_directory_wiped/) that instructions aren't enough to keep AI agents in check.\nAfter Claude Code silently wiped out hours of progress with a single `rm -rf ~/` or `git checkout --`, it became evident that **soft** rules in an `CLAUDE.md` or `AGENTS.md` file cannot replace **hard** technical constraints.\nThe current approach is to use a dedicated hook to programmatically prevent agents from running destructive commands.\n\n## Why Use This Instead of Permission Deny Rules?\n\nClaude Code's `.claude/settings.json` supports [deny rules](https://code.claude.com/docs/en/iam#tool-specific-permission-rules) with wildcard matching (e.g., `Bash(git reset --hard:*)`). Here's how this plugin differs:\n\n### At a Glance\n\n| | Permission Deny Rules | Safety Net |\n|---|---|---|\n| **Setup** | Manual configuration required | Works out of the box |\n| **Parsing** | Wildcard pattern matching | Semantic command analysis |\n| **Execution order** | Runs second | Runs first (PreToolUse hook) |\n| **Shell wrappers** | Not handled automatically (must match wrapper forms) | Recursively analyzed (5 levels) |\n| **Interpreter one-liners** | Not handled automatically (must match interpreter forms) | Detected and blocked |\n\n### Permission Rules Have Known Bypass Vectors\n\nEven with wildcard matching, Bash permission patterns are intentionally limited and can be bypassed in many ways:\n\n| Bypass Method | Example |\n|---------------|---------|\n| Options before value | `curl -X GET http://evil.com` bypasses `Bash(curl http://evil.com:*)` |\n| Shell variables | `URL=http://evil.com \u0026\u0026 curl $URL` bypasses URL pattern |\n| Flag reordering | `rm -r -f /` bypasses `Bash(rm -rf:*)` |\n| Extra whitespace | `rm  -rf /` (double space) bypasses pattern |\n| Shell wrappers | `sh -c \"rm -rf /\"` bypasses `Bash(rm:*)` entirely |\n\n### Safety Net Handles What Patterns Can't\n\n| Scenario | Permission Rules | Safety Net |\n|----------|------------------|------------|\n| `git checkout -b feature` (safe) | Blocked by `Bash(git checkout:*)` | Allowed |\n| `git checkout -- file` (dangerous) | Blocked by `Bash(git checkout:*)` | Blocked |\n| `rm -rf /tmp/cache` (safe) | Blocked by `Bash(rm -rf:*)` | Allowed |\n| `rm -r -f /` (dangerous) | Allowed (flag order) | Blocked |\n| `bash -c 'git reset --hard'` | Allowed (wrapper) | Blocked |\n| `python -c 'os.system(\"rm -rf /\")'` | Allowed (interpreter) | Blocked |\n\n### Defense in Depth\n\nPreToolUse hooks run [**before**](https://code.claude.com/docs/en/iam#additional-permission-control-with-hooks) the permission system. This means Safety Net inspects every command first, regardless of your permission configuration. Even if you misconfigure deny rules, Safety Net provides a fallback layer of protection.\n\n**Use both together**: Permission deny rules for quick, user-configurable blocks; Safety Net for robust, bypass-resistant protection that works out of the box.\n\n## What About Sandboxing?\n\nClaude Code offers [native sandboxing](https://code.claude.com/docs/en/sandboxing) that provides OS-level filesystem and network isolation. Here's how it compares to Safety Net:\n\n### Different Layers of Protection\n\n| | Sandboxing | Safety Net |\n|---|---|---|\n| **Enforcement** | OS-level (Seatbelt/bubblewrap) | Application-level (PreToolUse hook) |\n| **Approach** | Containment — restricts filesystem + network access | Command analysis — blocks destructive operations |\n| **Filesystem** | Writes restricted (default: cwd); reads are broad by default | Only destructive operations blocked |\n| **Network** | Domain-based proxy filtering | None |\n| **Git awareness** | None | Explicit rules for destructive git operations |\n| **Bypass resistance** | High — OS enforces boundaries | Lower — analyzes command strings only |\n\n### Why Sandboxing Isn't Enough\n\nSandboxing restricts filesystem + network access, but it doesn't understand whether an operation is destructive within those boundaries. These commands are not blocked by the sandbox boundary:\n\n\u003e [!NOTE]\n\u003e Whether they're auto-run or require confirmation depends on your sandbox mode (auto-allow vs regular permissions), and network access still depends on your allowed-domain policy. Claude Code can also retry a command outside the sandbox via `dangerouslyDisableSandbox` (with user permission); this can be disabled with `allowUnsandboxedCommands: false`.\n\n| Command | Sandboxing | Safety Net |\n|---------|------------|------------|\n| `git reset --hard` | Allowed (within cwd) | **Blocked** |\n| `git checkout -- .` | Allowed (within cwd) | **Blocked** |\n| `git stash clear` | Allowed (within cwd) | **Blocked** |\n| `git push --force` | Allowed (if remote domain is allowed) | **Blocked** |\n| `rm -rf .` | Allowed (within cwd) | **Blocked** |\n\nSandboxing sees `git reset --hard` as a safe operation—it only modifies files within the current directory. But you just lost all uncommitted work.\n\n### When to Use Sandboxing Instead\n\nSandboxing is the better choice when your primary concern is:\n\n- **Prompt injection attacks** — Reduces exfiltration risk by restricting outbound domains (depends on your allowed-domain policy)\n- **Malicious dependencies** — Limits filesystem writes and network access by default (subject to your sandbox configuration)\n- **Untrusted code execution** — OS-level containment is stronger than pattern matching\n- **Network control** — Safety Net has no network protection\n\n### Recommended: Use Both\n\nThey protect against different threats:\n\n- **Sandboxing** contains blast radius — even if something goes wrong, damage is limited to cwd and approved network domains\n- **Safety Net** prevents footguns — catches git-specific mistakes that are technically \"safe\" from the sandbox's perspective\n\nRunning both together provides defense-in-depth. Sandboxing handles unknown threats; Safety Net handles known destructive patterns that sandboxing permits.\n\n## Prerequisites\n\n- **Node.js**: Version 18 or higher is required to run this plugin\n\n## Quick Start\n\n### Claude Code Installation\n\n```bash\n/plugin marketplace add kenryu42/cc-marketplace\n/plugin install safety-net@cc-marketplace\n```\n\n\u003e [!NOTE]\n\u003e After installing the plugin, you need to restart your Claude Code for it to take effect.\n\n### Claude Code Auto-Update\n\n1. Run `/plugin` → Select `Marketplaces` → Choose `cc-marketplace` → Enable auto-update\n\n---\n\n### OpenCode Installation\n\n**Option A: Let an LLM do it**\n\nPaste this into any LLM agent (Claude Code, OpenCode, Cursor, etc.):\n\n```\nInstall the cc-safety-net plugin in `~/.config/opencode/opencode.json` (or `.jsonc`) according to the schema at: https://opencode.ai/config.json\n```\n\n**Option B: Manual setup**\n\n1. **Add the plugin to your config** `~/.config/opencode/opencode.json` (or `.jsonc`):\n\n  ```json\n  {\n    \"plugin\": [\"cc-safety-net\"]\n  }\n  ```\n\n---\n\n### Gemini CLI Installation\n\n```bash\ngemini extensions install https://github.com/kenryu42/gemini-safety-net\n```\n\n\u003e [!IMPORTANT]\n\u003e You need to set the following settings in `.gemini/settings.json` to enable hooks:\n\u003e ```json\n\u003e {\n\u003e   \"tools\": {\n\u003e     \"enableHooks\": true\n\u003e   }\n\u003e }\n\u003e ```\n\n## Commands Blocked\n\n| Command Pattern | Why It's Dangerous |\n|-----------------|-------------------|\n| git checkout -- files | Discards uncommitted changes permanently |\n| git checkout \\\u003cref\\\u003e -- \\\u003cpath\\\u003e | Overwrites working tree with ref version |\n| git restore files | Discards uncommitted changes |\n| git restore --worktree | Explicitly discards working tree changes |\n| git reset --hard | Destroys all uncommitted changes |\n| git reset --merge | Can lose uncommitted changes |\n| git clean -f | Removes untracked files permanently |\n| git push --force / -f | Destroys remote history |\n| git branch -D | Force-deletes branch without merge check |\n| git stash drop | Permanently deletes stashed changes |\n| git stash clear | Deletes ALL stashed changes |\n| git worktree remove --force | Force-deletes worktree without checking for changes |\n| rm -rf (paths outside cwd) | Recursive file deletion outside the current directory |\n| rm -rf / or ~ or $HOME | Root/home deletion is extremely dangerous |\n| find ... -delete | Permanently removes files matching criteria |\n| xargs rm -rf | Dynamic input makes targets unpredictable |\n| xargs \\\u003cshell\\\u003e -c | Can execute arbitrary commands |\n| parallel rm -rf | Dynamic input makes targets unpredictable |\n| parallel \\\u003cshell\\\u003e -c | Can execute arbitrary commands |\n\n## Commands Allowed\n\n| Command Pattern | Why It's Safe |\n|-----------------|--------------|\n| git checkout -b branch | Creates new branch |\n| git checkout --orphan | Creates orphan branch |\n| git restore --staged | Only unstages, doesn't discard |\n| git restore --help/--version | Help/version output |\n| git branch -d | Safe delete with merge check |\n| git clean -n / --dry-run | Preview only |\n| git push --force-with-lease | Safe force push |\n| rm -rf /tmp/... | Temp directories are ephemeral |\n| rm -rf /var/tmp/... | System temp directory |\n| rm -rf $TMPDIR/... | User's temp directory |\n| rm -rf ./... (within cwd) | Limited to current working directory |\n\n## What Happens When Blocked\n\nWhen a destructive command is detected, the plugin blocks the tool execution and provides a reason.\n\nExample output:\n```text\nBLOCKED by Safety Net\n\nReason: git checkout -- discards uncommitted changes permanently. Use 'git stash' first.\n\nCommand: git checkout -- src/main.py\n\nIf this operation is truly needed, ask the user for explicit permission and have them run the command manually.\n```\n\n## Testing the Hook\n\nYou can manually test the hook by attempting to run blocked commands in Claude Code:\n\n```bash\n# This should be blocked\ngit checkout -- README.md\n\n# This should be allowed\ngit checkout -b test-branch\n```\n\n## Development\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.\n\n## Custom Rules (Experimental)\n\nBeyond the built-in protections, you can define your own blocking rules to enforce team conventions or project-specific safety policies.\n\n\u003e [!TIP]\n\u003e Use `/set-custom-rules` to create custom rules interactively with natural language.\n\n### Quick Example\n\nCreate `.safety-net.json` in your project root:\n\n```json\n{\n  \"version\": 1,\n  \"rules\": [\n    {\n      \"name\": \"block-git-add-all\",\n      \"command\": \"git\",\n      \"subcommand\": \"add\",\n      \"block_args\": [\"-A\", \"--all\", \".\"],\n      \"reason\": \"Use 'git add \u003cspecific-files\u003e' instead of blanket add.\"\n    }\n  ]\n}\n```\n\nNow `git add -A`, `git add --all`, and `git add .` will be blocked with your custom message.\n\n### Config File Location\n\nConfig files are loaded from two scopes and merged:\n\n1. **User scope**: `~/.cc-safety-net/config.json` (always loaded if exists)\n2. **Project scope**: `.safety-net.json` in the current working directory (loaded if exists)\n\n**Merging behavior**:\n- Rules from both scopes are combined\n- If the same rule name exists in both scopes, **project scope wins**\n- Rule name comparison is case-insensitive (`MyRule` and `myrule` are considered duplicates)\n\nThis allows you to define personal defaults in user scope while letting projects override specific rules.\n\nIf no config file is found in either location, only built-in rules apply.\n\n### Config Schema\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `version` | integer | Yes | Schema version (must be `1`) |\n| `rules` | array | No | List of custom blocking rules (defaults to empty) |\n\n### Rule Schema\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `name` | string | Yes | Unique identifier (letters, numbers, hyphens, underscores; max 64 chars) |\n| `command` | string | Yes | Base command to match (e.g., `git`, `npm`, `docker`) |\n| `subcommand` | string | No | Subcommand to match (e.g., `add`, `install`). If omitted, matches any. |\n| `block_args` | array | Yes | Arguments that trigger the block (at least one required) |\n| `reason` | string | Yes | Message shown when blocked (max 256 chars) |\n\n### Matching Behavior\n\n- **Commands** are normalized to basename (`/usr/bin/git` → `git`)\n- **Subcommand** is the first non-option argument after the command\n- **Arguments** are matched literally (no regex, no glob), with short option expansion\n- A command is blocked if **any** argument in `block_args` is present\n- **Short options** are expanded: `-Ap` matches `-A` (bundled flags are unbundled)\n- **Long options** use exact match: `--all-files` does NOT match `--all`\n- Custom rules only add restrictions—they cannot bypass built-in protections\n\n#### Known Limitations\n\n- **Short option expansion**: `-Cfoo` is treated as `-C -f -o -o`, not `-C foo`. Blocking `-f` may false-positive on attached option values.\n\n### Examples\n\n#### Block global npm installs\n\n```json\n{\n  \"version\": 1,\n  \"rules\": [\n    {\n      \"name\": \"block-npm-global\",\n      \"command\": \"npm\",\n      \"subcommand\": \"install\",\n      \"block_args\": [\"-g\", \"--global\"],\n      \"reason\": \"Global npm installs can cause version conflicts. Use npx or local install.\"\n    }\n  ]\n}\n```\n\n#### Block dangerous docker commands\n\n```json\n{\n  \"version\": 1,\n  \"rules\": [\n    {\n      \"name\": \"block-docker-system-prune\",\n      \"command\": \"docker\",\n      \"subcommand\": \"system\",\n      \"block_args\": [\"prune\"],\n      \"reason\": \"docker system prune removes all unused data. Use targeted cleanup instead.\"\n    }\n  ]\n}\n```\n\n#### Multiple rules\n\n```json\n{\n  \"version\": 1,\n  \"rules\": [\n    {\n      \"name\": \"block-git-add-all\",\n      \"command\": \"git\",\n      \"subcommand\": \"add\",\n      \"block_args\": [\"-A\", \"--all\", \".\", \"-u\", \"--update\"],\n      \"reason\": \"Use 'git add \u003cspecific-files\u003e' instead of blanket add.\"\n    },\n    {\n      \"name\": \"block-npm-global\",\n      \"command\": \"npm\",\n      \"subcommand\": \"install\",\n      \"block_args\": [\"-g\", \"--global\"],\n      \"reason\": \"Use npx or local install instead of global.\"\n    }\n  ]\n}\n```\n\n### Error Handling\n\nCustom rules use **silent fallback** error handling. If your config file is invalid, the safety net silently falls back to built-in rules only:\n\n| Scenario | Behavior |\n|----------|----------|\n| Config file not found | Silent — use built-in rules only |\n| Empty config file | Silent — use built-in rules only |\n| Invalid JSON syntax | Silent — use built-in rules only |\n| Missing required field | Silent — use built-in rules only |\n| Invalid field format | Silent — use built-in rules only |\n| Duplicate rule name | Silent — use built-in rules only |\n\n\n\u003e [!IMPORTANT]  \n\u003e If you add or modify custom rules manually, always validate them with `npx -y cc-safety-net --verify-config` or `/verify-custom-rules` slash command in your coding agent.\n\n### Block Output Format\n\nWhen a custom rule blocks a command, the output includes the rule name:\n\n```text\nBLOCKED by Safety Net\n\nReason: [block-git-add-all] Use 'git add \u003cspecific-files\u003e' instead of blanket add.\n\nCommand: git add -A\n```\n\n## Advanced Features\n\n### Strict Mode\n\nBy default, unparseable commands are allowed through. Enable strict mode to fail-closed\nwhen the hook input or shell command cannot be safely analyzed (e.g., invalid JSON,\nunterminated quotes, malformed `bash -c` wrappers):\n\n```bash\nexport SAFETY_NET_STRICT=1\n```\n\n### Paranoid Mode\n\nParanoid mode enables stricter safety checks that may be disruptive to normal workflows.\nYou can enable it globally or via focused toggles:\n\n```bash\n# Enable all paranoid checks\nexport SAFETY_NET_PARANOID=1\n\n# Or enable specific paranoid checks\nexport SAFETY_NET_PARANOID_RM=1\nexport SAFETY_NET_PARANOID_INTERPRETERS=1\n```\n\nParanoid behavior:\n\n- **rm**: blocks non-temp `rm -rf` even within the current working directory.\n- **interpreters**: blocks interpreter one-liners like `python -c`, `node -e`, `ruby -e`,\n  and `perl -e` (these can hide destructive commands).\n\n### Shell Wrapper Detection\n\nThe guard recursively analyzes commands wrapped in shells:\n\n```bash\nbash -c 'git reset --hard'    # Blocked\nsh -lc 'rm -rf /'             # Blocked\n```\n\n### Interpreter One-Liner Detection\n\nDetects destructive commands hidden in Python/Node/Ruby/Perl one-liners:\n\n```bash\npython -c 'import os; os.system(\"rm -rf /\")'  # Blocked\n```\n\n### Secret Redaction\n\nBlock messages automatically redact sensitive data (tokens, passwords, API keys) to prevent leaking secrets in logs.\n\n### Audit Logging\n\nAll blocked commands are logged to `~/.cc-safety-net/logs/\u003csession_id\u003e.jsonl` for audit purposes:\n\n```json\n{\"ts\": \"2025-01-15T10:30:00Z\", \"command\": \"git reset --hard\", \"segment\": \"git reset --hard\", \"reason\": \"...\", \"cwd\": \"/path/to/project\"}\n```\n\nSensitive data in log entries is automatically redacted.\n\n## License\n\nMIT\n","funding_links":[],"categories":["TypeScript","Skills \u0026 Plugins","Claude Plugins","Defense \u0026 Security Controls"],"sub_categories":["Agent Runtime Security \u0026 Sandboxing"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkenryu42%2Fclaude-code-safety-net","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkenryu42%2Fclaude-code-safety-net","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkenryu42%2Fclaude-code-safety-net/lists"}