ADR-0029: One repo holds every LLM file, in two folders by audience
Status: Active · Date: 2026-10-13
References
- ADR-0027: Automations are standalone scripts, and Tranquil supplies their context: the rules for LLMs that every automation points to, which this ADR moves and republishes
- ADR-0026: Automations fill forms through a small, stable SDK on trusted input: the SDK that guide describes, and the test that ties the two together
Context
Tranquil writes a growing number of files whose reader is an LLM. They come in two kinds that do different jobs:
- Rules for agents working on Tranquil’s repos: how to change the code safely (security rules, owned packages, keyboard routing, tests), how to use the tools (the dev app, the test suite, the security lint), facts about each repo, and agent skills such as the docs review skill.
- User guides: files for a Tranquil user’s LLM, product content that tells a user’s agent how to write an automation. They ship with the app and are versioned with the SDK they describe. The automation guide is presented to users as the Tranquil Skill.
Before this decision they were scattered:
| What | Where it was |
|---|---|
| Cross-repo development rules | tranquil-client/CLAUDE.md |
Website rules and the tranquil-docs skill | www-tranquil/CLAUDE.md, www-tranquil/.claude/skills/ |
| About 50 rules and reference notes learned while working | one agent’s private memory folder, outside every repo |
| The automation guide | tranquil-automations/deno/authoring-guide.md, published as ~/.tranquil/automations/AGENTS.md |
Three problems followed from that:
- The project spans many sibling repos. A rule that applies to all of them had no home of its own: it lived in whichever repo it was first written in, and agents working in the other repos never saw it.
- The two kinds were easy to confuse. A file named for agents, sitting at the top of a repo, reads as instructions for working on that repo, even when it is a user guide.
- Private memory is invisible. Rules kept in one agent’s memory are not versioned, not reviewable, and not available to any other agent or person.
More files of both kinds are coming, so the layout has to take many more without rethinking it.
Agent tools are not built for this shape of project. They expect one repo per project, with its
instructions inside it: Claude Code loads CLAUDE.md from the folder it starts in and the folders
above it, and asks before loading anything from outside the project.cc Codex reads AGENTS.md files from the repo root down.codex A monorepo puts shared rules in a root file every package
sits under. Tranquil has no such root: its repos are siblings in a folder that is not itself a
repo, so there is nowhere standard for rules that apply to all of them.
Decision
Every file Tranquil writes for LLMs lives in one repo, tranquil-llm, in a folder for its
audience. Each code repo links to it rather than holding rules of its own. The app publishes the
users’ folder to ~/.tranquil/llm/.
The repo
tranquil-llm is a sibling of the other repos, cloned in the dev setup like them. Its two top-level
folders are never mixed:
| Folder | Read by | Ships with Tranquil? |
|---|---|---|
developers/ | agents working on Tranquil’s repos | no, never |
users/ | a Tranquil user’s LLM, writing automations | yes, published to ~/.tranquil/llm/ |
developers/ is organized by kind:
index.md, the entry point, linking every other file with a line on when to read it;rules/, how to work, one subject per file;tools/, how to use one tool per file;repos/, the facts specific to one repo per file;skills/, agent skills.
Conventions
- Topic-named files. No file in the repo is named
AGENTS.mdorCLAUDE.md. Agents load files of those names automatically, so a user guide given that name would be read as instructions for working on the repo it sits in. - A header line on every file, naming its audience:
developers/:<!-- For agents working on Tranquil's repos. Never shipped. -->users/:<!-- User guide: shipped with Tranquil and published to ~/.tranquil/llm/ for users' LLMs. Not instructions for working on any repo. -->
- Adding a file means putting it in the folder for its kind, giving it the header line, and
linking it from
developers/index.md(or naming it from a pointer, for a user guide).
How each audience finds its files
Agents on a code repo. Each code repo commits three small files that reach into the sibling
tranquil-llm:CLAUDE.md, a link to that repo’sdevelopers/repos/<repo>.md;.claude/CLAUDE.md, a link todevelopers/index.md;.claude/settings.json, listing../tranquil-llminadditionalDirectories, so an agent can read the files the index links to.
Claude Code loads a repo’s
CLAUDE.mdand.claude/CLAUDE.mdat startup, and follows the links with no prompt. The settings file takes effect once the folder is trusted, the prompt Claude Code shows for any new project.ccOther agents. Each code repo’s
AGENTS.mdnames the same two files in plain words, for agents that have no import syntax, such as Codex.codex When both files exist, Claude Code readsCLAUDE.md.ccUser-facing repos (tranquil-examples, tranquil-app-template, tranquil-ops-demo) get neither file. Users clone them, so an agent there is a user’s agent writing automations, and the first line of each script already points it at the automation user guide.
Users’ LLMs. On every start, a Tranquil-owned main-process module (
src/main-process/user-guides.js) copies the user guides from the linkedtranquil-llmpackage to~/.tranquil/llm/. Every user guide opens with the same header line, which also marks the copies: a file in the folder that carries it and is no longer a user guide in the app is removed, and any other file is left alone. Each user guide is named directly by its pointer, so the line every automation starts with becomes:// Tranquil automation. Rules for writing and changing it: ~/.tranquil/llm/writing-automations.mdSkills. Claude Code loads project skills from a repo’s
.claude/skills/, so each repo that uses a skill links to it there (www-tranquil/.claude/skills/tranquil-docspoints totranquil-llm/developers/skills/tranquil-docs).
What the multi-repo setup costs
None of this is how agent tools expect instructions to be laid out. Each piece below exists only because the rules live in a sibling repo rather than in the repo an agent works in:
| Piece | Where | Why it is needed |
|---|---|---|
Linked CLAUDE.md and .claude/CLAUDE.md | every code repo | an @path import of a sibling file waits for a per-repo approval; a linked file loads without one |
additionalDirectories in .claude/settings.json | every code repo | the index only links the other files, and reading outside the repo is otherwise blocked |
AGENTS.md in plain words | every code repo | Codex reads only AGENTS.md and has no import syntax, so other agents get the paths in words |
| A note on relative links | developers/index.md | an agent sees the index through a link, so rules/git.md must be read as ../tranquil-llm/developers/rules/git.md |
| Linked skills | each repo that uses one | skills load only from the repo’s own .claude/skills/ |
user-guides.js and link:../tranquil-llm | tranquil-client | the user guides ship from a repo that is not part of the SDK they describe |
| A guide test that finds the SDK through an import map entry for the sibling repo | tranquil-llm | the guide and the SDK are in different repos, so nothing else ties them together |
The llm-files check | lint:security | links, settings and pointer files are repeated in 19 repos, and any of them can drift |
The links are the least standard part. Claude Code documents links for sharing .claude/rules/ files, and asks before loading one that points outside the project;cc that a linked CLAUDE.md loads with no prompt was found by testing (claude -p loads nothing that needs approval), not
taken from the documentation.
The move
tranquil-client/CLAUDE.mdandwww-tranquil/CLAUDE.mdwere split into topic files, and the durable rules and reference notes in agent memory were sorted intorules/,tools/andrepos/, each keeping its reason and how to apply it. Memory keeps only a pointer to the repo.- The automation guide moved to
users/writing-automations.md, and its test with it: it imports the SDK from the sibling tranquil-automations repo through tranquil-llm’s import map and fails if the guide omits a core export, a command (Run, Check Custom Parts, Map Custom Parts) or its ask-first rules, if its error table differs from the SDK’s error codes, or if any example failsdeno checkor leaves out the pointer line. tranquil-automations no longer publishes anything for LLMs.
Enforcement
- In tranquil-llm,
deno task testchecks that only the two folders hold LLM files, that no file is namedAGENTS.mdorCLAUDE.md, that every file has its header line, and that every developer file is reachable fromdevelopers/index.md. - Across repos, the
llm-filescheck inlint:security(tranquil-test-suite) fails on anAGENTS.mdorCLAUDE.mdinside tranquil-llm, a file there without its header line, a code repo whose links or settings are missing or point elsewhere, anAGENTS.mdthat has grown rules, an instruction file in a user-facing repo, and a skill in.claude/skills/that is not a link into tranquil-llm.
Options considered
- tranquil-client as the hub. Keep every LLM file in the app’s repo, with the other repos pointing there. Not taken: tranquil-client is a Pulsar fork whose history is kept clean for upstream merges, every file in it reads as part of the app, and its own instruction file would mix rules for the whole project with facts about one repo.
- Guides beside their code. Keep each guide in the repo whose code it describes (the automation guide in the SDK repo) under a shared folder name. Not taken: the guides and rules stay scattered across repos, and nothing gathers the rules that apply to all of them.
- Leave the learned rules in agent memory. Not taken: memory is private to one agent on one machine, unversioned and unreviewed.
@pathimports in each repo’sCLAUDE.md. Not taken: Claude Code treats an import from outside the repo as external and asks once per repo, in an interactive session, before loading it; until then, and in every non-interactive run, the rules don’t load.cc Links load with no approval.- A
CLAUDE.mdin the shared parent folder. Claude Code loads it from every repo below it, with no approval. Not taken: the parent folder is not a repo, so the file could not be versioned, and every developer would have to create it by hand. - User-level rules in
~/.claude/rules/, which load in every project without approval.cc Not taken: they would load in every project on the machine, including users’ own automation folders, and each developer would have to set them up. - Rely on each agent’s own loading conventions, for example a guide published as
~/.tranquil/automations/AGENTS.md. Not taken: a file of that name reads as instructions for whatever folder it sits in, and loading conventions differ between agents. An explicit path in every pointer works for all of them.
Consequences
- One place for every LLM file, with its audience obvious from the folder and the first line. New rules, tools, repos and user guides have a slot without any new structure.
- Every agent and person sees the same rules, versioned and reviewed like code.
- One more repo to clone, and the app links it as a package (
link:../tranquil-llm) so it can shipusers/. - A non-standard layout to maintain. The pieces in “What the multi-repo setup costs” are
Tranquil’s own code and config, not a feature of any agent tool. A new code repo needs its links,
settings and
AGENTS.md, and a repo file indevelopers/repos/; the lint fails until it has them. Someone new to the project should expect the layout to differ from what agent docs describe. - The rules load with nothing to set up beyond cloning tranquil-llm as a sibling. The links
depend on that layout: a repo cloned alone has a broken
CLAUDE.md. Links also need a system that supports them in git (macOS and Linux do; Windows needs symlinks enabled). - The approach rests on undocumented behavior: Claude Code loads a
CLAUDE.mdlinked outside the repo with no prompt, while it asks before a linked rules file or an import. If a release changes that, the rules stop loading in every repo at once; aclaude -pcheck after each Claude Code update would catch it.lint:securitystill holds the layout, and the fallback is user-level rules. - Claude Code gets the most support. The links and settings are Claude Code’s; other agents
get
AGENTS.md, which names the files but loads none of them. - The native build does not ship the user guides yet. See below.
Before the first native build
Tranquil Studio has no native build yet, and this decision was implemented and checked in
development only. Evaluating the app build’s file patterns (script/electron-builder.js files, last match wins) against the files this ADR adds shows what a native build would ship
today:
| File | Native build today | Should |
|---|---|---|
tranquil-llm/users/*.md (the user guides) | dropped | ship |
tranquil-llm/developers/**, skills, README | dropped | stay out |
each repo’s CLAUDE.md, AGENTS.md, .claude/CLAUDE.md | dropped | stay out |
each owned package’s .claude/settings.json | ships | stay out |
tranquil-llm/deno.json | ships | stay out |
tranquil-llm/package.json, src/main-process/user-guides.js | ships | ship |
Everything that is dropped is dropped by one inherited Pulsar pattern, !**/*.{markdown,md,mkd,ts,jst,tgz,swp}, which also removes the automation SDK’s .ts files
(ADR-0026). The developer files stay out only by that accident. In a native build today, user-guides.js finds no user guides, logs an error and publishes nothing, so the pointer every
automation starts with names a file that does not exist.
Left for the native build pass:
- Ship the user guides. After the
.md/.tsexclusion, re-includenode_modules/tranquil-llm/users/**/*.md, alongside the SDK’s own re-include. - Keep developer files out on purpose. After that, exclude
node_modules/tranquil-llm/{developers,test}/**,node_modules/tranquil-llm/deno.jsonandnode_modules/*/.claude/**, so they stay out even if the.mdpattern changes. - Check both directions in
lint:security. Its test-exclusion check already evaluates the build patterns; add the reverse, failing when a user guide or an SDK file would not ship, or when anything underdevelopers/or.claude/would. - Confirm linked packages are packed. tranquil-llm reaches the app through
link:../tranquil-llm, like every owned package; whether electron-builder copies linked dependencies intoapp.asaras expected is open for all of them, and only a real native build answers it. - Smoke-test a native build. On first start,
~/.tranquil/llm/writing-automations.mdmatches the user guide in the app (read out ofapp.asar), and a second start rewrites nothing. - Check the pointer on Windows. The app publishes to
%USERPROFILE%\.tranquil\llm\; confirm that agents there resolve~/.tranquil/llm/writing-automations.mdto it, or name the path per platform in the guide.
- “How Claude remembers your project”, Claude Code documentation, Anthropic. https://code.claude.com/docs/en/memory↩
- “Custom instructions with AGENTS.md”, Codex documentation, OpenAI. https://learn.chatgpt.com/docs/agent-configuration/agents-md↩