Skip to content

Install the tool in one command, on a machine with no toolchain

Paste one line, get a verified binary for this machine, and run majordomus init — no git, no Rust, no Node, no Python, no root, and no way to install an archive whose digest does not match.

guaranteed Getting started and adoptionbasicoperatormaintainerwrites state

Situation

Someone wants to try the tool. They are not going to clone a repository, put bin/ on their PATH, and read a contributing guide first, and they should not have to: a supervisory tool that is hard to install is a tool that supervises nothing.

The other half of the situation is the one that makes curl | sh usually a bad idea. The script is unread, the archive is unverified, a failure halfway leaves a broken binary where a working one was, and an unsupported machine gets a confusing error instead of an answer.

Scenario

setup: bare
given:
  - 'a repository with no AI layer, and a machine with the tool already installed the way the installer installs it'
steps:
  - id: version
    run: ['version']
    note: 'the installed tool says which release it is; the installer refused to install an archive whose executable said anything else'
    expect:
      exit: 0
      stdout_contains: ['^majordomus [0-9]']
  - id: init
    run: ['init']
    note: 'the command the installer points at next, in the repository you want supervised'
    expect:
      exit: 0
      stdout_contains: ['next: majordomus update', 'next: majordomus doctor']
      files_exist: ['.ai/repo/policy.yaml', '.ai/manifest.yaml']
  - id: doctor
    run: ['doctor']
    note: 'the layer the installed tool created is a layer the installed tool accepts; the hook lines init printed are not in place yet, which is exactly what doctor is for'
    expect:
      exit: 12
      stdout_contains: ['^OK   layout      .ai/']
then:
  - 'nothing was installed into the project except .ai/ and the files the policy names'
  - 'the hook line init printed names the launcher, so an upgrade does not break it'
  - 'uninstalling removes the launchers and the prefix, and no repository state'

What you run

curl -fsSL https://majordomus.dev/install.sh | sh
majordomus init

or, in one line:

curl -fsSL https://majordomus.dev/install.sh | sh -s -- --init

The installer resolves this machine from uname and, on Linux, from the C library it finds; reads the release metadata this repository publishes rather than GitHub's API; verifies the artifact's SHA-256 and size before unpacking anything; refuses an archive that carries an absolute path, a traversal, a link or an entry outside its own directory; runs the unpacked tool once to prove it reports the version that was resolved; and only then replaces the launcher, by a rename.

--dry-run prints every one of those decisions and changes nothing. --version v0.2.0 pins a release, which is the form to use in CI.

Outcome

A working majordomus on the PATH — or the exact line to add to make it so — and a repository one command away from being supervised. Nothing was built, nothing was elevated, and if anything had gone wrong the installation that was there before would still be the installation that is there now.

The platforms this works on are not written down anywhere a person maintains: they are share/distribution.yaml, and the installer's table, the release build, the documentation and this page all read it (docs/DISTRIBUTION.md).

The scenario

Executed against the real tool, in a repository prepared by bare, every time this site is generated. What follows is not a description of what should happen; it is what happened.

given

  • a repository with no AI layer, and a machine with the tool already installed the way the installer installs it

when

  1. 1majordomus version
  2. 2majordomus init
  3. 3majordomus doctor

then

  • nothing was installed into the project except .ai/ and the files the policy names
  • the hook line init printed names the launcher, so an upgrade does not break it
  • uninstalling removes the launchers and the prefix, and no repository state

What the tool did

Evidence of the run this page was generated from: pass, 3 step(s). Output is normalised: the repository's path, timestamps, ids and durations are placeholders; nothing else is edited.

Tested by test/cases/94_use_cases.sh, which runs every scenario and refuses a step whose recorded output is not what it produced.

  1. the installed tool says which release it is; the installer refused to install an archive whose executable said anything else

    majordomus 1.0.0-alpha.8
    • exit 0
    • stdout_contains /^majordomus [0-9]/
  2. the command the installer points at next, in the repository you want supervised

    created
      .ai/README.md
      .ai/manifest.yaml
      .ai/repo/README.md
      .ai/repo/policy.yaml
      .ai/repo/scope.yaml
      .ai/repo/profiles/
      .ai/repo/prompts/
      .ai/repo/profiles/README.md
      .ai/repo/prompts/README.md
      .ai/repo/rules/README.md
      .ai/repo/rules/project/README.md
      .ai/repo/rules/vendor/majordomus/
      .ai/repo/knowledge/
      .ai/repo/knowledge/curated/README.md
      .ai/repo/knowledge/candidates/README.md
      .ai/repo/workflows/
      .ai/repo/skills/
      .ai/repo/adrs/
      .ai/repo/use-cases/
      .ai/repo/applications/
      .ai/repo/why/
      .ai/repo/features/
      .ai/repo/sessions/README.md
      .ai/repo/deployments/README.md
      .ai/repo/project/README.md
      .ai/repo/mesh/
      .gitignore:.ai/local/
      .gitignore:.ai/repo/**/.tmp.*
    scope: no stack recognised at the root (looked for mix.exs, Cargo.toml); seeded only the entries every repository shares; add your own to .ai/repo/scope.yaml
    local state: .ai/local/state/ (ignored by git; this checkout's own)
    next: majordomus update      # generate the provider instruction files named in the policy
    next: majordomus doctor      # verify nothing is declared that is not wired
    hooks are not installed by init; add these two lines yourself, doctor verifies them:
      pre-commit: majordomus doctor || exit $?
      pre-push:   majordomus finish --check || exit $?
    • exit 0
    • stdout_contains /next: majordomus update/
    • stdout_contains /next: majordomus doctor/
    • file_exists .ai/repo/policy.yaml
    • file_exists .ai/manifest.yaml
  3. the layer the installed tool created is a layer the installed tool accepts; the hook lines init printed are not in place yet, which is exactly what doctor is for

    OK   knowledge   graph — buildable here: 0 node(s), 0 edge(s), compiled into a temporary file and removed; no stored index to go stale
    OK   knowledge   records — 0 record(s) valid against knowledge/v1; every reference resolves  [reproduce: majordomus knowledge check]
    OK   knowledge   candidates — 0 await review, cap 40
    OK   layout      .ai/manifest.yaml — schema ai-repository/v1
    OK   layout      .ai/repo/scope.yaml — version 1; 14 in pathspec(s); every key is one the schema declares
    OK   layout      .ai/local/ — ignored, and nothing under it is tracked
    OK   layout      .ai/ — every section the manifest names exists; the layer is readable without the tool
    OK   layout      .ai/repo/prompts — present
    OK   layout      .ai/local/state/handovers — present, 0 record(s)
    OK   layout      .ai/local/state/checkpoints — present, 0 record(s)
    OK   records     ledger.jsonl — every line is a well-formed event
    OK   policy      39 key(s) — every policy value the code reads is declared, with no reader-side default
    OK   bootstrap   3 projection(s) — each points at .ai/README.md, carries no rule of its own and names only rules in force
    OK   catalogue   0 use case(s), 0 application(s) — every command, doctrine, claim, responsibility, category, setup and cross-reference resolves, both directions
    OK   context     .ai/ — 20 context document(s) carry the contract; ids unique, references resolve, no final document superseded, no cycle  [reproduce: majordomus context validate]
    OK   policy      .ai/repo/policy.yaml — parsed, version 1
    OK   profiles    4 files — parsed; default 'implementation' exists
    INFO adr         .ai/repo/adrs/ — no decisions; nothing to validate
    OK   records     decisions.md — every entry is attributable
    INFO project     .ai/repo/project — no canonical project model here; nothing to validate
    OK   command     surface — 30 public command(s), reconciled against the dispatch table  [reproduce: majordomus doctor]
    OK   doctrine    50 of 61 rule(s) carry a validator — validator, dispatch, propagation, test and CI resolve for every one of the 50; the remaining 11 declare no validator and this check does not examine them
    FAIL wiring      doctor-on-commit — hook .git/hooks/pre-commit does not exist  [reproduce: ls -l .git/hooks/pre-commit]
    FAIL wiring      finish-on-push — hook .git/hooks/pre-push does not exist  [reproduce: ls -l .git/hooks/pre-push]
    OK   command     coverage — every public command is exercised and refuted  [reproduce: bash test/run.sh 31_command_coverage]
    OK   resolver    handovers — no record for this worktree and branch (absence, not a stale match)  [reproduce: majordomus handover --resolve]
    OK   lifecycle   ledger — no ledger yet; nothing has happened here to be silent about
    OK   knowledge   wiring — the close path and the compaction adapter call the deriver
    OK   knowledge   deriver — no ledger yet; no episode has closed here
    INFO project     .ai/repo/project — no canonical project model here; nothing to validate
    FAIL projection  AGENTS.md — missing (run: majordomus update)  [reproduce: majordomus update]
    FAIL projection  CLAUDE.md — missing (run: majordomus update)  [reproduce: majordomus update]
    FAIL projection  GEMINI.md — missing (run: majordomus update)  [reproduce: majordomus update]
    OK   context     builder — 21 lines, budget 300  [reproduce: majordomus context]
    OK   capture     share/schemas/majordomus/capture/capture.v1 — 2 file(s) describe majordomus.capture/v1 at the path the identifier derives: the record as JSON Schema, the document as protobuf
    OK   capture     .ai/local/prompts — ignored and untracked
    OK   capture     .ai/local/prompts — no records yet; the archive is empty
    OK   capture     .ai/local/prompts — every prompt is present as all three: the record, the Markdown and the YAML
    OK   prompts     .ai/local/prompts — the archive and every record in it are readable by their owner only
    OK   prompts     .ai/local/prompts — no records yet; the archive is empty
    OK   prompt      4 asset(s) — front matter valid, every token known
    OK   records     open-questions.md — every entry parses
    OK   retention   ledger — 0 lines, cap 5000
    OK   retention   handovers — 0 files, cap 200
    OK   retention   checkpoints — 0 files, cap 500
    OK   retention   sessions — 0 records, cap 500
    INFO project     .ai/repo/project — no canonical project model here; nothing to validate
    OK   rules       .ai/repo/rules/vendor/majordomus — every file matches the manifest (1 (1.0.0-alpha.8))
    OK   rules       61 rule(s) — resolve in one deterministic order; vendored baseline plus project rules, no override — 51 carry a validator, 10 are normative text this tool does not check
    OK   rules       blocking — all 44 blocking rule(s) carry a validator
    OK   schema      rules — 61 rule(s) resolve in one order: the vendored baseline in manifest order, then the project's, as a dependency graph
    OK   schema      share/kinds.yaml — 37 kind(s); every one that carries metadata declares a schema
    OK   schema      share/schemas — 54 schema(s), each valid JSON and each applied — by a kind, through an allow-list the tool reads, by a validator that names it, or as a generated document's contract (15)
    WARN session     .ai/repo/sessions/ — 1 record(s) exist here and are committed nowhere, so they reach no surface: README.md  [reproduce: git add .ai/repo/sessions && majordomus derive]
    OK   records     0 record(s) — every changed_files names work, not generated or local state
    OK   session     .ai/local/session-contexts — ignored and untracked
    OK   session     .ai/local/session-contexts — no working contexts yet; the store is empty
    INFO skill       .ai/repo/skills/ — no skills; nothing to validate
    OK   skill       reachable — no personal command or skill shares a name with a projected skill  [reproduce: majordomus run editors.status]
    INFO use-case    30 advisory gap(s) — not covered by an active use case, and the policy does not require it: command:init command:update command:doctor command:watch command:start command:context command:checkpoint command:handover command:check command:finish command:history command:decision command:question command:prompt command:evidence command:skills command:capture command:search command:doctrine command:plan command:version command:session command:knowledge command:adr command:usecase command:rules command:migrate command:recover command:bench command:archive  [reproduce: majordomus usecase coverage]
    OK   use-case    0 of 30 target(s) covered — every public command the policy requires is named and run by an active use case (policy use_cases.coverage)
    INFO env         - — bash <version>, git <version>, jq <version>, shellcheck present
    WARN clone       unpushed — commits on no remote: main(2) — work on one disk is invisible to every other session and cannot be integrated  [reproduce: git push -u origin <branch>]
    OK   clone       uncommitted — no linked worktree, so no uncommitted work can sit in one
    INFO clone       trunk — no remote-tracking branch, so this checkout's distance from the remote trunk cannot be measured
    INFO clone       release — no remote-tracking branch, so whether the trunk's landed work is released cannot be measured
    ·    reasoning   <decided by the advisors and the executable of the recording machine>
    ·    layout      - — <judged when the recording machine has built the executable>
    ·    budget      doctor — <timed against the policy budget>
    doctor: 5 failure(s)
    • exit 12
    • stdout_contains /^OK layout .ai//

Why the tool knows this

The chain from this page to the code: the use case names commands, rules and claims; each rule is dispatched from the registry and each claim names the test that proves it; the scenario above executed the commands. Nothing in this chain is prose about intent.

Over MCP the same layer is reached through majordomus_distribution, majordomus_releases, majordomus_build, majordomus_artifact (the MCP surface).

The rules that make it hold

Guarantees exercised

Related use cases

Computed from what they share: claims, rules, commands, category, applications. Nobody maintains this list.

Searches the titles and descriptions of every page this site publishes.