Skip to content

Repository files navigation

se-harness

CI License: MIT Node.js >=18

Portable, tool-agnostic AI coding harness generator. One source of truth, AGENTS.md as the entrypoint, no vendor lock-in.

Table of Contents

Quick Start

curl -fsSL https://raw.githubusercontent.com/manuuuel/seh/main/scripts/install.sh | sh

# Once per machine: unified global ruleset + agent symlinks
seh init --global --agents claude,codex --yes

# Per project: detect stack, scaffold AGENTS.md + .seh/
cd your-project
seh init --tech typescript --yes

# Regenerate generated files after editing .seh/ sources
seh sync

This gives you a ~/.seh/AGENTS.md global ruleset symlinked into your agents' config paths, plus a project AGENTS.md (and CLAUDE.md, GEMINI.md, …) that every supported agent reads automatically.

Why seh

seh produces the context files that AI coding agents (Claude Code, Codex, Gemini, Pi, OpenCode, Copilot, …) read: a single global ruleset on your machine plus a per-project index of focused, technology-specific guideline modules. Skills from a harness package are distributed to every agent that supports them. Edit one source of truth, run seh sync, and every tool-specific file regenerates in lockstep — no more copy-pasting the same rules into CLAUDE.md, GEMINI.md, and .github/copilot-instructions.md separately.

Layers

Layer Location What it is
L0 — Core bundled in the CLI The authored source content (global sections + per-technology catalog). Fallback when no package is active.
L1 — Global ~/.seh/ A single unified AGENTS.md with your cross-cutting rules. Authored once per machine; optional agent symlinks. Not copied into repos.
L2 — Project <repo>/AGENTS.md + .seh/ A thin index linking project + per-technology modules. Committed to the repo.
Package <your-harness>/ A versioned git repo of global rules, stack modules, templates, and skills. Takes precedence over L0/L1 when active.

Resolution order for any file: package → ~/.seh/ → seh bundled core.

Global rules apply everywhere; project layers extend — never contradict them.

Generated files must NOT be hand-edited. Edit the .seh/ sources and run seh sync to regenerate.

The two shapes of AGENTS.md

  • Global (~/.seh/AGENTS.md) is one self-contained file — every guardrail inlined in a single document, led by a forced Craftsmanship principle (keep it small and sharp, write elegant code, seek the most minimal better-working design, introduce no slop). Tools that auto-load a global instructions file get the whole ruleset directly.

  • Project (<repo>/.seh/AGENTS.md) is the canonical file — a short directive preamble plus a progressive index (linked table of contents) pointing at focused modules under .seh/, loaded on demand:

    • .seh/project.md — mission, constraints, out-of-scope (read-first)
    • .seh/domain/*.md — architecture, glossary
    • .seh/stack/<tech>.md — per-technology best practices

    Tool-specific files (AGENTS.md, CLAUDE.md, GEMINI.md, .github/copilot-instructions.md, etc.) are generated symlinks to .seh/AGENTS.md, gitignored, and regenerated by seh sync.

Commands

1. Global setup (once per machine)

seh init --global                              # interactive: choose which agents to symlink
seh init --global --agents claude,codex --yes  # non-interactive

Creates:

  • ~/.seh/AGENTS.md — the unified global ruleset (Craftsmanship first, then security, quality gates, testing, commits, branching, dependencies, error handling, observability, data & privacy, documentation, refactoring, workflow, session startup, reporting, boundaries, code principles).
  • ~/.seh/config.json — which agents are symlinked.

Optionally wire agents to auto-load it (see seh link).

2. Project setup

cd your-project
seh init                                         # detects technologies, interactive multi-select
seh init --tech typescript,python --yes          # non-interactive (≥1 required)

Creates:

  • AGENTS.md — the project index (links to the modules below)
  • .seh/project.md, .seh/domain/architecture.md, .seh/domain/glossary.md
  • .seh/stack/<tech>.md for each selected technology
  • seh.lock — records the selected technologies (commit it)

Supported technologies: javascript, typescript, python, go, c, rust, java. No generic fallback — pick at least one.

Then fill in .seh/project.md and .seh/domain/* and re-sync.

3. Sync — regenerate from sources

seh sync

Rewrites the project AGENTS.md index and .seh/stack/* from seh.lock. Idempotent (no change on re-run with unchanged sources).

4. Check — detect drift

seh check

Exit 0 if the generated files match the sources; exit 1 (with a message) if AGENTS.md or a stack module is stale or missing. Suitable for pre-commit/CI.

5. Link — manage agent symlinks

seh link --add claude         # symlink ~/.claude/CLAUDE.md -> ~/.seh/AGENTS.md
seh link --remove claude      # remove it

AGENTS.md stays the single source of truth; symlinks are pure pointers, so there is no per-agent content to drift.

Supported agents: claude, codex, pi, gemini, opencode, copilot, agents

The agents target manages the cross-agent interoperability path (~/.agents/, .agents/) used as an alias by Gemini CLI, Pi, Copilot, and others.

Global targets

Agent Target
claude ~/.claude/CLAUDE.md
codex ~/.codex/AGENTS.md
pi ~/.pi/agent/AGENTS.md
gemini ~/.gemini/GEMINI.md
opencode ~/.config/opencode/AGENTS.md
copilot ~/.copilot/copilot-instructions.md
agents ~/.agents/AGENTS.md

Project targets

Agent Target Canonical
claude CLAUDE.md .seh/AGENTS.md
codex AGENTS.md .seh/AGENTS.md
pi AGENTS.md .seh/AGENTS.md
gemini GEMINI.md .seh/AGENTS.md
opencode AGENTS.md .seh/AGENTS.md
copilot .github/copilot-instructions.md .seh/AGENTS.md
agents .agents/AGENTS.md .seh/AGENTS.md

Harness Packages

A harness package is a plain directory the user versions with git, carries between machines, and shares with teammates. seh scaffolds and reads it; git is fully external and never wrapped.

my-harness/
├── harness.json          — package metadata (name, version, modelTag)
├── CHANGELOG.md          — harness decisions and reasoning (human-authored)
├── global/
│   ├── AGENTS.md         — global ruleset (replaces ~/.seh/AGENTS.md)
│   └── config.json       — agent symlink config
├── templates/
│   ├── stack/            — per-technology structural patterns
│   └── project/          — full project scaffolds
├── projects/             — per-repo overlays matched by repo name
└── skills/               — skills to distribute (vendored or referenced)
    ├── brainstorming/    — vendored skill (committed to package repo)
    └── caveman/          — referenced skill (fetched on install)

Package commands

seh package init [path]

Scaffolds a new harness package at path (default: ./my-harness). Creates the full directory structure, copies bundled stack modules as a starting point, writes harness.json and an empty CHANGELOG.md.

seh package init ~/my-harness
cd ~/my-harness && git init && git add . && git commit -m "init harness"

seh package use <path>

Points seh at an existing package. Writes packagePath into ~/.seh/config.json.

git clone git@github.com:you/my-harness.git ~/my-harness
seh package use ~/my-harness

seh package status

Shows the currently active package path, name/version from harness.json, and whether each expected directory exists.

seh package install

Installs artifacts from the active package onto the host machine.

seh package install --harness              # write ~/.seh/AGENTS.md + agent symlinks
seh package install --skills               # symlink skills into ~/.seh/skills/ + agent dirs
seh package install --all                  # both of the above
seh package install --all --agents claude,gemini  # non-interactive agent selection
Flag Action
--harness Writes ~/.seh/AGENTS.md from package/global/AGENTS.md; updates agent symlinks
--skills Fetches referenced skills, symlinks package/skills/<name>/~/.seh/skills/<name>/ → agent skill dirs
--all Both of the above
--agents <list> Comma-separated agents to receive skill symlinks (prompts interactively if omitted)
--force Overwrite existing files

New machine workflow:

git clone git@github.com:you/my-harness.git ~/my-harness
seh package use ~/my-harness
seh package install --all

Skills

Skills (reusable SKILL.md-based capability packages) are a first-class layer in the harness package. seh distributes them from the package to every agent that supports a skill directory.

Skill layer model

<package>/skills/<name>/   ← source (vendored or referenced)
         ↓ symlink
~/.seh/skills/<name>/      ← stable intermediate on this machine
         ↓ symlinks
~/.claude/skills/<name>/   ← Claude Code
~/.codex/skills/<name>/    ← Codex CLI
~/.gemini/skills/<name>/   ← Gemini CLI
~/.config/opencode/skills/<name>/  ← OpenCode
~/.pi/agent/skills/<name>/ ← Pi
~/.copilot/skills/<name>/  ← GitHub Copilot
~/.agents/skills/<name>/   ← cross-agent interoperability path

~/.seh/skills/ is the stable intermediate: if the package moves, agent symlinks remain intact until re-pointed.

Skill commands

seh skills add <url> [--vendor | --reference] [--ref <branch>] [routing flag]

Adds a skill from a GitHub URL to the active package.

seh skills add https://github.com/JuliusBrussee/caveman --reference
seh skills add github:you/my-skill --vendor --ref v1.2
  • --vendor: clones files into <package>/skills/<name>/ (committed to git)
  • --reference: records the URL in harness.json only; appends skills/<name>/ to .gitignore; files are fetched at install time
  • Prompts for type if neither flag is given
  • Infers skill name from the repo name

Routing flags tell agents when to invoke the skill. Exactly one may be used:

Flag When agent invokes
--always [label] Every response
--when <condition> When the described scenario matches
--optional Agent decides based on context
seh skills add github:you/caveman --vendor --always "every response"
seh skills add github:you/systematic-debugging --vendor --when "bug / test failure / unexpected behavior"
seh skills add github:you/xlsx --vendor --optional

Routing is stored in harness.json and rendered into a ## Skills section in both the project AGENTS.md (by seh sync) and the global ~/.seh/AGENTS.md (by seh package install --harness), so agents always know which skills to invoke and when.

seh skills update [name]

Re-fetches referenced skill(s) from their source. No arguments updates all referenced skills. Errors if the named skill is vendored.

seh skills list

Shows skills in the active package with their routing mode:

✓ brainstorming       [vendor]   always: before any implementation
✓ systematic-debugging [vendor]  when: bug / test failure
✗ caveman             [reference]  https://github.com/JuliusBrussee/caveman (ref: main)
✓ xlsx                [vendor]   optional

= files present on disk, = reference not yet fetched (run seh package install --skills to fetch).

harness.json skills metadata

{
  "name": "my-harness",
  "version": "1.0.0",
  "skills": {
    "brainstorming": {
      "type": "vendor",
      "invoke": { "mode": "always", "label": "before any implementation" }
    },
    "systematic-debugging": {
      "type": "vendor",
      "invoke": { "mode": "when", "condition": "bug / test failure / unexpected behavior" }
    },
    "caveman": {
      "type": "reference",
      "source": "https://github.com/JuliusBrussee/caveman",
      "ref": "main",
      "invoke": { "mode": "always", "label": "every response" }
    },
    "xlsx": {
      "type": "vendor",
      "invoke": { "mode": "optional" }
    }
  }
}

Skill routing in AGENTS.md

The same ## Skills section is appended to the project .seh/AGENTS.md (by seh sync) and to the global ~/.seh/AGENTS.md (by seh package install --harness) whenever a skill has routing configured:

## Skills

Always invoke:
- `brainstorming` — before any implementation
- `caveman` — every response

Invoke when:
- `systematic-debugging` — bug / test failure / unexpected behavior

Optional:
- `xlsx`

Skills with no invoke field are omitted from this section. If no skills have routing, the section is omitted entirely.


Memory

.seh/memory/ stores typed markdown files that agents read for persistent project context — decisions made, constraints discovered, learnings earned, problems still open. Files are committed to the repo so the whole team (and every agent) shares the same memory.

Memory file format

---
type: decision
---

# Auth strategy

Chose JWT over sessions. Sessions required sticky routing which complicates
the Docker setup. JWT is stateless and works across all replicas.

Types:

Type When to use
decision A choice made and why (architecture, tech, approach)
constraint A hard rule discovered (never do X, always do Y)
learning Something non-obvious that cost time to figure out
problem Unresolved issue to pick up next session

Memory commands

seh memory add <name> [--constraint | --learning | --problem]

Creates .seh/memory/<name>.md with the correct frontmatter and opens $EDITOR (prints the file path if $EDITOR is unset). Default type is decision. Does not overwrite an existing file.

seh memory add auth-strategy              # type: decision (default)
seh memory add rate-limiting --problem
seh memory add jwt-expiry --learning
seh memory add url-structure --constraint

seh memory list

Shows all memory files grouped by type:

Decisions
  auth-strategy       Chose JWT over sessions
  db-migrations       Use Flyway, not Liquibase

Constraints
  url-structure       Never expose user IDs in URLs

Learnings
  jwt-expiry          Access tokens must be short-lived (<15m)

Open problems
  rate-limiting       Strategy unresolved — Redis vs in-process

seh memory remove <name>

Deletes .seh/memory/<name>.md.

Memory in AGENTS.md

seh sync appends a ## Memory section to .seh/AGENTS.md whenever .seh/memory/ exists. It always includes a protocol block instructing agents to write memory at session end, plus an index of existing files grouped by type:

## Memory

Write to `.seh/memory/` at end of every session:
- **decision** — a choice made and why (architecture, tech, approach)
- **constraint** — a hard rule discovered (never do X, always do Y)
- **learning** — something non-obvious that cost time to figure out
- **problem** — unresolved issue to pick up next session

Run: `seh memory add <name> [--decision|--constraint|--learning|--problem]`

### Decisions
- [Auth strategy](.seh/memory/auth-strategy.md) — Chose JWT over sessions

### Open problems
- [Rate limiting](.seh/memory/rate-limiting.md) — Strategy unresolved

If .seh/memory/ is empty the protocol block is still rendered (so new agents know how to populate it). If the directory doesn't exist the section is omitted.


Agent skill directories

All supported agents have confirmed user-level skill directories (as of 2026-07):

Agent User skill directory
claude ~/.claude/skills/<name>
codex ~/.codex/skills/<name>
gemini ~/.gemini/skills/<name>
opencode ~/.config/opencode/skills/<name>
pi ~/.pi/agent/skills/<name>
copilot ~/.copilot/skills/<name>
agents ~/.agents/skills/<name>

Installation

seh is distributed from GitHub — no npm registry account needed.

Install / update (recommended)

One command installs a self-contained build (deps bundled) and puts seh on your PATH — no npm, no build step, no global node_modules:

curl -fsSL https://raw.githubusercontent.com/manuuuel/seh/main/scripts/install.sh | sh
  • Update: re-run the same command.
  • Pin a version: curl -fsSL .../scripts/install.sh | SEH_REF=v0.4.1 sh
  • Installs to ~/.local/share/seh, symlinks ~/.local/bin/seh (override via SEH_HOME / SEH_BIN). Requires node on PATH.
  • Uninstall: rm -rf ~/.local/share/seh ~/.local/bin/seh

Via npm (alternative)

npm install -g github:manuuuel/seh          # latest main
npm install -g github:manuuuel/seh#v0.4.1   # a tag

npm installs go through npm's git-dep preparation, which can fail with ENOTDIR if a previous global install left a broken entry. If that happens, remove the stale .../lib/node_modules/se-harness, run npm cache clean --force, and retry — or just use the curl installer above, which avoids npm entirely.

From source (development)

git clone git@github.com:manuuuel/seh.git ~/pocs/seh
cd ~/pocs/seh
npm install
npm run build
npm link       # makes `seh` available in $PATH

To uninstall: npm unlink -g se-harness.

Per-project

npm install --save-dev github:manuuuel/seh
npx seh init

Try it (sandboxed demo)

Runs the whole flow against a throwaway HOME — your real ~/.seh and ~/.claude are untouched:

npm run try

Development

npm install
npm run build    # compile to dist/
npm test         # run the test suite (155 tests)
npm run dev      # run the CLI via tsx without building

About

Portable, tool-agnostic AI coding harness generator. One source of truth via AGENTS.md — a single global ruleset plus per-project, technology-aware guideline modules — with no vendor lock-in.

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages