Docs

ADR-0029: One repo holds every LLM file, in two folders by audience

Status: Active · Date: 2026-10-13

References

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:

WhatWhere it was
Cross-repo development rulestranquil-client/CLAUDE.md
Website rules and the tranquil-docs skillwww-tranquil/CLAUDE.md, www-tranquil/.claude/skills/
About 50 rules and reference notes learned while workingone agent’s private memory folder, outside every repo
The automation guidetranquil-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:

FolderRead byShips with Tranquil?
developers/agents working on Tranquil’s reposno, never
users/a Tranquil user’s LLM, writing automationsyes, 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.md or CLAUDE.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’s developers/repos/<repo>.md;
    • .claude/CLAUDE.md, a link to developers/index.md;
    • .claude/settings.json, listing ../tranquil-llm in additionalDirectories, so an agent can read the files the index links to.

    Claude Code loads a repo’s CLAUDE.md and .claude/CLAUDE.md at 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.cc

  • Other agents. Each code repo’s AGENTS.md names the same two files in plain words, for agents that have no import syntax, such as Codex.codex When both files exist, Claude Code reads CLAUDE.md.cc

  • User-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 linked tranquil-llm package 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.md
  • Skills. 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-docs points to tranquil-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:

PieceWhereWhy it is needed
Linked CLAUDE.md and .claude/CLAUDE.mdevery code repoan @path import of a sibling file waits for a per-repo approval; a linked file loads without one
additionalDirectories in .claude/settings.jsonevery code repothe index only links the other files, and reading outside the repo is otherwise blocked
AGENTS.md in plain wordsevery code repoCodex reads only AGENTS.md and has no import syntax, so other agents get the paths in words
A note on relative linksdevelopers/index.mdan agent sees the index through a link, so rules/git.md must be read as ../tranquil-llm/developers/rules/git.md
Linked skillseach repo that uses oneskills load only from the repo’s own .claude/skills/
user-guides.js and link:../tranquil-llmtranquil-clientthe 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 repotranquil-llmthe guide and the SDK are in different repos, so nothing else ties them together
The llm-files checklint:securitylinks, 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.md and www-tranquil/CLAUDE.md were split into topic files, and the durable rules and reference notes in agent memory were sorted into rules/, tools/ and repos/, 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 fails deno check or leaves out the pointer line. tranquil-automations no longer publishes anything for LLMs.

Enforcement

  • In tranquil-llm, deno task test checks that only the two folders hold LLM files, that no file is named AGENTS.md or CLAUDE.md, that every file has its header line, and that every developer file is reachable from developers/index.md.
  • Across repos, the llm-files check in lint:security (tranquil-test-suite) fails on an AGENTS.md or CLAUDE.md inside tranquil-llm, a file there without its header line, a code repo whose links or settings are missing or point elsewhere, an AGENTS.md that 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.
  • @path imports in each repo’s CLAUDE.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.md in 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 ship users/.
  • 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 in developers/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.md linked 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; a claude -p check after each Claude Code update would catch it. lint:security still 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:

FileNative build todayShould
tranquil-llm/users/*.md (the user guides)droppedship
tranquil-llm/developers/**, skills, READMEdroppedstay out
each repo’s CLAUDE.md, AGENTS.md, .claude/CLAUDE.mddroppedstay out
each owned package’s .claude/settings.jsonshipsstay out
tranquil-llm/deno.jsonshipsstay out
tranquil-llm/package.json, src/main-process/user-guides.jsshipsship

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:

  1. Ship the user guides. After the .md/.ts exclusion, re-include node_modules/tranquil-llm/users/**/*.md, alongside the SDK’s own re-include.
  2. Keep developer files out on purpose. After that, exclude node_modules/tranquil-llm/{developers,test}/**, node_modules/tranquil-llm/deno.json and node_modules/*/.claude/**, so they stay out even if the .md pattern changes.
  3. 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 under developers/ or .claude/ would.
  4. Confirm linked packages are packed. tranquil-llm reaches the app through link:../tranquil-llm, like every owned package; whether electron-builder copies linked dependencies into app.asar as expected is open for all of them, and only a real native build answers it.
  5. Smoke-test a native build. On first start, ~/.tranquil/llm/writing-automations.md matches the user guide in the app (read out of app.asar), and a second start rewrites nothing.
  6. Check the pointer on Windows. The app publishes to %USERPROFILE%\.tranquil\llm\; confirm that agents there resolve ~/.tranquil/llm/writing-automations.md to it, or name the path per platform in the guide.

  1. “How Claude remembers your project”, Claude Code documentation, Anthropic. https://code.claude.com/docs/en/memory↩
  2. “Custom instructions with AGENTS.md”, Codex documentation, OpenAI. https://learn.chatgpt.com/docs/agent-configuration/agents-md↩