The AGENTS.md slot
The block vexillum keeps inside your own AGENTS.md or CLAUDE.md, what each part of its markers means, and how it is protected from overwriting your edits.
vx init modifies your AGENTS.md or CLAUDE.md
vx init writes a block into your own AGENTS.md (or into your CLAUDE.md when the project has no AGENTS.md, see Where the block goes), and makes sure a Claude Code commander can see it (Pi and OpenCode read AGENTS.md on their own). These files are yours, so init first lists the files it is about to touch and asks for your consent before writing anything. Answer no and nothing is changed. See vx init and Quickstart.
What the slot is
The slot is a block that vexillum owns inside a file you own: your project's AGENTS.md, or its CLAUDE.md when there is no AGENTS.md. It carries the always-on core of the commander's rules, the few things that must be in context on every turn. Everything operational (how to dispatch, pick a model, land, ship, strike, react to the sentinel) lives in skills that Claude Code loads only when the moment calls for them.
Why a slot, and not a rules file of its own:
- One short block. The core is small and the detail is on demand.
- It lives in a file the ecosystem already reads.
AGENTS.mdandCLAUDE.mdare where your project's agent instructions go. vexillum adds to one of them instead of creating a parallel convention. - It is safe to share the file. Everything outside the markers is yours and is never reordered or rewritten.
The block is rendered by the binary, in English or Spanish. You can see the exact text on AGENTS.md block, generated from the binary so it cannot drift.
Where the block goes
The block lives in one file per project, chosen like this:
- If
AGENTS.mdexists, the block goes there (CLAUDE.mdthen importsAGENTS.md, see Why CLAUDE.md must import AGENTS.md). - If
AGENTS.mddoes not exist,vx initproposes putting the block inCLAUDE.mdinstead of creating anAGENTS.md. The default answer is yes, andCLAUDE.mdis created if it does not exist. With--yes(or without a terminal) the default is taken. - Answer no and
initcreatesAGENTS.mdwith the block, andCLAUDE.mdimports it.
This project has no AGENTS.md. Put the vexillum block in CLAUDE.md instead of creating an AGENTS.md? [Y/n]When the project already has a CLAUDE.md, the question reads Add the vexillum block to your CLAUDE.md instead of creating an AGENTS.md? and your text in the file is kept: the block is appended after it. In the CLAUDE.md case no import line is needed, because Claude Code reads the file itself.
Once a block exists, it stays where it is. init, upgrade and doctor find it in either file and keep it fresh there, even if an AGENTS.md shows up later. If both files carry a block, the one in AGENTS.md is the one that counts.
The marker format
<!-- BEGIN VEXILLUM v:1 hash:ab12cd34 -->
...the commander core...
<!-- END VEXILLUM -->The BEGIN marker
<!-- BEGIN VEXILLUM v:1 hash:<8hex> --> carries two pieces of metadata:
| Part | Meaning |
|---|---|
v:1 | The marker format, so vexillum knows how to read the block. |
hash:<8hex> | The first 8 hex characters of the SHA-256 of the block body: the text between the two markers, with line endings normalized to LF and trailing newlines dropped (the marker lines themselves are not hashed). It is how vexillum tells a block it wrote and you left alone from one you edited. |
The body
Between the markers is the commander core. It holds:
- Role check. The rules apply only to the commander. A soldier that reads them by accident (every camp is a checkout of your project, so it will) must follow its dispatch prompt and never dispatch more soldiers.
- Vocabulary. general, commander, soldier, mission, scout, camp, sentinel. These stay in English in every language.
- Authority. An explicit instruction from you overrides a rule, but the commander says which rule it set aside.
- Tone. How to address you, and to drop the flavor when the news is bad.
- The instruction to load the
vexillumskill. Before dispatching, picking a model, landing, shipping, striking or handling a sentinel notice, the commander must load the skill and follow it, not work from memory. This is the hard link between the always-on core and the on-demand detail.
The END marker
<!-- END VEXILLUM --> closes the block. Everything after it is yours again.
Why the markers sit on their own lines
Each marker is alone on its line. Claude Code strips block-level HTML comments from the files it loads into context, so a marker on its own line costs no tokens and cannot confuse the model. Detection is also anchored to the start of a line and ignores markers inside fenced code blocks, so a page that merely quotes the markers (like this one) is never mistaken for a block.
The states
vx doctor reports the slot's state (AGENTS.md vexillum block or CLAUDE.md vexillum block, whichever file holds it), and init and upgrade act on it.
| State | What it means for you |
|---|---|
| absent | There are no vexillum markers in the file. init appends the block after a blank line (or creates the file with only the block). |
| current | The block matches what this binary would write, marker included. Nothing to do. doctor prints current (en) or current (es). |
| stale | You did not touch the block, but it differs from this binary's version (a newer binary, or another language). upgrade refreshes it. |
| drifted | You edited inside the block: the body no longer matches its hash. vexillum will not overwrite it silently. |
| malformed | The markers are broken: a BEGIN without an END, an END before the BEGIN, or more than one block. Nothing is written until you confirm a repair. |
When you edit the block
The block is meant to be managed, but it is your file. If you change something inside the markers:
initandupgradeleave it as it is and print the diff between your version ("your edit") and the current template ("vexillum template");vx upgrade --forcereplaces it with the current template. Your edited version is first saved to.vexillum/agents-md-slot.backup.md. An earlier backup is overwritten.
vx doctor shows a drifted block as drifted, edited by hand.
If you want different always-on rules, put your own text outside the markers: it is yours and is never touched.
Malformed markers and repair
A malformed block is never fixed behind your back. vx upgrade lists the repairs and asks Apply these repairs? [Y/n] (--yes accepts). Before it writes, the whole file as it was is saved to .vexillum/AGENTS.md.backup (.vexillum/CLAUDE.md.backup when the block is in CLAUDE.md). The repair is deliberately narrow:
- it keeps the first well-formed BEGIN/END pair;
- it deletes every other duplicate pair, contents included;
- it deletes an orphan BEGIN or END marker line only, never the text around it.
If you decline, the file is left as it is. After a repair the block can still be drifted: Repair never judges the body, so a block you edited keeps your text until you run upgrade --force. init never repairs; it reports the problem and points you to upgrade.
Removing the block
There is no uninstall command. To take the block out, delete the BEGIN line, the END line and everything between them (and the blank line above), by hand. Your other text is untouched. Keep in mind that vx init or vx upgrade add the block back when it is absent, so remove it only if you are done with vexillum in that project.
Language
The slot ships in English and Spanish. The domain vocabulary stays in English in both.
When init or upgrade is about to write the block, the language is settled in this order:
--lang enor--lang es, if you pass it;- The language of a block that is already in the file, so a rerun does not flip it because your surrounding text reads differently;
- The language detected in your own text in the file that holds the block;
- English.
Detection is simple, deterministic and offline: it counts frequent function words of each language, ignoring code, URLs and the vexillum block itself. It needs at least 8 hits and a 70% share to decide; otherwise, and when the file has no text of yours, it defaults to English.
When the language was detected or defaulted (not given by --lang, and not read from an existing block), you see it before anything is written, for example Detected language: es (from AGENTS.md). (or CLAUDE.md) followed by Use es for the vexillum block? [Y/n]. Answer no and you are asked Language (en/es):. With --yes, or without a terminal, it is only announced.
The hash is per language, so switching language is an ordinary update of the block. vx doctor reports the language of the block it found.
Why CLAUDE.md must import AGENTS.md
Claude Code reads CLAUDE.md, not AGENTS.md. For the slot to reach the commander, CLAUDE.md has to import it with one line:
@AGENTS.mdThis applies when the block is in AGENTS.md. When the block is in CLAUDE.md itself there is nothing to import, and doctor does not report the import.
init checks this. If CLAUDE.md does not exist it is created with that line, as part of the consent notice. If it exists without the import, it is a file of yours with content in it, so init asks a second, separate question before appending the line:
CLAUDE.md does not import AGENTS.md, so Claude Code would not see the vexillum block. Add the line @AGENTS.md to it? [Y/n]Decline and init warns that Claude Code will not see the block and tells you to add the line yourself. A CLAUDE.md that is a symlink to AGENTS.md already counts as importing it. vx doctor reports it as CLAUDE.md imports AGENTS.md.
Related
- Skills: what loads on demand.
- AGENTS.md block: the exact text, in both languages.
vx init,vx upgradeandvx doctor.
AGENTS.md and rules
The commander's behavior is markdown in your project, not code in the binary, a short always-on core in AGENTS.md or CLAUDE.md, and skills.
Skills
The three skills vexillum ships for a Claude Code, Pi or OpenCode commander, what each is for, where they live and how upgrade keeps them current.