Rafter is a dual-implementation (Node.js + Python) security CLI for AI coding agents. Both implementations have full feature parity and must stay in sync.
# Node.js
cd node && pnpm install && pnpm test
# Python
cd python && poetry install && pytest├── node/ # TypeScript implementation (@rafter-security/cli on npm)
│ ├── src/
│ │ ├── commands/ # CLI commands (commander.js)
│ │ │ ├── agent/ # agent init/scan/exec/audit/config
│ │ │ ├── mcp/ # MCP server (server.ts exports createServer)
│ │ │ ├── scan/ # scan local/remote
│ │ │ ├── hook/ # hook pretool/commit
│ │ │ ├── policy/ # policy export/validate
│ │ │ ├── ci/ # ci init
│ │ │ ├── brief.ts # knowledge delivery
│ │ │ ├── notify.ts # Slack/Discord webhooks
│ │ │ └── report.ts # HTML security reports
│ │ ├── core/ # Shared logic
│ │ │ ├── command-interceptor.ts # Risk classification + policy enforcement
│ │ │ ├── audit-logger.ts # JSONL audit trail
│ │ │ └── config-manager.ts # .rafter.yml + global config
│ │ └── scanners/
│ │ ├── betterleaks.ts # Betterleaks binary integration
│ │ ├── secret-patterns.ts # DEFAULT_SECRET_PATTERNS array (21+ patterns)
│ │ └── regex-scanner.ts # RegexScanner class (imports secret-patterns)
│ └── tests/ # Vitest test files
├── python/ # Python implementation (rafter-cli on PyPI)
│ ├── rafter_cli/
│ │ ├── commands/ # CLI commands (typer)
│ │ ├── core/ # Mirrors node/src/core/
│ │ └── scanners/ # secret_patterns.py + regex_scanner.py + betterleaks.py
│ └── tests/ # pytest test files
├── shared-docs/ # Canonical specs (both implementations follow these)
│ └── CLI_SPEC.md # Output contracts, exit codes, JSON schemas
├── recipes/ # Copy-paste integration guides per platform
├── vscode/ # VS Code extension
├── github-action/ # GitHub Action wrapper
└── .github/workflows/ # CI: test + publish to npm/PyPI
Dual implementation: Every feature exists in both Node and Python. Versions must match (node/package.json ↔ python/pyproject.toml). CLI_SPEC.md is the source of truth for behavior.
8-platform support: Platform-specific installation logic lives in node/src/commands/agent/init.ts (functions like installCursorMcp(), installGeminiMcp(), etc.). rafter agent init --with-<platform> calls the corresponding install function.
Risk classification: Commands are classified into 4 tiers (critical/high/medium/low) by pattern matching in command-interceptor.ts. Policy files (.rafter.yml) can override defaults.
Secret scanning: Dual-engine — tries Betterleaks binary first (higher accuracy), falls back to built-in regex patterns (21+ patterns, zero dependencies). Deterministic for a given version. Betterleaks is the gitleaks successor maintained by the original gitleaks authors. Existing installs with a leftover ~/.rafter/bin/gitleaks are detected by agent verify/status so users get an upgrade hint, but the legacy CLI flags (--with-gitleaks, --engine gitleaks, update-gitleaks) have been removed.
MCP server: rafter mcp serve exposes 4 tools (scan_secrets, evaluate_command, read_audit_log, get_config) and 3 resources (rafter://config, rafter://policy, rafter://docs) over stdio.
- Create
node/src/commands/<name>.tsexporting acreateXCommand()function - Register it in
node/src/index.ts - Create
python/rafter_cli/commands/<name>.py - Register it in
python/rafter_cli/__main__.py - Add tests in both
node/tests/andpython/tests/ - Update
shared-docs/CLI_SPEC.mdwith output contract
- Add the regex to
node/src/scanners/secret-patterns.tsin theDEFAULT_SECRET_PATTERNSarray - Add the same regex to
python/rafter_cli/scanners/secret_patterns.py - Add test cases with real-looking (but fake) secrets in both test suites
- Pattern format:
{ name, severity, regex, description }
- Add an install function in
node/src/commands/agent/init.ts(follow existinginstallCursorMcp()pattern) - Add corresponding logic in
python/rafter_cli/commands/agent.py - Add
--with-<platform>flag toagent initin both implementations - Add a recipe in
recipes/<platform>.md - Update README.md platform list
# Node: Vitest (fast, parallel)
cd node && pnpm test # all tests
cd node && npx vitest run tests/mcp-server-integration.test.ts # single file
# Python: pytest
cd python && pytest # all tests
cd python && pytest tests/test_mcp_server.py -v # single file# Node
cd node && pnpm run build # TypeScript → dist/
# Python
cd python && python -m build # wheel + sdistBoth node/package.json and python/pyproject.toml must have the same version. CI enforces this via validate-release.yml.
All scan commands write results to stdout as JSON, status messages to stderr, and use documented exit codes:
0— success / no findings1— findings detected / general error2— scan not found / invalid input
See shared-docs/CLI_SPEC.md for full JSON schemas and exit code matrix.
We welcome AI-assisted contributions. If your PR was substantially written by an AI tool, add a Co-Authored-By trailer and note it in the PR description. We evaluate contributions on quality, not authorship.