π΄ oh-my-harness
Tame your AI coding agents with natural language.
Stop hand-writing CLAUDE.md files. Describe your project, get enforced guardrails.
π€ The Problem
Every AI code agent needs configuration files. Claude Code needs CLAUDE.md + hooks. Cursor needs .cursorrules. Codex needs AGENTS.md. You end up:
- π Copy-pasting config files between projects
- π Forgetting to set up TDD enforcement hooks
- π₯ Agents committing code without running tests
- π² Inconsistent behavior across projects
β¨ The Solution
oh-my-harness init "React + FastAPI fullstack, TDD enforced, lint on save"
That's it. oh-my-harness generates enforced guardrails β not just instructions, but hooks that actually block bad behavior:
- β Commit without tests passing? Blocked.
- β Edit source without updating tests first? Blocked. (TDD Guard)
- β Write to
node_modules/or.next/? Blocked. - β Run
rm -rf /? Blocked. - β Commit on a merged branch? Blocked.
- β Auto-lint on every file save? Done.
- β Auto-create PR after push? Done.
- π Track all hook events for analytics? Done.
π Quick Start
# Zero-install: run directly with npx
npx oh-my-harness init "TypeScript Next.js frontend with Python FastAPI backend"
# Or install globally
npm install -g oh-my-harness
oh-my-harness init "React app with TDD"
# Short alias works too
omh init "Android Kotlin app with Hilt, JUnit, Gradle"
omh catalog list
omh test # Dry-run verify your harness
omh stats # TUI analytics dashboard
omh diff # Preview what `omh sync` would change
omh sync --check # Fail (exit 1) if generated files are out of date β CI gate
π Keeping generated files in sync
harness.yaml is the source of truth, so the committed CLAUDE.md, hooks, and
runtime configs can drift if someone edits harness.yaml without re-running
omh sync. Three commands keep them honest:
| Command | Use |
|---|---|
omh sync --check |
CI gate β exits non-zero (and lists the files) when generated output is stale, writes nothing |
omh diff |
Human preview of exactly what omh sync would change |
omh doctor --strict |
Health check that also fails on drift (plain omh doctor warns) |
# .github/workflows/ci.yml
- run: npx oh-my-harness sync --check # fails the build if the harness is out of date
The hook manifest records the oh-my-harness version that generated it, so an
upgrade that changes output is surfaced as a "re-run omh sync" hint.
π What Gets Generated
~/.omh/
βββ config.json # AI provider config (global, not per-project)
your-project/
βββ CLAUDE.md # Claude Code instructions (TDD rules, standards)
βββ AGENTS.md # Codex CLI instructions (same managed sections)
βββ harness.yaml # Your harness config (source of truth)
βββ .omh/ # Single source of truth β hooks + state
β βββ hooks/
β β βββ catalog-branch-guard.sh # Blocks commits on merged branches
β β βββ catalog-tdd-guard.sh # Enforces test-first workflow
β β βββ catalog-commit-test-gate.sh # Tests must pass before commit
β β βββ catalog-path-guard.sh # Protects build outputs
β β βββ catalog-command-guard.sh # Blocks dangerous commands
β β βββ catalog-lint-on-save.sh # Auto-lint on save
β β βββ catalog-auto-pr.sh # Auto-create PR after push
β βββ state/ # gitignored β log/runtime data
β β βββ events.jsonl # Unified hook event log (powers omh stats)
β β βββ tdd-edits.json # TDD guard working state
β βββ manifest.json # Generated-files manifest
βββ .claude/
β βββ settings.json # Claude permissions + hooks β .omh/hooks/*.sh
β βββ oh-my-harness.json # Harness init/sync state
βββ .codex/
βββ config.toml # [features] hooks = true, goals = true
βββ hooks.json # Codex hooks β .omh/hooks/*.sh (same scripts)
βοΈ How It Works
~/.omh/config.json βββββββββββββββββββββββ
ββββββββββββββββββ β β
β β’ Claude CLI ββββΆβ NL Processing ββββ "React + FastAPI
β β’ Claude API β β (describe your β TDD enforced"
β β’ OpenAI API β β β
β β’ Gemini API β β β
β β’ Codex OAuth β β β
β β’ Codex OAuth β β β
β API β ββββββββββ¬βββββββββββββ
ββββββββββββββββββ β
(global AI config) ββββββββββΌβββββββββββββ
β Project Detector β β Auto-detects language,
β (14 languages) β framework, package manager
ββββββββββ¬βββββββββββββ
β
ββββββββββΌβββββββββββββ
β harness.yaml β β Source of truth
β (editable, git β (hooks + rules)
β trackable) β
ββββββββββ¬βββββββββββββ
β
ββββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββ
βCLAUDE.md β β Hooks β βsettings. β
β (rules) β β(enforce) β β json β
β β β β β(perms) β
ββββββββββββ ββββββββββββ ββββββββββββ
π Project Detector
oh-my-harness automatically detects your project type and injects accurate facts into the LLM prompt:
| Language | Detection | Commands |
|---|---|---|
| π¦ TypeScript/JS | package.json, tsconfig | pnpm/npm/yarn test, eslint, tsc |
| π Python | pyproject.toml, requirements.txt, Pipfile, manage.py, .python-version | pytest, ruff, black, isort, mypy |
| π Swift | Package.swift, .xcodeproj | swift test, xcodebuild |
| π¦ Rust | Cargo.toml | cargo test, cargo clippy |
| πΉ Go | go.mod | go test, golangci-lint |
| β Java/Kotlin | pom.xml, build.gradle | mvn test, ./gradlew test |
| π Ruby | Gemfile | bundle exec rspec |
| π PHP | composer.json | phpunit |
| π― Dart/Flutter | pubspec.yaml | dart test, flutter test |
| β‘ C/C++ | CMakeLists.txt | cmake, make |
| π£ C#/.NET | *.csproj | dotnet test |
| π§ Elixir | mix.exs | mix test |
| π· Scala | build.sbt | sbt test |
| β‘ Zig | build.zig | zig build test |
π€ AI Provider Setup
oh-my-harness supports multiple AI providers for natural language mode:
| Provider | Setup | Available Models | Default |
|---|---|---|---|
| Claude CLI | claude command installed |
Opus 4.6, Sonnet 4.6, Haiku 4.5 | β |
| Claude API | Set ANTHROPIC_API_KEY |
Opus 4.6, Sonnet 4.6, Haiku 4.5 | Sonnet 4.6 |
| OpenAI API | Set OPENAI_API_KEY |
GPT-5.5, GPT-5.4, GPT-5.4-mini, GPT-5.4-nano, GPT-4.1, GPT-4.1-mini, o3, o4-mini | GPT-5.5 |
| Gemini API | Set GOOGLE_API_KEY |
Gemini 2.5 Pro, Gemini 2.5 Flash, Gemini 2.5 Flash Lite, Gemini 3.1 Pro Preview | Gemini 2.5 Pro |
| Codex OAuth | codex command installed + codex login; runs codex exec |
GPT-5.5, GPT-5.4, GPT-5.4-mini | GPT-5.5 |
| Codex OAuth API | omh config device-code login; imports ~/.codex/auth.json once if present, then uses ~/.omh |
GPT-5.5, GPT-5.4, GPT-5.4-mini | GPT-5.5 |
Configuration is saved to ~/.omh/config.json and selected via interactive UI on first use:
omh init # will prompt for AI provider selection and model choice
π§± Building Block Catalog
All enforcement is powered by catalog blocks β reusable, parameterized hook templates:
| Block | Category | Description |
|---|---|---|
π‘οΈ branch-guard |
git | Blocks commits on main/merged branches |
π§ͺ commit-test-gate |
quality | Runs tests before git commit |
π commit-typecheck-gate |
quality | Runs typecheck before git commit |
π command-guard |
security | Blocks dangerous shell commands |
π path-guard |
file-protection | Blocks writes to protected paths |
π lockfile-guard |
file-protection | Prevents manual lockfile edits |
π€« secret-file-guard |
security | Blocks edits to .env, credentials |
βοΈ lint-on-save |
auto-fix | Auto-lint on file save |
π¨ format-on-save |
auto-fix | Auto-format on file save |
π§ͺ test-on-save |
auto-fix | Auto-run tests on file save |
π auto-pr |
automation | Auto-create PR after push |
π§ͺ tdd-guard |
quality | Blocks source edits unless test modified first (JS/TS/Python/Kotlin/Java) |
π sql-guard |
security | Blocks dangerous SQL operations |
π³ worktree-setup |
monorepo | Supports monorepo worktree patterns |
ποΈ compact-context |
maintenance | Re-injects context on session start |
π config-audit |
audit | Audit trail for config changes |
π desktop-notify |
ux | Cross-platform desktop notifications |
Usage in harness.yaml
hooks:
- block: branch-guard
- block: tdd-guard
mode: ask # ask for approval instead of hard-blocking (Claude)
- block: commit-test-gate
params:
testCommand: "npx vitest run"
- block: path-guard
params:
blockedPaths:
- "node_modules/"
- "dist/"
- block: command-guard
params:
patterns:
- "rm -rf /"
- "sudo rm"
- block: lint-on-save
params:
filePattern: "*.ts"
command: "npx eslint --fix"
- block: auto-pr
params:
baseBranch: main
mode: block vs. ask
Any blocking hook accepts an optional mode (default block):
blockβ hard-blocks the tool call. The agent cannot proceed.askβ escalates to the user for approval instead of blocking outright.- Claude Code: shows a native permission prompt (
permissionDecision: "ask"). - Codex:
askis not supported, so the hook falls back to a hard block β your guardrail is never silently downgraded to "allow". The same generated script detects the calling runtime and responds accordingly.
- Claude Code: shows a native permission prompt (
mode: ask only applies to blocks that can block (canBlock: true); setting it
on a non-blocking block (e.g. lint-on-save) is reported and ignored.
π₯οΈ Commands
# π Initialize
omh init "your project description" # NL-powered (requires AI provider)
omh init # Interactive TUI (import existing harness.yaml)
# π Catalog
omh catalog list # Browse all building blocks
omh catalog info branch-guard # Block details + params
# π§ Hook management
omh hook add branch-guard # Add a hook
omh hook remove auto-pr # Remove a hook
# π Sync & manage
omh sync # Regenerate all files from harness.yaml
omh uninstall --dry-run # Preview generated-file cleanup
omh uninstall -y # Remove generated files, keep user content
omh uninstall -y --purge # Also remove harness.yaml
# π©Ί Verify & monitor
omh doctor # Health check
omh test # Dry-run verify all hooks
omh stats # TUI analytics dashboard
π§Ή omh uninstall β Safe generated-file cleanup
omh uninstall removes oh-my-harness generated artifacts while preserving user
content in merged files.
omh uninstall --dry-run
omh uninstall -y
omh uninstall -y --purge
Safety behavior:
- Prints the same uninstall plan for dry-run and real execution.
- Recommends backing up before execution; use
--skip-backup-warningonly for automation that already handles backups. - Keeps
harness.yamlby default;--purgeremoves it. - Preserves user content in
CLAUDE.md,AGENTS.md,.claude/settings.json,.codex/hooks.json,.codex/config.toml, and user Pi extensions. - Removes only OMH-owned hook commands that point at this project's
.omh/hooksdirectory. - Warns when
.codex/config.tomlfeature flags (hooks/goals) are removed, because manually-owned feature settings cannot be distinguished from OMH generated settings. - Warns that
.codex/config.tomlcomments may be lost when TOML is rewritten. - Uses backups for modified files and restores them on stop-on-error failures;
--continue-on-errorrecords failures and keeps applying independent operations.
π©Ί omh doctor
oh-my-harness: running health checks...
β .claude/oh-my-harness.json found
β CLAUDE.md exists with intact markers
β .claude/settings.json is valid
β All hook scripts are executable
oh-my-harness: all checks passed
π§ͺ omh test β Dry-Run Verification
Simulates hook inputs to verify block/allow behavior without entering Claude Code:
β omh test Harness dry-run verification
β
β Branch guard
β β git commit on feat/my-feature β ALLOWED
β
β TDD Guard
β β src/foo.ts without test β BLOCKED
β β tests/unit/foo.test.ts β ALLOWED
β β README.md β ALLOWED
β
β File guards
β β node_modules/test-file.js β BLOCKED
β β dist/test-file.js β BLOCKED
β β src/index.ts β ALLOWED
β
β Command guards
β β "rm -rf /" β BLOCKED
β β "npm test" β ALLOWED
β
β 14/14 checks passed β
π omh stats β TUI Analytics Dashboard
Interactive dashboard powered by ink with 3 views:
[1] Overview [2] Timeline [3] Blocks d:filter r:reload q:quit
Active: 8 Events: 1213 Block rate: 2%
branch-guard ββββββββββββββββββββ 0b/202a
tdd-guard βββββββββββββββββββββ 14b/68a
commit-test-gate ββββββββββββββββββββ 0b/199a
path-guard ββββββββββββββββββββ 4b/76a
command-guard ββββββββββββββββββββ 4b/202a
Dormant (0 hits):
β lockfile-guard
β secret-file-guard
- Overview β Active blocks with hit bar charts + dormant block detection
- Timeline β 24-hour heatmap + block rate + peak hour
- Blocks β Scrollable detail view with params, hits, last block reason
Keyboard: 1/2/3 views, β/β scroll, d date filter, r reload, q quit
π Stateful Hook Logging
Every hook invocation is recorded in .omh/state/events.jsonl:
{"ts":"2026-03-18T08:00:00Z","event":"PreToolUse","hook":"catalog-tdd-guard.sh","decision":"block","reason":"TDD β foo.test.* ν
μ€νΈ νμΌμ λ¨Όμ μμ νμΈμ"}
{"ts":"2026-03-18T08:00:05Z","event":"PreToolUse","hook":"catalog-command-guard.sh","decision":"allow","reason":""}
This powers omh test live verification and omh stats analytics.
ποΈ Architecture
oh-my-harness/
βββ bin/ # CLI entry point
βββ src/
β βββ catalog/
β β βββ blocks/ # 17 building block definitions
β β βββ types.ts # BuildingBlock, HookEntry schemas
β β βββ registry.ts # Block discovery & search
β β βββ template-engine.ts # Handlebars rendering + applyDefaults
β β βββ converter.ts # HookEntry[] β rendered scripts
β βββ cli/
β β βββ commands/ # init, doctor, catalog, hook, sync, test
β β βββ stats/ # TUI dashboard (ink/React)
β β β βββ App.tsx # App shell (tab bar, keyboard nav)
β β β βββ data.ts # Data aggregation layer
β β β βββ components/ # Overview, Timeline, Blocks views
β β βββ harness-tester.ts # Hook simulation engine
β β βββ event-logger.ts # events.jsonl read/write/stats
β β βββ event-verifier.ts # Event-based verification
β β βββ tui/ # Interactive provider & model selection
β β βββ provider-setup.ts # Provider configuration UI
β β βββ tool-checker.ts # Command executable checks
β βββ core/
β β βββ harness-schema.ts # harness.yaml Zod schema
β β βββ merged-config.ts # MergedConfig + HooksConfig interfaces
β β βββ harness-converter-v2.ts # harness.yaml β MergedConfig (catalog pipeline)
β β βββ generator.ts # Orchestrates all generators
β βββ generators/
β β βββ claude-md.ts # CLAUDE.md with idempotent markers
β β βββ hooks.ts # Hook scripts + event logger injection
β β βββ settings.ts # .claude/settings.json
β β βββ gitignore.ts # .gitignore updater
β βββ detector/
β β βββ project-detector.ts # Deterministic project detection
β β βββ types.ts # ProjectFacts, Detector interface
β β βββ detectors/ # 14 language detectors
β βββ cli/
β β βββ tui/ # Interactive provider & model selection
β β βββ provider-setup.ts # Provider configuration UI
β βββ nl/
β βββ provider-registry.ts # Multi-provider definitions
β βββ config-store.ts # ~/.omh/config.json persistence
β βββ providers/ # Provider implementations
β β βββ claude-cli.ts
β β βββ claude-api.ts
β β βββ openai-api.ts
β β βββ gemini-api.ts
β βββ parse-intent.ts # LLM prompt integration
β βββ prompt-templates.ts # NL prompt construction
βββ tests/ # 900+ tests (unit + integration)
π¦ Requirements
- Node.js >= 20
- Claude CLI (optional, for default NL mode) β Install guide
- API Keys (optional, for Claude/OpenAI/Gemini API modes) β set
ANTHROPIC_API_KEY,OPENAI_API_KEY, orGOOGLE_API_KEY - Codex CLI OAuth (optional, for
codexCLI-wrapper mode) β installcodexand runcodex login - Codex OAuth API (optional, experimental direct mode) β run
omh configand choose Codex OAuth API to complete device-code sign-in; credentials are stored under~/.omh
πΊοΈ Roadmap
-
npx oh-my-harnessβ zero-install usage -
omh syncβ regenerate from harness.yaml - Building block catalog β 17 verified hook templates
- Project detector β 14 language auto-detection
-
omh testβ dry-run hook verification -
omh statsβ TUI analytics dashboard (ink) - Stateful hook logging β events.jsonl
- TDD Guard β enforce test-first workflow
- Multi-provider AI support β Claude API, OpenAI, Gemini, Codex OAuth
- Interactive model selection per provider
- GitHub star prompt β first-time only
- Codex emitter β
AGENTS.md+.codex/hooks.json+.codex/config.toml - Unified
.omh/layout β single source of truth for hooks & state across runtimes - Pi (pi.dev) emitter β bridge extension (
.pi/extensions/omh-harness.ts) reusing the same.omh/hooks/*.sh -
askmode β request approval before executing risky tools (Claude native prompt / Pictx.ui.select; Codex falls back to block) -
omh uninstallβ remove generated artifacts while preserving user content -
omh configβ view, reconfigure, or reset the saved AI provider (rotate expired keys, switch provider/model) - Community harness.yaml registry β share and reuse configs
-
omh modify "change X"β NL config editing
π€ Contributing
Contributions are welcome! Please read the Contributing Guide before submitting a PR.
πͺ Support This Project
oh-my-harness is free and open source. Here's how you can help:
- β Star β Give a star to help others discover the project
- π Report Bugs β Open an issue when something doesn't work
- π‘ Request Features β Suggest ideas for new blocks, emitters, or features
- π§ Contribute β Fix a bug, add a block, or improve docs β PRs are always welcome
- π’ Spread the Word β Share oh-my-harness with your team or community
π License
MIT
Your agents are only as good as their guardrails. π΄
Built with frustration from hand-writing CLAUDE.md files.