ethos
AGENTS.md22 starsChanged 8 days agoMITView on GitHub
Ethos is a TypeScript agent framework where personality (SOUL.md + toolset.yaml + config.yaml) is architecture, not a prompt string. Node 24, TypeScript 6 strict, pnpm, Biome 2, vitest, tsx in dev. Layer names are archcheck's. Allowed: types ← core ← extensions ← apps; packages/wiring is the only composition root. Forbidden: upward imports, core importing implementations, extensions importing wiring. Enforced by the layer rules in architecture.config.ts and scripts/check-tool-imports.sh; pnpm exec archcheck explain <ruleId> gives the remedy. ARCHITECTURE.md says why each law…
- Reads credentials
- Installs packages
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,843 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository45 other files it gives its agents.
- dependency-analyzerSkill
- docsSkill
- handoffSkill
- openai-reviewerSkill
- plugin-homeSkill
- schema-validatorSkill
- security-auditSkill
- session-auditSkill
- test-validatorSkill
- claude-codeSkill
- codexSkill
- opencodeSkill
- chartsSkill
- export-csvSkill
- export-excelSkill
- make-chartSkill
- make-html-reportSkill
- make-pdfSkill
- a2a-communicateSkill
- a2a-handle-inboundSkill
- codebase-inspectionSkill
- ethos-skill-authoringSkill
- native-mcpSkill
- github-authSkill
- github-code-reviewSkill
- github-issuesSkill
- github-pr-workflowSkill
- github-repo-managementSkill
- birth-ritualSkill
- get-to-know-youSkill
- xurlSkill
- arxivSkill
- grounded-citationsSkill
- research-paper-writingSkill
- reddit-researchSkill
- code-reviewSkill
- coding-agentSkill
- planSkill
- requesting-code-reviewSkill
- spikeSkill
- subagent-driven-developmentSkill
- systematic-debuggingSkill
- tddSkill
- writing-plansSkill
- no-ai-slopSkill
The file
We split this AGENTS.md into the rules it gives an agent
4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Ask before adding to code you don't understand.
- Very specific: line 17
Verify before claiming: re-run pnpm test && pnpm typecheck && pnpm lint.
- Very specific: line 73
Every AgentLoop.run passes roomAudience → packages/core/src/__tests__/audience-census.test.ts.
- Very specific: line 100
Never cast API responses with as.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Ethos
Ethos is a TypeScript agent framework where personality (SOUL.md + toolset.yaml + config.yaml) is architecture, not a prompt string. Node 24, TypeScript 6 strict, pnpm, Biome 2, vitest, tsx in dev.
Behavioural rules
- Think before coding: state assumptions, surface tradeoffs, ask when unclear.
- Simplicity first: minimum code, nothing speculative.
- Surgical changes: touch only what you must, match existing style.
- Goal-driven: write the test first; run
pnpm checkbefore done andpnpm lintbefore pushing. - Surface conflicts, don't average them: pick one pattern, explain why, flag the other.
- Ask before adding to code you don't understand.
- Follow the constitution (ARCHITECTURE.md, enforced by
architecture.config.ts). Read it before: adding or moving a package, extension or app; adding a cross-layer workspace dependency; changing apackages/types/contract; touching asafety-*module; modifying a frozen schema; rawnode:fsin a personality boundary;console.*in library code. Refactor to fit or open an amendment (§VI). - Git safety: never commit to main unconfirmed; confirm each destructive git operation separately.
- Plan vs implementation: revising a plan means editing ONLY the plan file; wait for "now implement".
plan/is gitignored, no worktrees. - Verify before claiming: re-run
pnpm test && pnpm typecheck && pnpm lint; check each sub-agent-claimed bug against source. - Main session orchestrates; sub-agents execute. The main session does not write or edit files. Every code or doc change — even a one-line typo, a single-file rename, a single-language tweak — is delegated to a sub-agent via the Agent tool. Read-only inspection and verification stay here; AGENTS.md, CLAUDE.md and other agent-rule files may be edited here.
- Cite what enforces a guarantee. A comment or doc sentence asserting a guarantee — "X is refused", "Y is validated", "Z never happens" — names the file and symbol that enforces it, or the test that pins it. No enforcer you can name means write it down as a limitation.
Packages
Layer names are archcheck's.
packages/typeszero-dep contracts, frozen schemas →contractspackages/coreAgentLoop, registries, scoped fs →corepackages/wiringcomposition root (createAgentLoop, backup, locks) →wiringpackages/storage-fs,packages/safety/*Storage impls, safety-* →security-kernelpackages/config,packages/web-contracts,packages/sqlite(vendoredshim)extensions/llm-*,memory-*,tools-*,execution-*providers, backends, toolsets →extensionsextensions/platform-*+extensions/gatewaychannel adapters; gateway owns dedup, ledger, spool- SQLite stores:
session-sqlite,job-store,delivery-ledger,inbound-spool,notify-queue extensions/personalitiesregistry + built-insapps/*ethos (CLI), web-api, web, desktop, tui, mcp-server, acp-server →app-entry
Commands
make prepare # pnpm install
pnpm dev # chat
pnpm check # typecheck + lint + test
pnpm test | typecheck | lint | lint:fix
pnpm arch # archcheck
bash scripts/run-checks.sh # quiet, failures only
node scripts/check-agent-files.mjs # agent-file size gateDependency law
Allowed: types ← core ← extensions ← apps; packages/wiring is the only composition root.
Forbidden: upward imports, core importing implementations, extensions importing wiring. Enforced by the layer rules in architecture.config.ts and scripts/check-tool-imports.sh; pnpm exec archcheck explain <ruleId> gives the remedy.
Architecture checks (archcheck)
ARCHITECTURE.md says why each law exists; architecture.config.ts is the enforced projection — the layer table, banned constructs (console in libraries, process.env in tools, computed import(), empty catch, new FsStorage in libraries, raw Error in CLI commands) and their exceptions. archcheck checks it at pre-commit (archcheck --changed), pre-push (archcheck, archcheck emit --check, node scripts/check-archcheck-baseline.mjs), in pnpm test (packages/types/src/__tests__/archcheck.test.ts, archcheck-fixtures.test.ts) and in CI's architecture job. Pre-existing violations live in .archcheck/baseline.json, which only shrinks. scripts/check-architecture.mjs still checks tiers, the guarantee register, register claims, sidecar exceptions and stale paths — NOT layers.
What to do per pnpm arch exit code:
- 1 — a new violation. Fix the code using the finding's remedy (
pnpm exec archcheck explain <ruleId>). If the rule looks wrong for this case, STOP and raise a request to the maintainer with the rule id, the file, and the proposed manifest diff (a rule change or an exception with owner, expiry, reason, removal condition) — never apply it yourself. - 2 — the manifest or environment is broken (includes an expired exception). Stop and report; do not touch code or the manifest.
- 3 — emitted output is stale. Run
pnpm arch:emitand commit the regenerated ARCHITECTURE.md table and.archcheck/generated/. - 4 — a baselined violation was fixed. Run
pnpm arch:pruneand commit the smaller baseline.
Protected paths — changes need the maintainer's approval, and the Claude guard hook (scripts/guard-architecture.sh) blocks agent edits to them: architecture.config.ts, .archcheck/baseline.json, archcheck-fixtures/, packages/types/src/__tests__/archcheck.test.ts, packages/types/src/__tests__/archcheck-fixtures.test.ts, scripts/check-archcheck-baseline.mjs, scripts/guard-architecture.sh, .claude/settings.json (the hook's own registration). The hook also refuses baseline --write, --no-verify, LEFTHOOK=0, SKIP_PUSH_HOOK=1 and Architecture-Approved-By in shell commands — that trailer is the maintainer's to add, not an agent's.
Non-negotiables
- Storage only, no raw
node:fsfor~/.ethos/→apps/ethos/src/__tests__/no-raw-fs.test.ts. - No
console.*in libraries → archcheckl10-silent-libraries. - Extensionless imports (
./foo), the one hard rule. - Frozen schemas change only through their drift gates → ARCHITECTURE.md §VII.
- Drain
AgentLoop.run()to exhaustion →extensions/gateway/src/__tests__/turn-tail.test.ts. - Single owners, never a second writer →
.claude/rules/agent-loop.md. - Every
AgentLoop.runpassesroomAudience→packages/core/src/__tests__/audience-census.test.ts. - Static-first prompt →
packages/core/src/__tests__/prompt-prefix-stability.test.ts.
Where new code goes
| New | Where | Rule file |
| LLM provider | extensions/llm-<name>/, wire in packages/wiring | providers-and-tools |
| Tool | extensions/tools-* | providers-and-tools |
| Memory backend | extensions/memory-<name>/ | memory-tools |
| Channel adapter | extensions/platform-<name>/ | gateway-dedup |
| Personality | ~/.ethos/personalities/<id>/ | personality |
| CLI command | apps/ethos/src/commands/ | storage |
| SQLite store | extensions/<name>/ | sqlite-durability |
| Web RPC | packages/web-contracts + apps/web-api/src/rpc | ui-design |
Gotchas
- Node 24 before any
pnpm; vitest is 5.0.1, not 4. - Claude Code reads CLAUDE.md, not AGENTS.md, when both exist; here CLAUDE.md is a symlink to AGENTS.md, so edit AGENTS.md and keep the link.
- SQLite: STRICT tables,
rowidis not inSELECT *, tie-break onrowid. getMessages({ limit })returns the newest N.- A blocked
before_tool_callmust skip execution yet still persist atool_result. - Anthropic cache tokens are in
message_start; thinking params need theanycast. - OpenAI tool-call deltas key by index, not id.
openai's zod v3 peer warning is ignored on purpose.- Biome v2:
!dist/needs a trailing slash. - Never cast API responses with
as; use oRPC types or Zod.safeParse().
Deeper docs
.claude/rules/*.md load by path.
| File | Read when |
| agent-loop | AgentLoop, hooks, events, single owners |
| gateway-dedup, gateway-delivery-ledger, gateway-inbound-spool, gateway-audience-multibot | adapters, lost or double replies, replay, shared rooms |
| memory, memory-tools | memory scopes, memory tools, new backend |
| personality | personalities, PersonalityConfig limits |
| providers-and-tools | new provider or tool, result budget |
| storage | Storage, ScopedStorage, atomic writes |
| fs-carveouts-containment, -host, -locks, -sqlite | raw node:fs outside Storage |
| sqlite-durability, sqlite-gotchas | synchronous choice, STRICT/FTS5 |
| tool-progress-audience | ctx.emit progress |
| toolchain-gotchas | package.json, Biome, tsx |
| ui-design | any UI decision (also DESIGN.md) |
Also ARCHITECTURE.md, DESIGN.md, TESTING.md, .agents/skills/docs/SKILL.md, docs/content/building/reference/storage-interface.md.
Moved sections
Source comments cite CLAUDE.md, "<old heading>"; files in .claude/rules/.
- "Hook registry", "AgentEvent types", "Single-owner contracts" → agent-loop.md
- "Tool-progress audience boundary" → tool-progress-audience.md
- "Channel adapter contract" → gateway-*.md
- "Storage abstraction" → storage.md + fs-carveouts-*.md
- "SQLite durability posture", "Session key convention" → sqlite-durability.md, sqlite-gotchas.md
- "Adding a new LLM provider/tool" → providers-and-tools.md
- "Adding a personality", "What does NOT belong on PersonalityConfig" → personality.md
- "Memory", "Memory tool reference" → memory.md, memory-tools.md
- "Design system" → ui-design.md; "Learnings" → toolchain-gotchas.md
- "Monorepo layout", "Key files", "Core design principles" → dropped
Compact instructions
On compaction keep: the active plan path and task number; the failing gate and its .logs/ path; files touched; open decisions.
Drop tool output bodies.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

