Skip to content

fireharp/overseer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

overseer

A Go CLI that steers Claude Code and OpenAI Codex CLI agents by registering as their hook command. On every hook event (PreToolUse, UserPromptSubmit, etc.) it judges the situation against a markdown constitution + a versioned precedent ledger, then returns one of:

  • allow — the agent proceeds with no friction
  • ask — the host agent's own permission UI shows; the human decides
  • deny — the action is blocked and the reason flows back to the agent

Every outcome is appended to the ledger so it becomes precedent for next time.

                       ┌────────────────────────┐
   tool call           │  Claude Code / Codex   │
   prompt    ────────► │  (host agent)          │
                       └───────────┬────────────┘
                                   │  spawn `overseer hook PreToolUse`
                                   │  pipe JSON to stdin
                                   ▼
                       ┌────────────────────────┐         ┌──────────────────┐
                       │     overseer (Go)      │ ◄────── │  constitution/   │
                       │  rule × precedent      │         │  *.md (markdown) │
                       │  decision tree         │         └──────────────────┘
                       └───────────┬────────────┘                ▲
                                   │                              │ append
                                   ▼                              │
                       ┌────────────────────────┐                 │
                       │  hookSpecificOutput    │         ┌──────────────────┐
                       │  {permissionDecision}  │         │  ledger          │
                       │  + exit code           │         │  (SQLite / Dolt) │
                       └────────────────────────┘         └──────────────────┘

Install

go install github.com/fireharp/overseer@latest

overseer init                       # scaffold ~/.overseer/
overseer install                    # write hooks to ~/.claude + ~/.codex
overseer doctor                     # verify

overseer install writes entries marked with _overseer: "managed" into ~/.claude/settings.json and ~/.codex/hooks.json. overseer uninstall removes only those marked entries — your other hooks are left untouched. Use --scope project to install to ./.claude/settings.json and ./.codex/hooks.json instead.

CLI

Command Purpose
overseer init [--local] Scaffold ~/.overseer/ (or ./.overseer/ with --local).
overseer install [--claude] [--codex] [--scope user|project] [--binary PATH] Register hooks. Idempotent.
overseer uninstall [--scope ...] Remove only entries with our managed marker.
overseer hook <event> Subprocess entry — Claude/Codex spawn this; reads stdin JSON, writes stdout JSON, exits 0/2.
overseer rules list / show <id> / validate Inspect the loaded constitution.
overseer ledger tail [-n N] / search <q> / outcome <event-id> <allow|deny|ask> Browse recent events, token-search, or record a human outcome.
overseer ledger branch <name> / checkout <name> / merge <from> <into> Dolt-only branching.
overseer why <event-id> Explain a past verdict — event, rules cited, precedent cited, human outcome.
overseer doctor Self-check + dry-run a known-bad event.

Constitution format

Markdown files in ~/.overseer/constitution/ (or ./.overseer/constitution/ for project-local):

shared.md     → ScopeShared    (apply everywhere)
project.md    → ScopeProject   (apply in this repo)
claude.md     → ScopeAgent     (Claude Code only)
codex.md      → ScopeAgent     (Codex CLI only)

One rule per block:

Rule: block-rm-rf-root
Priority: 1000
Scope: shared
When:
  event=PreToolUse
  tool=Bash
  cmd=/(?:^|[\s'"();|&]|\/)rm\s+(?:-[A-Za-z]*r[A-Za-z]*f[A-Za-z]*|-[A-Za-z]*f[A-Za-z]*r[A-Za-z]*|-[A-Za-z]*r[A-Za-z]*\s+-[A-Za-z]*f[A-Za-z]*|-[A-Za-z]*f[A-Za-z]*\s+-[A-Za-z]*r[A-Za-z]*)(?:\s+--)?\s+\/(?:[\s'"();|&]|$)/
Do: deny
Reason: `rm -rf /` is almost certainly catastrophic.
Examples: rm -rf /, sudo rm -rf /, rm -rf -- /

When: directives are AND-ed:

directive meaning
event=PreToolUse,UserPromptSubmit only these hook events
tool=Bash,Write only these tool names (PreToolUse / PostToolUse)
path=**/.env,/etc/** candidate file paths must match a glob
cmd=/regex/ bash command (or cmd field) must match the regex
keyword=migrate,deploy content (prompt + command + paths) must contain a keyword

Free text in When: (lines without key=value) becomes lowercase keyword matchers (length ≥ 3).

Do: is one of deny, ask, allow, or freeform guidance (treated as no-op for the verdict but still emitted in Reason).

Decision tree

1. Hard rule (deny / allow) wins, sorted by priority desc, then scope (agent>project>shared).
2. Otherwise tally precedent:
     - if human-resolved outcomes lean deny ≥ allow and deny > 0 → deny
     - if N similar past actions were allowed and none denied  → allow
3. If an "ask" rule fired but precedent didn't decide          → ask
4. If safe_mode and event=PreToolUse                            → ask
5. Default                                                       → allow

Tunables in ~/.overseer/config.toml:

safe_mode = false

[ledger]
backend = "dolt"            # or "sqlite"
path    = "~/.overseer/ledger"
[ledger.dolt]
branch  = "main"

[precedent]
min_score       = 0.25
allow_threshold = 3
top_k           = 10

[privacy]
redact = true
patterns = [
  '(?i)(api[_-]?key|secret|token|password)\s*[:=]\s*\S+',
  'AKIA[0-9A-Z]{16}',
  '[A-Za-z0-9+/]{40,}={0,2}',
]

Storage

Two backends share one ledger.Store interface:

  • SQLite (default, via modernc.org/sqlite — pure-Go, no CGO). Single file <path>/ledger.db. FTS5 candidate search + Go-side Jaccard rerank.
  • Dolt (via the MySQL wire protocol; build with -tags dolt). Same schema, plus branch / checkout / merge for experimentation. Requires a running dolt sql-server against your ledger directory.

To use Dolt:

go install -tags dolt github.com/fireharp/overseer@latest

cd ~/.overseer/ledger && dolt sql-server --user overseer --password '' &

# in ~/.overseer/config.toml:
#   [ledger]
#   backend = "dolt"
#   path    = "tcp(127.0.0.1:3306)/overseer"
#   [ledger.dolt]
#   branch  = "main"

Hook contracts

Both Claude and Codex deliver the same six events with near-identical JSON shapes; overseer normalizes them. A PreToolUse event from either looks roughly like:

{
  "hook_event_name": "PreToolUse",   // Codex (snake_case) or "hookEventName" (Claude camelCase)
  "session_id": "abc123",
  "cwd": "/repo",
  "tool_name": "Bash",
  "tool_input": { "command": "rm -rf /" }
}

Overseer responds with a hookSpecificOutput:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "rule block-rm-rf-root: ..."
  }
}

Exit code: 0 for allow/ask, 2 for deny. The --agent claude|codex flag (set automatically by overseer install) tells overseer which JSON shape to expect; without it, the parser sniffs by hookEventName vs hook_event_name keys.

Docs:

Development

go build ./...                     # default (SQLite only)
go build -tags dolt ./...          # with Dolt support
go test ./...

# Opt-in real Claude Code integration test.
OVERSEER_E2E_CLAUDE=1 go test ./e2e -run TestClaudeBlocksRmRfRoot -count=1 -v

Prior art

Inspirations from sibling projects in this repo (TS / Python; not ported verbatim):

  • /z_archive/resolver/ — markdown rule format, three-tier rule scoping, JSONL event ledger, Jaccard precedent search.
  • /z_archive/decisions/ — OAVI governance vocabulary (Owner / Advisors / Veto / Informed) and decision-class taxonomy (Routine / Elevated / One-way-door / Emergency) — informs v1.1 escalation richness.
  • /z_archive/overseer/ — confirms the hook-command-registration shape used by both vendors.

See docs/prior-art.md for file-level references.

Status

v0.1 — works end-to-end against synthetic events. Smoke-tested with both Claude- and Codex-shape JSON payloads against a sandbox HOME. Real-agent integration (claude -p "rm -rf /") is covered by the opt-in ./e2e test.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages