@noord-agency/agentdef
v0.4.1
Published
Define an AI agent once, generate the config file every tool expects (CLAUDE.md, AGENTS.md). Implements the AGENTS.md standard. Prior art: open-gitagent (MIT).
Readme
agentdef
Define an AI agent once. Generate the config every tool expects.
A clean-room reimplementation built on the design of open-gitagent (MIT), scoped to the two instruction formats that matter in practice and extended with a format-drift watcher.
agentdef turns one agent definition into the instruction file each AI coding tool reads, so your agent's identity, rules, and skills stay consistent across every tool, and you are never locked into a single vendor.
npm install -g @noord-agency/agentdef
agentdef init # install git hooks: regenerate on pull/merge/checkout
agentdef sync # generate configs for the tools in .agent-adaptersThe idea
Write your agent once:
agent.yaml name, description, model, extends
SOUL.md identity, voice, persona
RULES.md constraints and operating rules
skills/ one folder per skill, each with a SKILL.mdagentdef generates whatever each tool reads from that single source. No parallel copies to maintain, no drift between tools.
Supported tools
| Run | Emits | Read by |
|-----|-------|---------|
| --format claude-code | CLAUDE.md | Claude Code |
| --format agents | AGENTS.md | Codex, Cursor, Kimi, Grok, Antigravity, Windsurf, Zed, Aider, and the rest of the AGENTS.md standard |
| --format gemini | GEMINI.md | Gemini CLI |
| --format cursor | .cursor/rules/*.mdc | Cursor (native rules) |
agents is the canonical format. It produces the single AGENTS.md file every tool in that row reads, define once, run anywhere. The tool names are accepted as aliases (--format kimi, --format grok, --format codex all resolve to the same AGENTS.md), so reaching for the tool you know still works, but prefer agents.
Why only two formats
The AI-coding ecosystem converged on essentially two instruction-file formats: AGENTS.md (now a standard read by 30+ tools) and CLAUDE.md. Define once, run in any tool, switch freely. Even the model-lab CLIs (Kimi, Grok) and models reached through other harnesses (GLM) read these same files rather than inventing their own. That convergence is why agentdef can stay small and still cover the field.
Skills
Skills are the other half of the standard. A skill is a folder with a SKILL.md (YAML frontmatter + instructions); the format is shared across tools, so skills are copied, not translated.
You author skills once in skills/. Tools never read that folder directly, agentdef sync mirrors it into each tool's skills dir:
| Tool | Skills dir |
|---|---|
| Claude Code | .claude/skills/ |
| Codex, Kimi, Grok, Antigravity | .agents/skills/ (the cross-tool standard) |
| Cursor | .cursor/skills/ |
| Gemini CLI | .gemini/skills/ |
Same split as the instruction files: .agents/skills/ is the shared standard for the AGENTS.md family, the others are tool-specific. There is no single root skills folder that every tool reads; skills/ is the source, the .[tool]/skills/ dirs are generated. In the instruction file, CLAUDE.md indexes skills with a pointer (Claude Code loads each on demand) while AGENTS.md and GEMINI.md inline them in full.
Commands
agentdef init # install git hooks that run sync on pull/merge/checkout/rebase
agentdef sync # generate every adapter in .agent-adapters + mirror skills/agents
agentdef export --format <claude-code|agents|gemini|cursor> [--dir .] [--out FILE]
agentdef install # resolve the full `extends:` chain into .agentdef/parent
agentdef validate # check the definition (fail-loud); enforces provider:model
agentdef watch # detect upstream format driftStatus goes to stderr and only generated content to stdout, so agentdef export -f claude-code > CLAUDE.md is clean.
Inheritance
A repo can inherit a shared agent definition:
# agent.yaml
extends: https://github.com/your-org/base-agent.gitextends resolves recursively: if the parent has its own extends, the grandparent resolves too, and so on up the chain. So texte → we-site → noord materializes the whole ancestry in one sync, always current. A cycle (a repo that transitively extends itself) fails loudly.
agentdef install clones each ancestor one level deeper under .agentdef/parent (a regenerable cache; agentdef init adds it to .gitignore, and migrates a repo off the old .gitagent/ name by untracking and deleting it, so existing projects just re-run agentdef init and commit). On generation, nearer wins: SOUL.md is taken from the closest ancestor that defines one (local over parent over grandparent), RULES.md is the union (furthest ancestor first, local last), and skills merge with the nearest definition winning on name collision, so a local skill still overrides every inherited one.
Format-drift watcher
Tools occasionally change their config format. agentdef watch fingerprints each tool's published format and compares it to a stored baseline. Deterministic, no LLM, no API key. It exits non-zero when something changes, so CI can open an issue and a human can update the affected adapter. See .github/workflows/format-watch.yml.
Models
Models are a config value, not an emission target. Set model: provider:model in agent.yaml (for example anthropic:claude-opus-4-7, zhipu:glm-4.6, moonshot:kimi-k2); validate enforces the provider:model form. The endpoint and credentials for a given model live in your own machine config, never generated by agentdef.
License
MIT, see LICENSE. Built and maintained by noord.
