Features: - 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents) - RalphLoop autonomous agent integration - Multi-AI consultation (Qwen) - Agent management system with sync capabilities - Custom hooks for session management - MCP servers integration - Plugin marketplace setup - Comprehensive installation script Components: - Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc. - Agents: 100+ agents across engineering, marketing, product, etc. - Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger - Commands: /brainstorm, /write-plan, /execute-plan - MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread - Binaries: ralphloop wrapper Installation: ./supercharge.sh
14 KiB
Contributing to Claude Code Safety Net
First off, thanks for taking the time to contribute! This document provides guidelines and instructions for contributing to cc-safety-net.
Table of Contents
- Code of Conduct
- Before You Start: Proposing New Features
- Getting Started
- Project Structure
- Development Workflow
- Making Changes
- Pull Request Process
- Publishing
- Getting Help
Code of Conduct
Be respectful, inclusive, and constructive. We're all here to make better tools together.
Before You Start: Proposing New Features
Please open an issue to discuss new features before implementing them.
This project has a focused scope: preventing coding agents from making accidental mistakes that cause data loss (e.g., rm -rf ~/, git reset --hard). It is NOT a general security hardening tool or an attack prevention system.
Why Discuss First?
- Scope alignment — Your idea might be great but outside the project's scope
- Approach feedback — We can suggest the best way to implement it
- Avoid wasted effort — Save time for both you and maintainers
When to Open an Issue First
| Scenario | Open Issue First? |
|---|---|
| New detection rule (git, rm, etc.) | Yes |
| New command category to block | Yes |
| Architectural changes | Yes |
| New configuration options | Yes |
| Typo/documentation fixes | No, just PR |
| Small bug fixes with obvious solution | No, just PR |
What to Include in Your Proposal
- What you want to add/change
- Why it fits the project scope (preventing accidental data loss)
- Real-world scenario where this would help
- Any trade-offs you've considered
A quick 5-minute issue can save hours of implementation time on both sides.
Getting Started
Prerequisites
- Bun - Required runtime and package manager (install guide)
- Claude Code or OpenCode - For testing the plugin
Development Setup
# Clone the repository
git clone https://github.com/kenryu42/claude-code-safety-net.git
cd claude-code-safety-net
# Install dependencies
bun install
# Build for distribution
bun run build
# Check for all lint errors, type errors, dead code and run tests
bun run check
Testing Your Changes Locally
Claude Code
-
Build the project:
bun run build -
Disable the safety-net plugin in Claude Code (if installed) and exit Claude Code completely.
-
Run Claude Code with the local plugin:
claude --plugin-dir . -
Test blocked commands to verify your changes:
# This should be blocked git checkout -- README.md # This should be allowed git checkout -b test-branch
Note
See the official documentation for more details on testing plugins locally.
OpenCode
-
Build the project:
bun run build -
Update your OpenCode config (
~/.config/opencode/opencode.jsonoropencode.jsonc):{ "plugin": [ "file:///absolute/path/to/cc-safety-net/dist/index.js" ] }For example, if your project is at
/Users/yourname/projects/cc-safety-net:{ "plugin": [ "file:///Users/yourname/projects/cc-safety-net/dist/index.js" ] }
Note
Remove
"cc-safety-net"from the plugin array if it exists, to avoid conflicts with the npm version. Or comment out the line if you're usingopencode.jsonc.
-
Restart OpenCode to load the changes.
-
Verify the plugin is loaded: Run
/statusand confirm that the plugin name appears asdist. -
Test blocked commands to verify your changes:
# This should be blocked git checkout -- README.md # This should be allowed git checkout -b test-branch
Note
See the official documentation for more details on OpenCode plugins.
Project Structure
claude-code-safety-net/
├── .claude-plugin/
│ ├── plugin.json # Plugin metadata
│ └── marketplace.json # Marketplace config
├── .github/
│ ├── workflows/ # CI/CD workflows
│ │ ├── ci.yml
│ │ ├── lint-github-actions-workflows.yml
│ │ └── publish.yml
│ └── pull_request_template.md
├── .husky/
│ └── pre-commit # Pre-commit hook (knip + lint-staged)
├── assets/
│ └── cc-safety-net.schema.json # JSON schema for config validation
├── ast-grep/
│ ├── rules/ # AST-grep rule definitions
│ ├── rule-tests/ # Rule test cases
│ └── utils/ # Shared utilities
├── commands/
│ ├── set-custom-rules.md # Slash command: configure custom rules
│ └── verify-custom-rules.md # Slash command: validate config
├── hooks/
│ └── hooks.json # Hook definitions
├── scripts/
│ ├── build-schema.ts # Generate JSON schema
│ ├── generate-changelog.ts # Changelog generation
│ └── publish.ts # Release automation
├── src/
│ ├── index.ts # OpenCode plugin export
│ ├── types.ts # Shared type definitions
│ ├── bin/
│ │ └── cc-safety-net.ts # Claude Code CLI entry point
│ └── core/
│ ├── analyze.ts # Main analysis orchestration
│ ├── analyze/ # Analysis submodules
│ │ ├── analyze-command.ts # Command analysis entry
│ │ ├── constants.ts # Shared constants
│ │ ├── dangerous-text.ts # Text pattern detection
│ │ ├── find.ts # find command analysis
│ │ ├── interpreters.ts # Interpreter one-liner detection
│ │ ├── parallel.ts # parallel command analysis
│ │ ├── rm-flags.ts # rm flag parsing
│ │ ├── segment.ts # Command segment analysis
│ │ ├── shell-wrappers.ts # Shell wrapper detection
│ │ ├── tmpdir.ts # Temp directory detection
│ │ └── xargs.ts # xargs command analysis
│ ├── audit.ts # Audit logging
│ ├── config.ts # Config loading
│ ├── custom-rules-doc.ts # Custom rules documentation
│ ├── env.ts # Environment variable utilities
│ ├── format.ts # Output formatting
│ ├── rules-git.ts # Git subcommand analysis
│ ├── rules-rm.ts # rm command analysis
│ ├── rules-custom.ts # Custom rule evaluation
│ ├── shell.ts # Shell parsing utilities
│ └── verify-config.ts # Config validator
├── tests/
│ ├── helpers.ts # Test utilities
│ ├── analyze-coverage.test.ts
│ ├── audit.test.ts
│ ├── config.test.ts
│ ├── custom-rules.test.ts
│ ├── custom-rules-integration.test.ts
│ ├── edge-cases.test.ts
│ ├── find.test.ts
│ ├── parsing-helpers.test.ts
│ ├── rules-git.test.ts
│ ├── rules-rm.test.ts
│ └── verify-config.test.ts
├── .lintstagedrc.json # Lint-staged config (biome + ast-grep)
├── biome.json # Linter/formatter config
├── knip.ts # Dead code detection config
├── package.json # Project config
├── sgconfig.yml # AST-grep config
├── tsconfig.json # TypeScript config
├── tsconfig.typecheck.json # Type-check only config
├── AGENTS.md # AI agent guidelines
├── CLAUDE.md # Claude Code context
└── README.md # Project documentation
| Module | Purpose |
|---|---|
analyze.ts |
Main entry, command analysis orchestration |
analyze/ |
Submodules for specific analysis tasks (find, xargs, parallel, interpreters, etc.) |
audit.ts |
Audit logging to ~/.cc-safety-net/logs/ |
config.ts |
Config loading (.safety-net.json, ~/.cc-safety-net/config.json) |
env.ts |
Environment variable utilities (envTruthy) |
format.ts |
Output formatting (formatBlockedMessage) |
rules-git.ts |
Git rules (checkout, restore, reset, clean, push, branch, stash) |
rules-rm.ts |
rm analysis (cwd-relative, temp paths, root/home detection) |
rules-custom.ts |
Custom rule matching |
shell.ts |
Shell parsing (splitShellCommands, shlexSplit, stripWrappers) |
verify-config.ts |
Config file validation |
Development Workflow
Build Commands
# Run all checks (lint, type check, dead code, ast-grep scan, tests)
bun run check
# Individual commands
bun run lint # Lint + format (Biome)
bun run typecheck # Type check
bun run knip # Dead code detection
bun run sg:scan # AST pattern scan
bun test # Run tests
# Run specific test
bun test tests/rules-git.test.ts
# Run tests matching pattern
bun test --test-name-pattern "checkout"
# Build for distribution
bun run build
Code Style & Conventions
| Convention | Rule |
|---|---|
| Runtime | Bun |
| Package Manager | bun only (bun install, bun run) |
| Formatter/Linter | Biome |
| Type Hints | Required on all functions |
| Type Syntax | type | null preferred over type | undefined |
| File Naming | kebab-case (e.g., rules-git.ts, not rulesGit.ts) |
| Function Naming | camelCase for functions, PascalCase for types/interfaces |
| Constants | SCREAMING_SNAKE_CASE for reason constants |
| Imports | Relative imports within package |
Examples:
// Good
export function analyzeCommand(
command: string,
options?: { strict?: boolean }
): string | null {
// ...
}
// Bad
export function analyzeCommand(command, options) { // Missing type hints
// ...
}
Anti-Patterns (Do Not Do):
- Using npm/yarn/pnpm instead of bun
- Suppressing type errors with
@ts-ignoreorany - Skipping tests for new rules
- Modifying version in
package.jsondirectly
Making Changes
Adding a Git Rule
-
Add reason constant in
src/core/rules-git.ts:const REASON_MY_RULE = "git my-command does something dangerous. Use safer alternative."; -
Add detection logic in
analyzeGit():if (subcommand === "my-command" && tokens.includes("--dangerous-flag")) { return REASON_MY_RULE; } -
Add tests in
tests/rules-git.test.ts:describe("git my-command", () => { test("dangerous flag blocked", () => { assertBlocked("git my-command --dangerous-flag", "dangerous"); }); test("safe flag allowed", () => { assertAllowed("git my-command --safe-flag"); }); }); -
Run checks:
bun run check
Adding an rm Rule
- Add logic in
src/core/rules-rm.ts - Add tests in
tests/rules-rm.test.ts - Run checks:
bun run check
Adding Other Command Rules
-
Add reason constant in
src/core/analyze.ts:const REASON_MY_COMMAND = "my-command is dangerous because..."; -
Add detection in
analyzeSegment() -
Add tests in the appropriate test file
-
Run checks:
bun run check
Edge Cases to Test
When adding rules, ensure you test these edge cases:
- Shell wrappers:
bash -c '...',sh -lc '...' - Sudo/env prefixes:
sudo git ...,env VAR=1 git ... - Pipelines:
echo ok | git reset --hard - Interpreter one-liners:
python -c 'os.system("...")' - Xargs/parallel:
find . | xargs rm -rf - Busybox:
busybox rm -rf /
Pull Request Process
- Fork the repository and create your branch from
main - Make changes following the conventions above
- Run all checks locally:
bun run check # Must pass with no errors - Test in Claude Code and OpenCode using the local plugin method described above
- Commit with clear, descriptive messages:
- Use present tense ("Add rule" not "Added rule")
- Reference issues if applicable ("Fix #123")
- Push to your fork and create a Pull Request
- Describe your changes clearly in the PR description
PR Checklist
- Code follows project conventions (type hints, naming, etc.)
bun run checkpasses (lint, types, dead code, tests)- Tests added for new rules
- Tested locally with Claude Code and Opencode
- Updated documentation if needed (README, AGENTS.md)
- No version changes in
package.json
Publishing
Important: Version bumping and releases are handled by maintainers only.
- Never modify the version in
package.jsonorplugin.jsondirectly - Maintainers handle versioning, tagging, and releases
Getting Help
- Project Knowledge: Check
CLAUDE.mdorAGENTS.mdfor detailed architecture and conventions - Code Patterns: Review existing implementations in
src/core/ - Test Patterns: See
tests/helpers.tsfor test utilities - Issues: Open an issue for bugs or feature requests
Thank you for contributing to Claude Code Safety Net! Your efforts help keep AI-assisted coding safer for everyone.