Skip to content

Latest commit

 

History

History
108 lines (82 loc) · 8.26 KB

File metadata and controls

108 lines (82 loc) · 8.26 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project

Sage (Safety for Agents) — a lightweight Agent Detection & Response (ADR) layer for AI agents that guards commands, files, and web requests. Supports Claude Code, Cursor, and OpenClaw. See doc/spec.md for the full specification.

Commands

pnpm install                               # Install all dependencies
pnpm test                                    # Run all tests (builds automatically, E2E excluded)
pnpm test -- --reporter=verbose              # Verbose test output
pnpm test -- packages/core/src/__tests__/extractors.test.ts  # Single test file
pnpm test -- -t "test name"                  # Run single test by name
pnpm test:e2e                                # All E2E tests (Claude Code + OpenClaw + Cursor + VS Code)
pnpm test:e2e:claude                         # Claude Code E2E only
pnpm test:e2e:openclaw                       # OpenClaw E2E only (requires gateway + token)
pnpm test:e2e:cursor                         # Cursor extension E2E only
pnpm test:e2e:vscode                         # VS Code extension E2E only
pnpm build                                  # Build all packages (tsc + esbuild bundle)
pnpm build:sea                              # Build standalone SEA binaries (requires official Node.js, not Homebrew)
pnpm lint                                   # Lint with Biome
pnpm lint:fix                               # Lint + auto-fix
pnpm check                                  # Type check all packages
pnpm changeset                              # Create a changeset for your changes
pnpm run version                            # Apply changesets: bump versions, generate changelogs, sync manifests
bash scripts/pre-release-audit.sh           # Pre-release content audit (requires .gitleaks.toml symlink)

Repository Structure

TypeScript monorepo with five packages:

  • packages/core/@gendigital/sage-core: Platform-agnostic detection engine (extractors, heuristics, URL check client, decision engine, caching)
  • packages/claude-code/@gendigital/sage-claude-code: Claude Code hook entry points (pre-tool-use, session-start)
  • packages/openclaw/@gendigital/sage-openclaw: OpenClaw plugin connector (in-process hook, native approval). resources/ is gitignored — generated by pnpm build via sync-assets.mjs.
  • packages/opencode/@gendigital/sage-opencode: OpenCode plugin connector
  • packages/extension/sage-cursor: Cursor and VS Code extensions
  • threats/ — YAML threat definitions (data, not code). dummy.yaml contains harmless canary rules for E2E testing (excluded from distribution by sync-assets filters)
  • allowlists/ — Trusted domain allowlists
  • hooks/hooks.json registering hooks with Claude Code

Test Tiers

