Repository navigation
Specs launch
This spec covers how a seat is started and recorded: the rules text a seat is given and the three ways it reaches the seat, the per-seat rules file and the one line that names it, the profile that decides each CLI's launch line, exit, screens and rules mode, and the team state file the launch writes beside the team file. It leaves the agent, team and project records to the registry spec, the reading of a seat's state to the seat-state-and-watch spec, and the admission of the commands that launch to the Kernel and to the grants spec. It says what the code at the tag does, in the code's words.
- rules: the standing instructions a seat gets at launch; not a task.
-
delivery: how the rules reach the seat —
option,messageorprepend. - rules file: the file a message-delivered seat's rules are written to, in the project state folder.
- rules line: the one line typed into a message seat's pane, naming the rules file and the first twelve hex digits of its SHA-256.
-
profile: the shipped description of one CLI's launch line, screen grammar, rules delivery
and tested version range, keyed by the seat's
cli. - tested range: the two versions, both included, a profile was captured against.
-
state file:
.agents/team.state.jsonbeside the team file, holding the session's seats, worktrees, watch, hold and the project's last readings. -
stage: a seat record's word —
launched,namedorready. - waiting record: the record a launch leaves when a seat stops at a dialog it never answers.
- launched identity: the pane's shell pid and the foreground pids the launch recorded after the idle prompt.
-
project state folder:
.config/team/<project>-<hash>under the owner's home, beside the approval store.<project>is the project name with every character outsideA-Za-z0-9._-replaced by_.<hash>is the first twelve hexadecimal digits of SHA-256 of the root's canonical path, or of the path as given when it cannot be canonicalised (src/store/store.ts).
The rules are one text, built in a fixed order. The first four are the tool's own, in these words:
End every commit message and every pull request body with your signature, given below.Never stop at a question: tell the orchestrator (<name>) in one line and keep working.Never run `team grant`, `team delegate` or `team revoke`, and never edit `trust:` in the team file.In a protected checkout, never switch the branch, reset or commit.
Then, in this order:
| Part | Written from |
|---|---|
| the profile's own rules | the profile's standing_rules, a safety line the CLI makes necessary; often empty |
| the file's rules | the team file's rules list |
| the signature lines | two lines, from the file's signature templates and the seat |
| the workspace lines | the protected checkouts, and the worktree or shared-folder line |
The signature lines:
-
Your signature in a commit message, <place>: <commit signature>, where<place>isas a trailer, in a last paragraph of its own that holds trailers only,as its last line, oron a line of its own, from the file'scommits.position. -
Your signature in a pull request body, as its last line: <pull request signature>.
The workspace lines:
-
Protected checkouts, relative to the project root: <path>, <path>— only when the file names any. - In worktree mode:
Work on the code in the worktree your brief names, never in the checkout you started in.followed byBranches are named <pattern>.when the file names one. - In shared mode:
Change to <cwd> before any project work.where<cwd>is the seat's folder resolved against the project root.
The whole text is the headline, one - line per rule, and the delivery's closing line last:
Rules for this session, from the team file:
- <rule>
...
<closing line>
A rule that equals the closing line is written once, as the closing line.
| Delivery | How the rules reach the seat | Closing line | Rules file | state.rules |
|---|---|---|---|---|
option |
embedded in the launch option the profile names (--append-system-prompt for claude-code, --rules for grok) |
These are standing rules, not a task. |
none | option |
message |
written to the rules file, and one line typed into the pane at an empty idle prompt | These are standing rules, not a task: reply ready and wait for your brief. |
yes |
message, or undelivered when the line was not typed |
prepend |
prepended to every brief a send types into the pane; there is no standing session to keep them | These are standing rules for this session. The brief follows. |
none | prepend |
A first message is answered once, so its closing line asks for the ready reply; a launch option
stays in force on every later turn, so its closing line must not; prepended rules ride every
brief, so they say the brief follows. The delivery is the seat's profile's rules, defaulting to
message.
Path: <project state folder>/rules/<seat name>.md. The seat name must pass the team file's own
seat-name rule, and the file name must stay within 255 bytes; a name the file refuses gets no path
at all.
| What | Required |
|---|---|
the state root, .config/team
|
a real directory of this user's; whatever mode the user keeps |
| the project state folder | a real directory of this user's, mode exactly 0700
|
rules/ |
a real directory of this user's, mode exactly 0700
|
| the file | this user's regular file, mode exactly 0600
|
Writing: each level is checked with lstat and a missing level is made one at a time with an
explicit mode; the text lands through a temporary of an unpredictable name opened
O_CREAT | O_EXCL | O_NOFOLLOW at 0600 and renamed into place; the file is read back without
following a link and its SHA-256 compared with the hash the line carries. A link, a FIFO, another
owner or a wider mode is refused, never chmod'd or replaced.
The typed line:
Read <absolute path> (sha256 <first 12 hex digits>): your standing rules for this session; reply ready and wait for your brief.
Example:
Read <home>/.config/team/demo-3f9c2a8e1d7b/rules/implementer.md (sha256 5e1d0a9c4b2f): your standing rules for this session; reply ready and wait for your brief.
A path is typed only when every character is in A B C ... Z a b c ... z 0 9 . _ / @ + -; a path
holding whitespace or anything else is refused, never quoted or escaped. The line is read back row
by row — every visible character in order, a row break allowed to stand for at most one space or
nothing — and only then is Enter pressed, once. A box that already holds exactly the line is
verified and sent, never typed onto again. A box the run cannot verify is never cleared.
The refusals a message seat can meet, in the launch's words:
| Line | When |
|---|---|
<seat>: left out: rules not typed: the folder that would hold its rules file is <what>; the owner removes or repairs it, then runs up again |
a folder from the state root down to rules/ is a link, not a directory, another user's, or rules/ or the project folder is wider than 0700
|
<seat>: left out: rules not typed: its rules file's place holds <what>; the owner removes it, then runs up again |
the final name holds anything but this user's 0600 regular file |
<seat>: left out: rules not typed: its rules file did not read back as written; check the project state folder, then run up again |
the write landed and read back as another text |
<seat>: left out: rules not typed: its rules file could not be written; check the project state folder, then run up again |
any other write fault |
<seat>: left out: rules not typed: its rules file's path can't be typed safely: the read-back can't prove a path outside letters, digits and . _ / @ + -; rename the seat or move the project, then run up again |
the path holds a character the read-back cannot prove |
<seat>: left out: rules typed, not sent: the rules file changed after it was written |
the before-Enter look found another text; Enter was not pressed |
team status and team doctor check a message seat's file against the live file's rules text and
print one finding each: its rules file is missing, is a symbolic link, is not a regular file,
has mode <mode>, not 0600, is not owned by this user, cannot be read, or differs from the team file's rules; the repair is team reload <seat>, and no check ever rewrites the file.
Profiles ship with the tool, one per CLI, as src/profiles/<cli>.yaml; the loader parses each file
with its own parser, and src/profiles/profile.schema.json documents the shape the tests check the
shipped files against. The runtime does not load profiles through the schema. The launch-relevant
fields:
| Field | Type | Meaning |
|---|---|---|
format |
number | the profile file's format |
cli |
string | the key a seat's cli names |
binary |
string | the binary whose version is read, and the one herdr must see in the pane |
process_names |
string[] | the process names the caller check accepts |
tested.from, tested.to
|
string | the tested range, both ends included |
unattended |
string[] | options that run the CLI without approvals |
rules |
first-message | prepend | { option: <flag> }
|
the delivery: first-message reads as message, { option } as option
|
standing_rules |
string[] | rules for every seat of this CLI, over the file's |
login.check, login.hint
|
string[] / string | the arguments that exit 0 only when logged in, and the login command |
exit |
string | the text typed at an idle prompt to exit; absent when the CLI exits by key |
exit_keys |
string[] | the keys that exit an idle CLI; empty when exit is used |
exit_clear, exit_confirm
|
string | the one key that empties the box, and the one that confirms the CLI's exit question |
lobby_files |
string[] | the regular files the CLI may leave in its working folder |
startup_reads |
string[] | relative paths the CLI reads at start; a trailing / names a directory |
timeouts.idle, timeouts.exit
|
duration | the waits for the idle prompt and for the pane's shell after exit |
models.option, models.ids
|
string[] / rules | the model flag and the ids it maps to a model and version |
status_model |
rules | how a status line names the model |
quota |
patterns | account, window, used and reset readings |
screen |
stages | the CLI's dialog and prompt grammar: unknown, trust, permission, question, exit_question, provider_error, rate_limit, working, composer
|
herdr_status |
reliable | unreliable
|
whether herdr reports this CLI's status faithfully |
startup_reads is a YAML string list, not the loader's object form: each entry is a non-empty path
relative to the lobby, with no empty, . or .. segment and no *, ? or [; a trailing /
marks a directory, and the loader keeps { path, directory } in memory. Writing an object into a
profile is refused (src/profiles/profile.ts).
The shipped profiles at the tag:
| CLI | Binary | Rules delivery | Tested |
|---|---|---|---|
claude-code |
claude |
option (--append-system-prompt) |
2.1.288 to 2.1.302 |
codex |
codex |
message |
0.157.0 to 0.161.0 |
cursor |
cursor-agent |
message |
2026.10.01 to 2026.10.14 |
antigravity |
agy |
message |
1.2.16 to 1.4.1 |
grok |
grok |
option (--rules) |
1.0.50 to 1.0.52 |
gemini |
gemini |
message |
0.64.0 to 0.64.0 |
muse |
muse |
message |
1.4.9 to 1.4.9 |
jules |
jules |
prepend |
0.1.42 to 0.1.42 |
A version against a profile's range reads tested, older, newer or unread; team doctor
warns for older, newer and unread, the last saying its version cannot be read. team reload
refuses reload.untested for older and newer only — naming the version, the range and that
its ready screen may not be recognised — and closes nothing. An unread version is not evidence
against the CLI: it is warned by doctor and passes that reload gate.
The owner's override file is <project state folder>/overrides.yaml. It may add dialog patterns
for unknown, trust, permission and question, and quota patterns; it cannot remove a
shipped pattern, and it cannot change a composer, a prompt, a footer, a launch line or the order
of the stages — anything else is refused with its line. An edit takes effect only once the
approved copy records the text; until then the approved copy stays in force, and a copy that
cannot be read leaves the shipped profiles.
Lives at .agents/team.state.json, beside the team file. A missing file is an empty state; a
file that is not valid JSON, or is not format 1, is an error that refuses — never silently
replaced.
| Field | Type | Meaning |
|---|---|---|
format |
1 |
the file's format |
last_valid |
{ read_at, file } |
the last reading of the team file that verified, when the state records it |
budgets |
map | the project's last account readings, whatever session saw them |
spend |
map | the project's last spend readings |
hold |
{ reason, by, at, until? } |
the team's hold; a hold past until reads as none |
expired_policies |
string[] | expired policy declarations already logged |
sessions |
map | one entry per herdr session |
A session entry:
| Field | Type | Meaning |
|---|---|---|
started |
{ at, by } |
when and by whom the session was started |
seats |
map | the live seat records |
retained_seats |
map |
seat_<12 hex> handles kept across remove --keep, down and up's repair |
swapping |
map | a lead stopped for a replacement by remove <lead> --keep: who and when |
worktrees |
map |
{ path, branch, own_commits?, seat?, setup } per worktree |
watch |
{ pid?, heartbeat, pane?, workspace? } |
the watch's process, last pass, pane and workspace |
launched_file |
string | the team file the session was launched from |
watchdog |
{ file, pane? } |
the team file a flagless watch may read, and the pane that may read it |
nudge |
{ pending_since } |
the work drop the watch is waiting to type |
procs |
map | the processes seats recorded with team proc add
|
A seat record:
| Field | Type | Meaning |
|---|---|---|
id |
seat_<12 hex> |
the stable seat handle, minted when the seat is first recorded |
stage |
launched | named | ready
|
how far the launch has come |
cli |
string | the CLI launched, so a stop uses it even if the file renamed it |
last_active |
ISO 8601 | the last ready, or the last time the seat was seen working |
pane, workspace
|
string | herdr's pane and workspace |
start_cwd |
string | the folder the launch line ran in |
cli_version |
string | the version the CLI printed |
rules |
option | message | prepend | undelivered
|
how the rules were delivered |
worked |
boolean | whether the seat has been seen working |
launched |
{ shell, cli: number[] } |
the launched identity: the pane's shell pid and the CLI's pids |
agent_session |
string | the agent session herdr reported at idle, for continuity |
model, version
|
string | what the launch declared |
effort |
string | the effort word the launch set, when it set one |
launch_line |
string | the launch line as it ran |
temporary |
{ like, until, task?, own_commits? } |
a temporary seat's terms |
waiting |
{ state, classification, manual?, sentAt?, version?, folder? } |
a seat left at a dialog |
The waiting state is waiting-owner or trust-sent-recovery; its classification is one of the
closed list trust, permission, question, provider error, rate limit, vendor notice,
login, unknown, unsent, timeout, and anything else that enters the file reads unknown.
Every write holds .agents/team.lock and goes through a temporary file. The log is
.agents/team.log: one cleaned line per change — when, which command, by whom, what — rotated at
one megabyte with three kept; a log write that fails is dropped.
team up --json writes one team.up v1 document on stdout, its schema tag first: format,
dry_run, status (dry-run, or ready on a real run), action_summary, project, session,
seats (every name the file carries, once) and notes. A dry run's plan holds one
{ step, seat?, detail, prefix? } per plan line, a run step prefixed + and a skip skip; a
warning leads as { step: "warning", prefix: "!" } when there is one. A refusal writes one
team.error v1 document instead — its id, message, repair and, where it carries one,
rule — with stderr empty and the same exit code as without --json.
A team's seats start and wait in one lobby, chosen in this order:
- the file's explicit
lobby:entry, which is the owner's own declaration and is re-recorded each time it is read; - else the lobby the registry recorded for the session, which is kept: editing the file's
entity:never moves a recorded lobby; - else the entity's own lobby, one folder per entity under the tool's configuration folder;
- else the machine-global lobby of the releases before entities.
The lobby gate admits the lobby only when every component it reaches is a real directory of this
user, with no symbolic link on the way, and the lobby itself has mode exactly 0700. An
ancestor's mode is not tested; only the lobby's is. The seat's
CLI trust record is written in the lobby before the seat's workspace exists, so the launch meets
no folder-trust dialog there. A lobby the gate refuses ends the launch for every seat with
up.lobby.
Source: src/file/sections/lobby.ts (the lobby: entry), src/lobby/recorded.ts (the recorded
map), src/lobby/gate.ts (the gate), src/launch/pretrust.ts (the trust record written first).
Proof: test/commands/lobby.test.ts, test/lobby-recorded-acceptance.test.ts,
test/check-lobby-recorded.test.ts, test/launch/pretrust.test.ts.
team up [--dry-run] [--serial] [--session <name>] [--file <path>] [--json]
team add <name> [--model <model>] [--effort <effort>] [--dry-run] [--session <name>] [--file <path>] [--json]
team add --temporary --like <seat> --until <result:path|merged:branch> [--worktree <task>] [--model <model>] [--effort <effort>] [--dry-run] [--session <name>] [--file <path>] [--json]
team restart <seat> [--abandon] [--dry-run] [--session <name>] [--file <path>] [--json]
team reload <seat> [--file <path>] [--json]
team down [--dry-run] [--wait] [--abandon] [--session <name>] [--file <path>] [--json]
team remove <name> [--keep] [--abandon] [--session <name>] [--file <path>] [--json]
team down --wait gives a working seat up to 120 seconds to stop before the command proceeds
(WAIT_SECONDS, src/commands/down.ts).
team up's exit ids at the tag: up.ready and up.dry-run (0); up.agents, up.clear,
up.delegate, up.delegate-approval, up.delegate-command, up.delegate-evidence,
up.delegate-flag, up.delegate-placement, up.deny, up.detached, up.doctor,
up.grant-another-pane, up.grant-approval, up.grant-caller, up.grant-flag,
up.grant-no-pane, up.grant-scope, up.herdr, up.lobby, up.machine, up.never-approved,
up.no-launch, up.not-owner, up.pending, up.placement, up.run-lock, up.server,
up.stopped, up.unknown, up.watch (1); up.file, up.file-invalid, up.invocation,
up.not-a-repo (2). The other launch commands' ids are the exit-codes registry's.
-
A launch records what it started, in the state beside the file.
upMUST start the session, run each seat's launch line in its folder, wait for the idle prompt, name the pane, record the process identity, deliver the rules, write the state, the log and the registry, paint the sidebar and start the watch. A refusal before the first step MUST launch nothing. Source:src/launch/plan.ts,src/launch/execute.ts,src/launch/agent.ts. Proof:test/launch/launch.test.ts. -
The rules text's order is fixed. The tool's four MUST come first, then the profile's,
the file's, the seat's signature and the workspace's; the closing line MUST be last and a file
rule equal to it MUST be written once. Source:
src/launch/rules.ts(seatRules,rulesText). Proof:test/launch/launch.test.ts,test/launch/rules-file.test.ts. -
The delivery is the profile's choice. A seat's rules MUST travel as
option,messageorprependas its profile says, and a seat with no profile MUST default tomessage. Source:src/launch/rules.ts(rulesOf),src/profiles/profile.ts(rulesMode). Proof:test/profile-launch.test.ts,test/launch/rules-file.test.ts. -
A message seat's rules file is written whole, or nothing is typed. The path MUST be built
from the project's own state folder; every folder MUST be a real directory of this user's at
its required mode; the file MUST be this user's
0600regular file, written through an exclusive no-follow temporary and proved by a read-back hash. Source:src/launch/rules-file.ts(rulesFilePath,writeRulesFile). Proof:test/launch/rules-file.test.ts. -
The typed line names the file and its hash, and Enter follows the read-back alone. A path
MUST be refused, never quoted, unless it is in the typeable characters; the line MUST be read
back row by row before one Enter; a box the run cannot verify MUST NOT be cleared. Source:
src/launch/rules-file.ts(rulesLine,typeablePath,rulesFileHolds),src/launch/execute.ts. Proof:test/launch/launch.test.ts,test/agy-rules-readback-boundaries.test.ts. -
A profile is data the tool ships and validates. Each profile MUST name its CLI, binary,
tested range and rules delivery, and MUST be read by the loader's own parser; the JSON Schema
MUST remain the documented shape the tests check the shipped profiles against; a CLI with no
profile MUST NOT launch. Source:
src/profiles/profile.ts(loadShipped,launchOf,rulesOf),src/profiles/profile.schema.json. Proof:test/profile-schema.test.ts,test/profile-launch.test.ts. -
Outside its tested range, a CLI is read at launch only if its screens are recognised. A
version
older,newerorunreadMUST be warned bydoctor;reloadMUST refusereload.untestedforolderandneweronly and close nothing; anunreadversion alone MUST NOT refuse the reload. Source:src/profiles/profile.ts(versionVerdict),src/commands/doctor.ts,src/commands/reload.ts. Proof:test/launch/launch.test.ts(the version verdicts),test/commands/doctor-models.test.ts(the warnings),test/exit-codes.test.ts(thereload.untestedscene). -
The owner's overrides MAY add, never remove or change. An override MUST be limited to
dialog and quota patterns; anything else MUST be refused with its line; an edit MUST take
effect only once the approved copy records it. Source:
src/profiles/overrides.ts. Proof:test/overrides-approval.test.ts. -
A seat's stage and rules word are recorded by the launch. A record MUST carry
launched,namedorready, andoption,message,prependorundelivered; a record reachedreadyonly after the idle prompt appeared. Source:src/state.ts(SeatState),src/launch/execute.ts. Proof:test/state.test.ts,test/launch/launch.test.ts. -
A dialog at launch is never answered. The launch MUST NOT answer the dialog or type into
it. The owner at a terminal is asked; a delegated or terminal-less run takes the close path.
A kept seat MUST be left out with its classification and a
waiting-ownerrecord, and its workspace MUST be kept. A close path MAY close the workspace without input only when the seat's identity and ownership are proved; the record MUST then be dropped and the close said. A refused or failed close MUST preserve the waiting record. Source:src/launch/progress.ts(CLASSIFICATIONS),src/launch/execute.ts(atDialog),src/state.ts(SeatState.waiting). Proof:test/launch/pause.test.ts,test/launch/progress.test.ts,test/launch/launch.test.ts(the closed-without-input cases). -
The launched identity is pids, never a command line. The launch MUST record the pane's
shell pid and the CLI's foreground pids after the idle prompt; a pane whose shell is in front
with no CLI MUST read
gone; a pane fronting a program the record does not name MUST readreplaced, and is the seat again only when herdr names the seat there and the agent session is the one stored at launch. Source:src/launch/identity.ts(LaunchedIdentity,seatProcessVerdict,replacedSeat). Proof:test/launch/identity.test.ts. -
The state file is written by the tool alone, whole or not at all. Every write MUST hold
the team's lock and go through a temporary file; a missing file MUST read as empty; an
unreadable or wrong-format file MUST refuse, never be replaced silently. Source:
src/state.ts(readState,writeAtomic,LOCK_FILE). Proof:test/state.test.ts,test/unsigned-state-boundaries.test.ts. -
A seat record the file no longer declares is read past. Only a temporary seat's record
MUST stand without a file declaration;
team check --repairMAY drop the rest. Source:src/state.ts(seatOfFile). Proof:test/state-departed-seats.test.ts.
operations (the commands this area owns, by gate):
| Entry | Meaning | Since | Source at the tag | Note |
|---|---|---|---|---|
up |
the owner, or leads for its own team |
0.5.0 | src/permissions/map.ts |
the start row |
down |
the owner, or leads for its own team |
0.5.0 | src/permissions/map.ts |
the stop row; the owner may always stop |
restart |
the owner, or leads for its own team |
0.5.0 | src/permissions/map.ts |
the start row for one seat |
reload |
the owner, or leads for its own team |
0.5.0 | src/permissions/map.ts |
the start row for a running seat |
add |
the owner alone | 0.5.0 | src/permissions/map.ts |
where no agree or grant holders stand |
remove |
the owner, or leads for its own team |
0.5.0 | src/permissions/map.ts |
a seat holding grant, agree or leads stands only by the owner |
exit-codes (the team up rows):
| Entry | Meaning | Since | Source at the tag | Note |
|---|---|---|---|---|
up.ready |
the launch finished | 0.5.0 | contract/exit-codes.json |
exit 0 |
up.dry-run |
the plan, or the refusal a real run would give | 0.5.0 | contract/exit-codes.json |
exit 0 |
up.deny |
deny | 0.5.0 | contract/exit-codes.json |
exit 1; a refused real run answers this one word |
up.detached |
a run with no terminal | 0.5.0 | contract/exit-codes.json |
exit 1 |
up.machine |
the machine is over a launch limit | 0.5.0 | contract/exit-codes.json |
exit 1 |
up.run-lock |
another session-mutating run holds the session | 0.5.0 | contract/exit-codes.json |
exit 1 |
up.lobby |
the lobby could not be created | 0.5.0 | contract/exit-codes.json |
exit 1 |
up.pending |
a seat was left short of ready | 0.5.0 | contract/exit-codes.json |
exit 1 |
up.watch |
the watch did not start | 0.5.0 | contract/exit-codes.json |
exit 1 |
up.file |
the team file can't be read | 0.5.0 | contract/exit-codes.json |
exit 2 |
up.file-invalid |
the team file can't be parsed | 0.5.0 | contract/exit-codes.json |
exit 2 |
up.invocation |
the invocation can't be read | 0.5.0 | contract/exit-codes.json |
exit 2 |
up.not-a-repo |
not inside a git repository | 0.5.0 | contract/exit-codes.json |
exit 2 |
The full set, up.agents to up.unknown included, is the up rows of contract/exit-codes.json.
cli-ranges (the shipped profiles):
| Entry | Meaning | Since | Source at the tag | Note |
|---|---|---|---|---|
claude-code |
binary claude; 2.1.288 to 2.1.302 |
0.5.0 | src/profiles/claude-code.yaml |
rules as an option |
codex |
binary codex; 0.157.0 to 0.161.0 |
0.5.0 | src/profiles/codex.yaml |
rules as a first message |
cursor |
binary cursor-agent; 2026.10.01 to 2026.10.14 |
0.5.0 | src/profiles/cursor.yaml |
rules as a first message |
antigravity |
binary agy; 1.2.16 to 1.4.1 |
0.5.0 | src/profiles/antigravity.yaml |
rules as a first message |
grok |
binary grok; 1.0.50 to 1.0.52 |
0.5.0 | src/profiles/grok.yaml |
rules as an option |
gemini |
binary gemini; 0.64.0 to 0.64.0 |
0.5.0 | src/profiles/gemini.yaml |
rules as a first message |
muse |
binary muse; 1.4.9 to 1.4.9 |
0.5.0 | src/profiles/muse.yaml |
rules as a first message |
jules |
binary jules; 0.1.42 to 0.1.42 |
0.5.0 | src/profiles/jules.yaml |
rules prepended to each brief |
-
Eight profiles ship, seven are named. The Runtime text's must-not-pretend line names seven
CLIs with a profile; the tag ships eight,
julesbeside them, whose rules are prepended because its TUI keeps no standing session. -
No launcher registry. A profile's launch line is the file's text, checked where it will
start; the
launcherreference a text names is declared and never resolved. - No hash-pinned start command. The launch line is recorded as it ran; the per-seat digest of prompt, instructions, environment and permissions that a text names is not built.
-
The state's
budgetsandspendare the budget text's. This spec records their place in the file and leaves their reading, marks and staleness to the budgets spec. -
last_validis a remembered valid reading, not an approval.currentTeamrecords the text of a file that loaded, and when an existing file no longer validates it returns the remembered copy with a notice naming the copy's date (src/file/current.ts). A missing file does not take that fallback. Only the commands that must keep working read this way —status,watchanddown; the commands that launch or change anything load the live file and refuse an invalid one. The remembered text proves that it validated once and is not an approval record. -
A message seat's rules are the live file's, never the approved copy's. Both the folder and
the text follow the live file: the delivery helper ignores its standing-copy arguments and
derives the path from the live project's name (
src/launch/rules-file.ts), anduppasses the live project to the writer (src/commands/up.ts). A project rename therefore moves the path with the file; the approved copy is not consulted. - CLI extension contracts (0002). Waits for the CLI extension contracts spec: the screen grammar, the composer-region safety floor, the restricted portable patterns, the staged escape hatch and cross-implementation conformance.
- Draft (the Runtime text's writer, 2026-10-18): lifted from the Runtime's chapters D and I; read at the tag.
-
Draft, amended (the Runtime text's writer, 2026-10-18): a second read against the tag
corrected eight points — the rules path follows the live file; the remembered-valid fallback is
described;
startup_readsis a YAML string list; the loader's parser, not the schema, enforces;reloadrefuses onlyolderandnewer; the dialog's prompt, keep and safe-close outcomes are separated; the lobby's exact mode check is its own; and the store folder's hash and project-name sanitiser are given.
Generated from docs/specs/launch.md at v0.5.2 (1d1224a4) — edit the repository, not this page.