[{"data":1,"prerenderedAt":82},["ShallowReactive",2],{"doc:en:escouade-yml":3},{"title":4,"lede":5,"html":6,"headings":7},".escouade.yml","A .escouade.yml file at the root of the repository holds the project settings the whole team shares. This page is the reference of its format: every key, its values, how it is read, and what Escouade does with it.","\u003Ch2 id=\"what-it-is-for\">What it is for\u003C\u002Fh2>\n\u003Cp>The file is committed with the code. Everyone who adds the repository to Escouade gets the same way of working: one worktree per agent, the same branch prefixes, the same setup commands, the same ticket approval. Escouade reads it when the project opens, reads it again when it changes, and can write it from a project that is already set up.\u003C\u002Fp>\n\u003Ch2 id=\"a-complete-example\">A complete example\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-yaml\"># yaml-language-server: $schema=https:\u002F\u002Fescouade.dev\u002Fschemas\u002Fescouade.schema.json\nversion: 1\nagents:\n  engine: claude\nprivate: false\nworktrees:\n  per_agent: true\n  at_first_message: true\n  base: target\n  dir: ..\u002Fapp-worktrees\n  copy:\n    - &#39;.env*&#39;\n    - config\u002Flocal.json\n  setup:\n    - npm ci\n    - command: cargo fetch\n      cwd: src-tauri\n  teardown:\n    - command: docker compose down\n      shell: bash\nlaunch:\n  - name: web\n    command: npm run dev\n    cwd: web\n  - name: api\n    command: cargo run\n    cwd: api\ngit:\n  agent_branch_prefix: agent\u002F\n  ticket_branch_prefix: ticket\u002F\n  commit_mode: agent\n  conventional_commits: true\nboard:\n  on_approve: merge\n  target_branch: main\n  merge_strategy: squash\n  draft_pr: false\n  test_command: npm test\n  tests_before_approve: true\n  on_conflict: agent\n  remove_worktree: true\n  model: sonnet\n  effort: medium\n  mode: auto\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>A minimal file only says what it wants to set:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yaml\">version: 1\nworktrees:\n  per_agent: true\nboard:\n  merge_strategy: rebase\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"the-rules-of-the-format\">The rules of the format\u003C\u002Fh2>\n\u003Ch3 id=\"the-style-of-the-keys\">The style of the keys\u003C\u002Fh3>\n\u003Cp>Keys are in English, in \u003Ccode class=\"key\">snake_case\u003C\u002Fcode> (lowercase words joined by \u003Ccode class=\"key\">_\u003C\u002Fcode>), sorted into groups by theme: \u003Ccode class=\"key\">agents\u003C\u002Fcode>, \u003Ccode class=\"key\">worktrees\u003C\u002Fcode>, \u003Ccode class=\"key\">git\u003C\u002Fcode> and \u003Ccode class=\"key\">board\u003C\u002Fcode> hold their keys indented; \u003Ccode class=\"key\">version\u003C\u002Fcode> and \u003Ccode class=\"key\">launch\u003C\u002Fcode> are at the top level. The order of groups and keys is free. The file is YAML 1.2: a \u003Ccode class=\"key\">#\u003C\u002Fcode> starts a comment, and comments are kept when Escouade writes the file again.\u003C\u002Fp>\n\u003Ch3 id=\"the-version-key\">The version key\u003C\u002Fh3>\n\u003Cp>\u003Ccode class=\"key\">version\u003C\u002Fcode> is the number of the file’s format, a whole number: \u003Ccode class=\"key\">1\u003C\u002Fcode> today. Escouade writes it at the top of every file it creates. It is not required: without it, the file is read as version 1, and the “.escouade.yml” group of Settings › Projects says so (“no “version” key: read as version 1”). A value that is not a whole number of at least 1 (\u003Ccode class=\"key\">one\u003C\u002Fcode>, \u003Ccode class=\"key\">'1'\u003C\u002Fcode>, \u003Ccode class=\"key\">0\u003C\u002Fcode>) is told the same way, and the file is read as version 1.\u003C\u002Fp>\n\u003Ch3 id=\"an-older-or-a-newer-version\">An older or a newer version\u003C\u002Fh3>\n\u003Cp>The format can evolve: each version of Escouade reads the ones it knows. A file of an older version is migrated to the current one as it is read, one version to the next, without being written back to disk: it stays valid as it is. A file of a newer version than the one Escouade knows is read as well as possible: the known keys apply, the others are told as unknown, with the warning “made for a newer version of Escouade (file version 2, 1 known here): read as well as possible”. Escouade doesn’t write over such a file: “Export to .escouade.yml” refuses it.\u003C\u002Fp>\n\u003Ch3 id=\"a-missing-key\">A missing key\u003C\u002Fh3>\n\u003Cp>Every key is optional, \u003Ccode class=\"key\">version\u003C\u002Fcode> included. A missing key changes nothing: the project keeps its value. The “Missing” column of the tables below gives the value of a new project, Escouade’s default. Removing a key from the file doesn’t set the project back to that value: it keeps the last one the file gave it.\u003C\u002Fp>\n\u003Ch3 id=\"an-unknown-key\">An unknown key\u003C\u002Fh3>\n\u003Cp>A key Escouade doesn’t know (a typo, or a key from a newer version) doesn’t stop the reading: it is ignored and told with its line. When it looks like a known key of the same group, or bears the name of a key of another group, Escouade proposes the right one:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode class=\"key\">worktrees.per_agnet\u003C\u002Fcode>: “unknown key: worktrees.per_agnet (did you mean worktrees.per_agent?), ignored”;\u003C\u002Fli>\n\u003Cli>\u003Ccode>worktrees.test_command\u003C\u002Fcode>: “unknown key: worktrees.test_command (did you mean board.test_command?), ignored”;\u003C\u002Fli>\n\u003Cli>an unknown group, \u003Ccode class=\"key\">bord:\u003C\u002Fcode> for instance, is told the same way (“did you mean board?”), and all it holds is ignored.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"an-invalid-value\">An invalid value\u003C\u002Fh3>\n\u003Cp>A value of the wrong type or outside the allowed values is ignored and told with its line and what is expected; the rest of the file applies: “invalid value for board.merge_strategy: “fast” (expected: merge, squash, rebase) (ignored)”. In a list of steps or commands, only the invalid item is ignored, the others stay. A group that is not a set of keys (\u003Ccode>board: true\u003C\u002Fcode>) is ignored whole.\u003C\u002Fp>\n\u003Cp>A file that isn’t readable YAML (an unclosed bracket, broken indentation), or whose top level isn’t a set of keys, applies nothing: the message says why and at which line.\u003C\u002Fp>\n\u003Ch2 id=\"the-types-of-values\">The types of values\u003C\u002Fh2>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>YAML form\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode> or \u003Ccode class=\"key\">false\u003C\u002Fcode>, without quotes (any case)\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>per_agent: true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Text\u003C\u002Ftd>\n\u003Ctd>A single value, with or without quotes; \u003Ccode class=\"key\">''\u003C\u002Fcode> or \u003Ccode class=\"key\">~\u003C\u002Fcode> is an empty text\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>target_branch: main\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>A text, exactly one of the allowed values\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>merge_strategy: squash\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>List of texts\u003C\u002Ftd>\n\u003Ctd>A YAML list, as \u003Ccode>- …\u003C\u002Fcode> lines or in brackets; a single value is a list of one; \u003Ccode class=\"key\">[]\u003C\u002Fcode> or \u003Ccode class=\"key\">~\u003C\u002Fcode> is an empty list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>copy: config\u002Flocal.json\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Relative path\u003C\u002Ftd>\n\u003Ctd>A text, relative to the repository; a full path (\u003Ccode class=\"key\">\u002F…\u003C\u002Fcode>, \u003Ccode class=\"key\">\\…\u003C\u002Fcode>, \u003Ccode class=\"key\">C:…\u003C\u002Fcode>) or one from the home folder (\u003Ccode class=\"key\">~…\u003C\u002Fcode>) is refused\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>dir: ..\u002Fapp-worktrees\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Branch prefix\u003C\u002Ftd>\n\u003Ctd>A text that can start a git branch name: no spaces, \u003Ccode class=\"key\">..\u003C\u002Fcode>, \u003Ccode class=\"key\">~\u003C\u002Fcode>, \u003Ccode class=\"key\">^\u003C\u002Fcode>, \u003Ccode class=\"key\">:\u003C\u002Fcode>, \u003Ccode class=\"key\">?\u003C\u002Fcode>, \u003Ccode class=\"key\">*\u003C\u002Fcode>, \u003Ccode class=\"key\">[\u003C\u002Fcode>, \u003Ccode class=\"key\">\\\u003C\u002Fcode> or \u003Ccode class=\"key\">@{\u003C\u002Fcode>, no \u003Ccode class=\"key\">-\u003C\u002Fcode> or \u003Ccode class=\"key\">\u002F\u003C\u002Fcode> at the start, no \u003Ccode class=\"key\">\u002F\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>agent_branch_prefix: agent\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>\u003Ccode class=\"key\">'true'\u003C\u002Fcode> in quotes is text, not a boolean, and \u003Ccode class=\"key\">yes\u003C\u002Fcode>, \u003Ccode class=\"key\">no\u003C\u002Fcode>, \u003Ccode class=\"key\">on\u003C\u002Fcode>, \u003Ccode class=\"key\">off\u003C\u002Fcode> are not booleans (YAML 1.2). A number is read as text where text is expected (\u003Ccode>target_branch: 2024\u003C\u002Fcode> is the branch \u003Ccode class=\"key\">2024\u003C\u002Fcode>). A pattern that starts with \u003Ccode class=\"key\">*\u003C\u002Fcode> is written in quotes (\u003Ccode class=\"key\">'*.local'\u003C\u002Fcode>): without them, YAML reads an alias.\u003C\u002Fp>\n\u003Ch2 id=\"the-keys\">The keys\u003C\u002Fh2>\n\u003Ch3 id=\"agents\">agents\u003C\u002Fh3>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>Values\u003C\u002Fth>\n\u003Cth>Missing\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">agents.engine\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">claude\u003C\u002Fcode>, \u003Ccode class=\"key\">codex\u003C\u002Fcode>, \u003Ccode class=\"key\">copilot\u003C\u002Fcode>, \u003Ccode class=\"key\">opencode\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">claude\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>engine: codex\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>The harness of the project’s new agents and tickets that don’t choose another (“Default harness”).\u003C\u002Fp>\n\u003Ch3 id=\"private\">private\u003C\u002Fh3>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>Values\u003C\u002Fth>\n\u003Cth>Missing\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">private\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>each machine’s setting\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>private: true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>“Private project”: the agents of the other projects don’t see it through Escouade’s MCP server and don’t read its files (see \u003Ca href=\"\u002Fen\u002Fdocs\u002Fsettings-projects\u002F\">Settings › Projects\u003C\u002Fa>). The repository is sensitive for the whole team, hence its place in the file; the accounts reserved to the project stay each machine’s own.\u003C\u002Fp>\n\u003Cp>The file can make a project private, never public again: on a machine where the project is private, \u003Ccode>private: false\u003C\u002Fcode> isn’t applied, the setting becomes a local setting of this machine and a warning says so (“private: false ignored: this project is private on this machine, untick “Private project” to make it public”). To make it public, untick “Private project” yourself.\u003C\u002Fp>\n\u003Ch3 id=\"worktrees\">worktrees\u003C\u002Fh3>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>Values\u003C\u002Fth>\n\u003Cth>Missing\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">worktrees.per_agent\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>per_agent: true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>worktrees.at_first_message\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>at_first_message: false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">worktrees.base\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Text\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">head\u003C\u002Fcode>, \u003Ccode class=\"key\">target\u003C\u002Fcode> or a branch name\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">head\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>base: origin\u002Frelease\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">worktrees.dir\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Relative path\u003C\u002Ftd>\n\u003Ctd>A folder relative to the repository\u003C\u002Ftd>\n\u003Ctd>empty: \u003Ccode class=\"key\">.claude\u002Fworktrees\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>dir: .worktrees\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">worktrees.copy\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>List of texts\u003C\u002Ftd>\n\u003Ctd>File patterns (\u003Ccode class=\"key\">*\u003C\u002Fcode>, \u003Ccode class=\"key\">**\u003C\u002Fcode>)\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">['.env*']\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>copy: ['.env*', config\u002Flocal.json]\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">worktrees.setup\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>List of steps\u003C\u002Ftd>\n\u003Ctd>See \u003Ca href=\"#worktree-steps\">worktree steps\u003C\u002Fa>\u003C\u002Ftd>\n\u003Ctd>none\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>setup: npm ci\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">worktrees.teardown\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>List of steps\u003C\u002Ftd>\n\u003Ctd>See \u003Ca href=\"#worktree-steps\">worktree steps\u003C\u002Fa>\u003C\u002Ftd>\n\u003Ctd>none\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>teardown: [docker compose down]\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cul>\n\u003Cli>\u003Ccode class=\"key\">per_agent\u003C\u002Fcode>: “One worktree per agent”, each new agent in a worktree of its own (see \u003Ca href=\"\u002Fen\u002Fdocs\u002Fworktrees\u002F\">worktrees\u003C\u002Fa>).\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">at_first_message\u003C\u002Fcode>: “Create the worktree at the first message, under the agent’s name”. A new agent’s worktree waits for its first message, which names it: its branch and its folder take that name (see \u003Ca href=\"\u002Fen\u002Fdocs\u002Fworktrees\u002F#at-the-first-message\">at the first message\u003C\u002Fa>). \u003Ccode class=\"key\">false\u003C\u002Fcode> creates it at once, as \u003Ccode class=\"key\">agent-N\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">base\u003C\u002Fcode>: “Starting branch of new worktrees”, the branch a new agent’s worktree starts from, its base: \u003Ccode class=\"key\">head\u003C\u002Fcode> (the folder’s branch), \u003Ccode class=\"key\">target\u003C\u002Fcode> (the board’s target branch) or a branch’s name, local or remote (\u003Ccode class=\"key\">origin\u002Frelease\u003C\u002Fcode>). A branch named \u003Ccode class=\"key\">head\u003C\u002Fcode> or \u003Ccode class=\"key\">target\u003C\u002Fcode> is written \u003Ccode class=\"key\">refs\u002Fheads\u002Ftarget\u003C\u002Fcode>. See \u003Ca href=\"\u002Fen\u002Fdocs\u002Fworktrees\u002F#the-starting-branch\">the starting branch\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">dir\u003C\u002Fcode>: “Worktrees folder”. It can’t be the project’s folder, a folder holding it, or a folder in \u003Ccode class=\"key\">.git\u003C\u002Fcode>: such a path is told and ignored.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">copy\u003C\u002Fcode>: “Files copied into worktrees”, the files git doesn’t track copied into every new worktree.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">setup\u003C\u002Fcode>: “When a worktree opens”, run one after the other in every new worktree, before its agent’s first message. Commands: they wait for your approval.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">teardown\u003C\u002Fcode>: “Before a worktree is removed”, run in a worktree before Escouade removes it. Commands: they wait for your approval.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"launch\">launch\u003C\u002Fh3>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>Values\u003C\u002Fth>\n\u003Cth>Missing\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">launch\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>List of launch commands\u003C\u002Ftd>\n\u003Ctd>See \u003Ca href=\"#launch-commands\">launch commands\u003C\u002Fa>\u003C\u002Ftd>\n\u003Ctd>none\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>- name: web\u003C\u002Fcode> then \u003Ccode>command: npm run dev\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>The project’s “Launch” commands (dev servers, watchers), each in its own terminal (see \u003Ca href=\"\u002Fen\u002Fdocs\u002Flaunch\u002F\">launch\u003C\u002Fa>). Commands: they wait for your approval.\u003C\u002Fp>\n\u003Ch3 id=\"git\">git\u003C\u002Fh3>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>Values\u003C\u002Fth>\n\u003Cth>Missing\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode>git.agent_branch_prefix\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Branch prefix\u003C\u002Ftd>\n\u003Ctd>The start of a branch name\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">escouade\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>agent_branch_prefix: agent\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>git.ticket_branch_prefix\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Branch prefix\u003C\u002Ftd>\n\u003Ctd>The start of a branch name\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">ticket\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>ticket_branch_prefix: tickets\u002F\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">git.commit_mode\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">agent\u003C\u002Fcode>, \u003Ccode class=\"key\">direct\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">agent\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>commit_mode: direct\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>git.conventional_commits\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>conventional_commits: false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cul>\n\u003Cli>\u003Ccode class=\"key\">agent_branch_prefix\u003C\u002Fcode>: a new agent’s branch is \u003Ccode class=\"key\">&lt;prefix&gt;&lt;name&gt;\u003C\u002Fcode>. Empty (\u003Ccode class=\"key\">''\u003C\u002Fcode>), it is its name alone.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">ticket_branch_prefix\u003C\u002Fcode>: a ticket’s branch is \u003Ccode class=\"key\">&lt;prefix&gt;&lt;key&gt;\u003C\u002Fcode> (\u003Ccode class=\"key\">ticket\u002FDEM-12\u003C\u002Fcode>).\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">commit_mode\u003C\u002Fcode>: “Commit”, who writes the commits asked from the files panel: \u003Ccode class=\"key\">agent\u003C\u002Fcode> (“Written by the agent”) or \u003Ccode class=\"key\">direct\u003C\u002Fcode> (“Direct, with a suggested message”).\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">conventional_commits\u003C\u002Fcode>: “Generated commit message”, messages in the Conventional Commits form.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"board\">board\u003C\u002Fh3>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Key\u003C\u002Fth>\n\u003Cth>Type\u003C\u002Fth>\n\u003Cth>Values\u003C\u002Fth>\n\u003Cth>Missing\u003C\u002Fth>\n\u003Cth>Example\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.on_approve\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">merge\u003C\u002Fcode>, \u003Ccode class=\"key\">pr\u003C\u002Fcode>, \u003Ccode class=\"key\">push\u003C\u002Fcode>, \u003Ccode class=\"key\">keep\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">merge\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>on_approve: pr\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.target_branch\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Text\u003C\u002Ftd>\n\u003Ctd>A branch name\u003C\u002Ftd>\n\u003Ctd>empty: the folder’s branch at the first ticket\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>target_branch: develop\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.merge_strategy\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">merge\u003C\u002Fcode>, \u003Ccode class=\"key\">squash\u003C\u002Fcode>, \u003Ccode class=\"key\">rebase\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">squash\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>merge_strategy: rebase\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.draft_pr\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>draft_pr: true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.test_command\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Text\u003C\u002Ftd>\n\u003Ctd>A command\u003C\u002Ftd>\n\u003Ctd>empty: none\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>test_command: npm test\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>board.tests_before_approve\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>tests_before_approve: true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.on_conflict\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">ask\u003C\u002Fcode>, \u003Ccode class=\"key\">agent\u003C\u002Fcode>, \u003Ccode class=\"key\">abort\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">ask\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>on_conflict: agent\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>board.remove_worktree\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Boolean\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">true\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>remove_worktree: false\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.model\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Text\u003C\u002Ftd>\n\u003Ctd>A model, as the harness names it\u003C\u002Ftd>\n\u003Ctd>empty: the account’s\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>model: opus\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.effort\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">low\u003C\u002Fcode>, \u003Ccode class=\"key\">medium\u003C\u002Fcode>, \u003Ccode class=\"key\">high\u003C\u002Fcode>, \u003Ccode class=\"key\">xhigh\u003C\u002Fcode>, \u003Ccode class=\"key\">max\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>empty: the account’s\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>effort: high\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">board.mode\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>One of a list\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">auto\u003C\u002Fcode>, \u003Ccode class=\"key\">default\u003C\u002Fcode>, \u003Ccode class=\"key\">plan\u003C\u002Fcode>, \u003Ccode class=\"key\">acceptEdits\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>empty: the account’s\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>mode: plan\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cul>\n\u003Cli>\u003Ccode class=\"key\">on_approve\u003C\u002Fcode>: “When I approve a ticket in “To review””: merge its branch into the target branch (\u003Ccode class=\"key\">merge\u003C\u002Fcode>), open a pull request (\u003Ccode class=\"key\">pr\u003C\u002Fcode>), push its branch (\u003Ccode class=\"key\">push\u003C\u002Fcode>), or keep it as it is (\u003Ccode class=\"key\">keep\u003C\u002Fcode>) (see \u003Ca href=\"\u002Fen\u002Fdocs\u002Fboard\u002F\">the Kanban\u003C\u002Fa>).\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">target_branch\u003C\u002Fcode>: “Target branch”, where tickets merge, and the base of their branch and pull request.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">agents_from_target\u003C\u002Fcode>: the former key of \u003Ccode class=\"key\">worktrees.base\u003C\u002Fcode>, still read when the file has no \u003Ccode class=\"key\">worktrees.base\u003C\u002Fcode> (\u003Ccode class=\"key\">true\u003C\u002Fcode> reads as \u003Ccode class=\"key\">target\u003C\u002Fcode>, \u003Ccode class=\"key\">false\u003C\u002Fcode> as \u003Ccode class=\"key\">head\u003C\u002Fcode>), with a warning. “Export to .escouade.yml” replaces it with \u003Ccode class=\"key\">worktrees.base\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">merge_strategy\u003C\u002Fcode>: the merge’s “Strategy”: merge commit, squash or rebase.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">draft_pr\u003C\u002Fcode>: “Draft PR”.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">test_command\u003C\u002Fcode>: “Test command”. A command: it waits for your approval.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">tests_before_approve\u003C\u002Fcode>: “Re-run the tests first” before a ticket is approved; without a test command, nothing runs again.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">on_conflict\u003C\u002Fcode>: “On conflict” at the merge: ask you (\u003Ccode class=\"key\">ask\u003C\u002Fcode>), let the agent resolve it (\u003Ccode class=\"key\">agent\u003C\u002Fcode>), or give up (\u003Ccode class=\"key\">abort\u003C\u002Fcode>).\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">remove_worktree\u003C\u002Fcode>: “Delete the worktree of a done or deleted ticket”.\u003C\u002Fli>\n\u003Cli>\u003Ccode class=\"key\">model\u003C\u002Fcode>, \u003Ccode class=\"key\">effort\u003C\u002Fcode>, \u003Ccode class=\"key\">mode\u003C\u002Fcode>: the model, effort and mode of the ticket agents (Settings › Kanban, group “Agents”). An empty value (\u003Ccode>model: ''\u003C\u002Fcode>) leaves the account’s. \u003Ccode class=\"key\">bypassPermissions\u003C\u002Fcode> is never in the file: a repository doesn’t lift the permissions of whoever opens it. Read, it is refused (“bypassPermissions is not shared: it is set on each machine”); set in the window, it stays a local setting, which the export doesn’t write.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"worktree-steps\">Worktree steps\u003C\u002Fh2>\n\u003Cp>Each item of \u003Ccode class=\"key\">worktrees.setup\u003C\u002Fcode> and \u003Ccode class=\"key\">worktrees.teardown\u003C\u002Fcode> is a step, in one of these two forms:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yaml\">setup:\n  # The command alone, as text: run by the default shell, at the root of the worktree.\n  - npm ci\n  # Or its fields:\n  - command: cargo fetch\n    shell: bash\n    cwd: src-tauri\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Field\u003C\u002Fth>\n\u003Cth>Required\u003C\u002Fth>\n\u003Cth>What it says\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">command\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>yes\u003C\u002Ftd>\n\u003Ctd>The command line, as the shell reads it.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">shell\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>The shell that runs it (see \u003Ca href=\"#shells\">shells\u003C\u002Fa>). Missing: the system’s default shell.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">cwd\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>A subfolder of the worktree, relative. Missing or \u003Ccode class=\"key\">.\u003C\u002Fcode>: the root of the worktree.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>A step without \u003Ccode class=\"key\">command\u003C\u002Fcode>, or whose \u003Ccode class=\"key\">cwd\u003C\u002Fcode> is a full path, is told and ignored; another field (\u003Ccode class=\"key\">env:\u003C\u002Fcode>, \u003Ccode class=\"key\">name:\u003C\u002Fcode>) is told as an unknown key. Steps run in the file’s order. A single step can be written without a list: \u003Ccode>setup: npm ci\u003C\u002Fcode> is a list of one step.\u003C\u002Fp>\n\u003Ch2 id=\"launch-commands\">Launch commands\u003C\u002Fh2>\n\u003Cp>Each item of \u003Ccode class=\"key\">launch\u003C\u002Fcode> is a named command:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yaml\">launch:\n  - name: web\n    command: npm run dev -- --port 5173\n    cwd: web\n  - name: docs\n    command: npm run docs\n    shell: pwsh\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Field\u003C\u002Fth>\n\u003Cth>Required\u003C\u002Fth>\n\u003Cth>What it says\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">name\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>The name shown for the command and its terminal. Missing: the command is its name.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">command\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>yes\u003C\u002Ftd>\n\u003Ctd>The command line.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">shell\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>The shell that runs it. Missing: the system’s default shell.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode class=\"key\">cwd\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>A subfolder of the project, relative. Missing: the root of the project.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>Unlike steps, a launch command has no short form: a text alone is told as an invalid value. A single command can be written without a list (\u003Ccode class=\"key\">launch:\u003C\u002Fcode> followed directly by \u003Ccode class=\"key\">name:\u003C\u002Fcode> and \u003Ccode class=\"key\">command:\u003C\u002Fcode>, indented): it is a list of one command.\u003C\u002Fp>\n\u003Ch2 id=\"shells\">Shells\u003C\u002Fh2>\n\u003Cp>\u003Ccode class=\"key\">shell\u003C\u002Fcode> takes the id of a shell Escouade finds on the machine:\u003C\u002Fp>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>System\u003C\u002Fth>\n\u003Cth>Ids\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Windows\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">pwsh\u003C\u002Fcode> (PowerShell 7), \u003Ccode class=\"key\">powershell\u003C\u002Fcode> (Windows PowerShell), \u003Ccode class=\"key\">bash\u003C\u002Fcode> (Git Bash), \u003Ccode class=\"key\">wsl\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>macOS and Linux\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">zsh\u003C\u002Fcode>, \u003Ccode class=\"key\">bash\u003C\u002Fcode>, \u003Ccode class=\"key\">fish\u003C\u002Fcode>, \u003Ccode class=\"key\">sh\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>A shell the reading machine lacks (\u003Ccode class=\"key\">pwsh\u003C\u002Fcode> on a Mac, \u003Ccode class=\"key\">zsh\u003C\u002Fcode> on Windows) is no error: the command runs in that system’s default shell. For a file shared across systems, leave \u003Ccode class=\"key\">shell\u003C\u002Fcode> out and write commands every shell understands.\u003C\u002Fp>\n\u003Ch2 id=\"the-json-schema-and-autocompletion\">The JSON schema and autocompletion\u003C\u002Fh2>\n\u003Cp>The format’s JSON schema is published at \u003Ccode>https:\u002F\u002Fescouade.dev\u002Fschemas\u002Fescouade.schema.json\u003C\u002Fcode>. It follows every version of Escouade: it describes each key, its type and its allowed values.\u003C\u002Fp>\n\u003Cp>For autocompletion, put at the top of the file the line the files Escouade writes already have:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yaml\"># yaml-language-server: $schema=https:\u002F\u002Fescouade.dev\u002Fschemas\u002Fescouade.schema.json\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Editors that read YAML schemas (VS Code with Red Hat’s YAML extension, JetBrains IDEs, Neovim with \u003Ccode class=\"key\">yaml-language-server\u003C\u002Fcode>) then complete the keys, show their description on hover, and flag an unknown key or a value outside the list as you type.\u003C\u002Fp>\n\u003Ch2 id=\"what-stays-out-of-the-file\">What stays out of the file\u003C\u002Fh2>\n\u003Cp>The file is committed and read by the whole team, and a public repository shows it to anyone. So it only holds what is true for everyone, never what belongs to one person, one machine, or is secret:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>the project’s name and color: each person’s display choice, in their own tab bar;\u003C\u002Fli>\n\u003Cli>the preferred account, the accounts reserved to a private project and “Shared accounts at the limit”: everyone has their own accounts;\u003C\u002Fli>\n\u003Cli>remote control: a personal choice, which makes one’s agents reachable from one’s own claude.ai;\u003C\u002Fli>\n\u003Cli>“In parallel” and autopilot: they spend your quota; someone who only reviews doesn’t want tickets to start by themselves on their machine;\u003C\u002Fli>\n\u003Cli>the \u003Ccode class=\"key\">bypassPermissions\u003C\u002Fcode> mode of ticket agents: a repository doesn’t lift the permissions of whoever opens it;\u003C\u002Fli>\n\u003Cli>the tickets’ key: each machine has its own Kanban and numbers its own tickets, and the key is fixed by the first ticket;\u003C\u002Fli>\n\u003Cli>the integrations (Jira, Trello, GitHub, Linear, ClickUp, GitLab, Azure Boards): they belong to your connected accounts;\u003C\u002Fli>\n\u003Cli>full paths: they only hold on one machine (hence a full \u003Ccode class=\"key\">dir\u003C\u002Fcode> or \u003Ccode class=\"key\">cwd\u003C\u002Fcode> is refused);\u003C\u002Fli>\n\u003Cli>tokens and passwords: no key takes one, and “Export to .escouade.yml” never writes one.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"when-the-project-opens\">When the project opens\u003C\u002Fh2>\n\u003Cp>When the folder you add has a \u003Ccode class=\"key\">.escouade.yml\u003C\u002Fcode>, the “New project” assistant offers “Settings from .escouade.yml” as a starting point, above “Recommended setup”, and picks it by itself. Once the project is made (or reopened), Escouade applies the file and says so: “settings read from .escouade.yml”.\u003C\u002Fp>\n\u003Cp>The file is read again as soon as it changes: after a \u003Ccode>git pull\u003C\u002Fcode>, a branch switch or an edit by hand. The settings that changed apply, and a message says so.\u003C\u002Fp>\n\u003Ch2 id=\"commands-wait-for-your-approval\">Commands wait for your approval\u003C\u002Fh2>\n\u003Cp>A cloned repository can come from anyone. The file’s commands (\u003Ccode class=\"key\">worktrees.setup\u003C\u002Fcode>, \u003Ccode class=\"key\">worktrees.teardown\u003C\u002Fcode>, \u003Ccode class=\"key\">launch\u003C\u002Fcode> and \u003Ccode class=\"key\">board.test_command\u003C\u002Fcode>) never run before you approve them, and reading the file runs none. Until you approve them, the project keeps its own, and the Kanban shows “The commands of .escouade.yml wait for your approval: they don’t run yet.”.\u003C\u002Fp>\n\u003Cp>“Read them” opens Settings › Projects, group “.escouade.yml”, which shows each command in full, with its shell and folder. “Trust these commands” applies them. If the file changes them later (a command, its shell or folder, a command added or removed), Escouade asks for your approval again; until then, the ones you approved stay in place. Commands the same as those the project already has need no approval.\u003C\u002Fp>\n\u003Cdiv class=\"callout warning\">\u003Cp class=\"callout-title\">Warning\u003C\u002Fp>\u003Cp>Read each command before you trust it: the setup runs in every new worktree, before its agent’s first message.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Ch2 id=\"marked-settings\">Marked settings\u003C\u002Fh2>\n\u003Cp>In Settings › Projects and Settings › Kanban, a setting the file defines says so under its label: “Defined by .escouade.yml”. Changing it and saving makes it a local setting of this machine, which goes before the file, even when the file is read again: “Local setting of this machine: it goes before .escouade.yml.”. Under the setting, “Write into .escouade.yml” puts your value into the file (to commit), and “Use the file’s value” hands it back to the file.\u003C\u002Fp>\n\u003Ch2 id=\"export-a-project-s-settings\">Export a project’s settings\u003C\u002Fh2>\n\u003Cp>To share a project that is already set up, Settings › Projects › “Export to .escouade.yml” writes the file at the root of the repository from the project’s saved settings: every key, in the order of the complete example (a target branch still empty is left out, and so is the \u003Ccode class=\"key\">bypassPermissions\u003C\u002Fcode> mode). An existing file keeps its comments, the order of its keys and the keys Escouade doesn’t know; a new file starts with the schema line and \u003Ccode>version: 1\u003C\u002Fcode>. The exported commands are the project’s own: they need no approval. Then commit the file.\u003C\u002Fp>\n",[8,12,15,18,22,25,28,31,34,37,40,43,45,47,49,51,53,55,58,61,64,67,70,73,76,79],{"id":9,"text":10,"depth":11},"what-it-is-for","What it is for",2,{"id":13,"text":14,"depth":11},"a-complete-example","A complete example",{"id":16,"text":17,"depth":11},"the-rules-of-the-format","The rules of the format",{"id":19,"text":20,"depth":21},"the-style-of-the-keys","The style of the keys",3,{"id":23,"text":24,"depth":21},"the-version-key","The version key",{"id":26,"text":27,"depth":21},"an-older-or-a-newer-version","An older or a newer version",{"id":29,"text":30,"depth":21},"a-missing-key","A missing key",{"id":32,"text":33,"depth":21},"an-unknown-key","An unknown key",{"id":35,"text":36,"depth":21},"an-invalid-value","An invalid value",{"id":38,"text":39,"depth":11},"the-types-of-values","The types of values",{"id":41,"text":42,"depth":11},"the-keys","The keys",{"id":44,"text":44,"depth":21},"agents",{"id":46,"text":46,"depth":21},"private",{"id":48,"text":48,"depth":21},"worktrees",{"id":50,"text":50,"depth":21},"launch",{"id":52,"text":52,"depth":21},"git",{"id":54,"text":54,"depth":21},"board",{"id":56,"text":57,"depth":11},"worktree-steps","Worktree steps",{"id":59,"text":60,"depth":11},"launch-commands","Launch commands",{"id":62,"text":63,"depth":11},"shells","Shells",{"id":65,"text":66,"depth":11},"the-json-schema-and-autocompletion","The JSON schema and autocompletion",{"id":68,"text":69,"depth":11},"what-stays-out-of-the-file","What stays out of the file",{"id":71,"text":72,"depth":11},"when-the-project-opens","When the project opens",{"id":74,"text":75,"depth":11},"commands-wait-for-your-approval","Commands wait for your approval",{"id":77,"text":78,"depth":11},"marked-settings","Marked settings",{"id":80,"text":81,"depth":11},"export-a-project-s-settings","Export a project’s settings",1793278987187]