Tier Scope Files Requires
1 — Unit Core library functions packages/core/src/__tests__/*.test.ts pnpm dev deps
2 — Integration Hook/plugin entry points packages/claude-code/src/__tests__/, packages/openclaw/src/__tests__/e2e-integration.test.ts pnpm dev deps
3 — E2E (Claude Code) Full plugin in Claude CLI packages/claude-code/src/__tests__/e2e.test.ts claude CLI + ANTHROPIC_API_KEY
3 — E2E (OpenClaw) Full plugin in OpenClaw gateway packages/openclaw/src/__tests__/e2e.test.ts OpenClaw gateway (token read from ~/.openclaw/openclaw.json)
3 — E2E (Cursor extension) Sage extension in Cursor Extension Host packages/extension/src/__tests__/e2e.test.ts Installed Cursor executable
3 — E2E (VS Code extension) Sage extension in VS Code Extension Host packages/extension/src/__tests__/e2e.test.ts Installed VS Code executable

pnpm test runs tiers 1–2 automatically (builds via globalSetup before running). Tier 3 (E2E) is excluded — run with pnpm test:e2e (all), pnpm test:e2e:claude, pnpm test:e2e:openclaw, pnpm test:e2e:cursor, or pnpm test:e2e:vscode.

Claude Code E2E prerequisites: claude CLI in PATH, valid ANTHROPIC_API_KEY, and Sage must not be installed via the Claude Code marketplace (duplicate-plugin conflict with --plugin-dir).

OpenClaw E2E prerequisites: Running OpenClaw gateway with Sage installed. Auth token is read from ~/.openclaw/openclaw.json automatically (override via OPENCLAW_GATEWAY_TOKEN env var). See docs/development.md for gateway setup.

Cursor / VS Code E2E prerequisites: Installed Cursor / VS Code executables. Cursor headless agent coverage in pnpm test:e2e:cursor additionally requires the agent CLI (PATH or SAGE_AGENT_PATH) plus valid auth (agent login or CURSOR_API_KEY); if unavailable, only that headless sub-suite is skipped. Optional executable overrides: SAGE_CURSOR_PATH, SAGE_AGENT_PATH, SAGE_VSCODE_PATH, VSCODE_EXECUTABLE_PATH.

Architecture

This is a multi-platform plugin with three connectors and a shared core:

  1. Claude Code Connector (packages/claude-code/src/) — pre-tool-use.ts reads tool call JSON from stdin, orchestrates core, outputs verdict JSON to stdout. session-start.ts scans installed plugins for threats. Both are bundled by esbuild into single CJS files.

  2. OpenClaw Connector (packages/openclaw/src/) — In-process plugin using api.on('before_tool_call'). Flagged actions use OpenClaw's native requireApproval mechanism with an onResolution callback that persists allowlist entries. Bundled into a single CJS file.

  3. Core Library (packages/core/src/) — Platform-agnostic TypeScript library:

    • extractors.ts — Extracts URLs, commands, file paths from tool inputs
    • threat-loader.ts — Loads YAML threat definitions from threats/
    • heuristics.ts — Matches extracted artifacts against threat patterns
    • clients/url-check.ts — HTTP client for URL reputation checking and endpoint resolver
    • engine.ts — Decision engine combining signals into a Verdict
    • cache.ts — JSON file verdict cache with TTLs
    • allowlist.ts — User allowlist management
    • trusted-domains.ts — Trusted domain loading and matching
    • audit-log.ts — JSONL audit log for verdicts
    • installation-id.ts — Persistent installation UUID (~/.sage/installation-id)
    • version-check.ts — Version check via POST with environment context
    • session-start.ts — Session start orchestrator (scan + version check)
    • plugin-scanner.ts — Plugin file scanning for threats
    • plugin-scan-cache.ts — Plugin scan result cache
  4. Plugin Confighooks/hooks.json registers hooks, .claude-plugin/plugin.json is the plugin manifest, skills/security-awareness/SKILL.md provides security knowledge to Claude.

Data flow (Claude Code): Hook stdin → extract artifacts → check allowlist → check cache → heuristics + URL check → DecisionEngine → cache result → audit log → hook stdout JSON

Data flow (OpenClaw): before_tool_call event → extract artifacts → check allowlist → check cache → heuristics + URL check → DecisionEngine → cache result → audit log → block/pass

Key Conventions

  • Never skip git hooks. Do not use --no-verify on git commit or git push. The hooks run gitleaks, lint, build, typecheck, and tests. If a hook fails, fix the underlying issue.
  • All detection patterns are data (YAML in threats/), not hardcoded
  • Fail-open: every internal error path returns an allow verdict; extension hooks always exit with code 0
  • Verdicts use three decisions: allow, deny, ask with confidence scoring
  • Sensitivity presets: paranoid (0.70), balanced (0.85), relaxed (0.95)
  • Merge precedence when multiple signals fire: deny > ask > allow
  • URL check works without API key for basic malware/phishing detection
  • Standalone binary via Node.js SEA for distribution (no runtime deps)
  • Naming: YAML/JSON data uses snake_case (threat_id, source_file); TypeScript interfaces use camelCase (threatId, sourceFile). Conversion functions bridge the two at serialization boundaries.

Pre-PR Checklist

Before creating a pull request, run the @"code-simplifier:code-simplifier (agent)" subagent on all changed files to review for clarity, consistency, and maintainability improvements. Apply any suggested changes before opening the PR.