phantom
AGENTS.md214 starsChanged 9 days agoMITView on GitHub
- Commits and pushes
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
The file
We split this AGENTS.md into the rules it gives an agent
10 rules. About 0 are common, 3 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 27
Run the CLI: cargo run --locked -- --help.
- Very specific: line 31
Before shipping, run cargo fmt --all, cargo clippy --locked --all-targets -- -D warnings, and cargo test --locked.
- Distinctive: line 37
Use PascalCase for types, camelCase for functions and variables, and snake_case for modules.
- Very specific: line 38
Keep CLI flags and config keys consistent with .rabi.toml and rabi config.
- Distinctive: line 39
All files, issues, and pull requests must be written in English.
- Very specific: line 48
Use conventional commits as in history: feat:, fix:, chore:, docs:, refactor:.
- Very specific: line 49
Do not bump Cargo.toml or Cargo.lock in a feature pull request.
- Distinctive: line 51
Follow Review process, REVIEW.md, and risk-tiers.md for review, risk assessment, security review, and merge approval.
- Very specific: line 52
Ensure cargo fmt, cargo clippy --locked, and cargo test --locked pass.
- Very specific: line 56
Never commit tokens or GitHub credentials.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Repository Guidelines
Project Structure & Module Organization
- rabi is a Rust CLI that manages local Git workspaces so many coding agents and humans can work independently in the same repository. The crate lives at the repository root (
Cargo.toml,src/,tests/). - Development happens on
main. Open pull requests againstmain. - Modules follow the old package boundaries:
cli,worktree,git,config,preferences,projects,github,help. - Command help text and bash/zsh/fish completions are generated from
help-data.json; do not maintain separate command or flag lists. Selector completion queriescommand rabi list --namesat completion time, honors -R/--repo, and silently ignores query failures. Quote candidates for shell input before insertion (Bash uses printf %q; zsh/fish use native completion quoting). - Keep README.md and README.ja.md aligned in sections, commands, flags, and examples. Document breaking CLI changes in CHANGELOG.md under Unreleased; verify CLI guidance against the implementation and tests. Keep the READMEs concise; detailed English reference material lives in
docs/(commands, JSON, exit codes, installation, configuration, hooks, safety, sync, and shell integration). Documentation consistency checks live in tests/docs.rs. completions bash|zsh|fishandshell-init bash|zsh|fishoutput raw scripts, ignore RABI_OUTPUT, and refuse explicit JSON output with usage exit 2. Missing or unknown shells exit 2. shell-init defines only the rabi function forrabi cd [SEL] [-R REF](alsorabi -R REF cd [SEL]): resolvecommand rabi pathas text, change directory only on success, preserve trailing path newlines by removing exactly one output delimiter, and preserve lookup errors/status. Other argv pass through unchanged. Load completions separately; zsh requires compinit. No sessions or panes. Shell smoke tests live in tests/cli.rs and explicitly skip unavailable shells; CI installs zsh and fish.- Project hooks live in
.rabi.toml([hooks] setupandpre-remove) in the invoking checkout, or the selected primary checkout with-R/--repo.setup/remove --source-checkoutoverrides that source with a checkout in the same repository.RABI_REPO_PATHalways points to the primary checkout. Hooks and exec also receiveRABI=1,RABI_WORKSPACE,RABI_WORKSPACE_ID(empty when unrecorded), andRABI_WORKSPACE_PATH. Hooks run only after that git common directory is trusted (rabi trust addorRABI_TRUST_ALL=1). rabi does not ask with nonemptyCI, JSON output,--no-input,RABI_NO_INPUTother than empty or0, or when stdin or stderr is not a terminal.create --no-setupskips copying and hooks;setup/remove/gc --no-hooksskips hooks. Unknown hook fields fail with exit 1 through normal validation.rabi gcskips an untrusted repository that has pre-remove hooks and does not ask. Trust is the common-dir path, so a re-clone at the same path stays trusted untilrabi trust remove. rabi run [--provider codex|cursor|claude] [--skill VALUE] [--fresh] [--timeout DURATION] [TASK | -]starts one parent per current workspace, resuming it by default.rabi run [options] SEL -- [TASK | -]selects a workspace without cd;-R/--reporequires SEL. Without a separator a single positional remains TASK; option values never act as separators. The selected repository must be trusted before status inspection, without prompting. Primary and orphaned checkouts are refused. The parent manages progress and its own subagents; rabi only launches, stops, locks and records sessions. Skill values are injected verbatim without resolution. First/fresh runs require --skill. Missing/broken sessions fail with a --fresh hint. Provider defaults to codex on first/fresh runs; resume uses the record provider, permits the same explicit flag, and rejects a different flag with exit 2 before state changes.list/showexpose a read-onlyrunsummary including provider (null if absent or invalid, warning on invalid data); stale running records display stopped unless their lock pid or process group is alive.- Codex parents use auto mode (
--approve-for-me) without --sandbox, including resume; Codex, Cursor and Claude receive--add-dir <memory dir>when handoff is enabled (default for recorded workspaces), unless--no-handoff; model/effort are internal constants. Timeout defaults to 2h per launch; interruption/timeout kills the whole process group, reaps the parent and releases the per-workspace pid lock. rabi reports parent exit status without deciding task completion. - Cursor parents resolve
cursor-agent, thenagent, and use-p --output-format stream-json --workspace WS --trust --sandbox enabled --auto-review --model grok-4.7-high, plus--resume ID. Prompt is stdin. Resume requires HOME-based Cursor metadata withhasConversation:trueunder the MD5 of the same absolute workspace path. Existing.cursor/sandbox.jsonis preserved; absent files get the GitHub allowlist and a common-directoryinfo/excludeentry. Completed insecure-policy tool requests produce an audit count/message. Cursor stops with INT -> TERM -> KILL and best-effort Linux descendant cleanup; Codex stop behavior is unchanged. Cursor answers come from the last result event, atomically written after reap. - Claude parents resolve only PATH
claude, use-p --output-format stream-json --verbose --session-id UUID --permission-mode auto --permission-prompts none --model opus --effort high, replacing--session-id UUIDwith--resume IDon resume. Prompt is stdin; no workspace settings are written. New launches record requestedSessionId separately from the observed session id; init must report permissionMode auto before the session is resumable. Mismatched ids or non-auto/missing init permissionMode stop with an error. Probe checks CLAUDE_CONFIG_DIR (nonempty) or HOME/.claude projects/*/ID.jsonl, returning Present or Unknown. Claude uses INT -> 2s -> TERM -> 1s -> KILL with the existing Linux descendant cleanup. Result finalization follows Cursor; timeout/interrupt win over exit-0 error results, including null result strings. - Handoff memory lives under
paths::state_dir()/repositories/<sha256(canonical common-dir bytes)>/memory/<workspace-id>/, bound to workspace id and createdAt.rabi handoff show/pathare read-only;addappends under a dedicated file lock. First/fresh runs inject bounded memory, resume injects foreign entries with createdAt after the last delivered handoff snapshotAt (startedAt fallback for old records), or the full first/fresh snapshot when none exists in the run. Capture reads the snapshot under the memory lock; delivery requires an observed launch session id or exit code 0;--no-handoffskips capture, injection, grants and run env vars. Parents receiveRABI_BIN,RABI_RUN_ID,RABI_RUN_LAUNCH,RABI_RUN_PROVIDERand workspace variablesRABI,RABI_REPO_PATH,RABI_WORKSPACE,RABI_WORKSPACE_ID,RABI_WORKSPACE_PATHwhen memory is enabled;RABI_BINis the launcher’s absolute executable path (canonicalized when possible, falling back torabiif lookup fails), also used with shell quoting where needed in injected commands. Memory is retained by remove/gc/forget. Existing runs/workspaces remain in the git common directory. trust addlists hooks and grants common-dir execution trust; JSON data stays{path,trustedAt}.rabi skill listindependently lists direct child SKILL.md directories in checkout .agents/.codex/.claude skills, then user equivalents (respect CODEX_HOME); sort within each source, retain duplicates. Run never uses discovery.- Outer commands are
repo add/list/show/forget,config get/set/unset/list(--sourcesfor reads),trust add/remove/list,help [COMMAND...] [--json], and--version/-v.trust addshows hooks and records trust without prompting. Global-R/--repo REFselects a repository; exec requires it before SEL, followed by the required--before the child command. Unknown commands and flags return ordinary usage errors (exit 2); do not add compatibility shims for retired interfaces before v7 stable. - User config keys are
workspace-root,clone-root,discover-ghq,sync.strategy(auto|rebase|merge, default auto), andsync.rewrite-published(boolean, default false). Sync policy lives under [sync] in user config.toml, never in repository .rabi.toml. Invalid policy values exit 2. Unknown config keys are rejected without rewriting. Workspace names preserve hierarchical slashes. Clone-root keeps ghq.root -> GHQ_ROOT -> ~/ghq defaults.help --jsonincludes help-data.json and its schemaVersion/exitCodes/errorCodes contract;--version --jsonkeeps the application version in data.version. - Principles: single responsibility, a centralized git executor, and
Resultfor every fallible path.
Build, Test, and Development Commands
- Prerequisite: Rust 1.99.1, pinned in
rust-toolchain.toml. The same version is pinned in.github/workflows/ci.ymlandrelease-compile.yml(toolchainandRUSTUP_TOOLCHAIN). Dependabot opens Cargo and GitHub Actions updates from.github/dependabot.yml. It does not bumprust-toolchain.tomlor those workflow strings. To move the pin, change every one of those places together, then run fmt, clippy, and tests on the new compiler. Changerust-versioninCargo.tomlonly when the MSRV changes. It is 1.89 because uuid 1.28 declaresrust-version = "1.89.0". mise.tomldefines optional task aliases.mise run fmt,mise run clippy, andmise run testrun the same checks as CI. It does not install Rust or other tools.- The installed command is
rabi(rabi create,rabi --help). The Cargo package name israbi. There is noptmorphantombinary. - Run the CLI:
cargo run --locked -- --help. - Format:
cargo fmt --all. - Lint:
cargo clippy --locked --all-targets -- -D warnings. - Tests:
cargo test --locked. - Before shipping, run
cargo fmt --all,cargo clippy --locked --all-targets -- -D warnings, andcargo test --locked.
Coding Style & Naming Conventions
- Rust 2021.
rustfmtis the formatter. - Non-test code must not use
unwrap(),expect(), orpanic!. Propagate errors withResultandthiserror. The crate deniesclippy::unwrap_used,clippy::expect_used, andclippy::panicoutside tests. - Use PascalCase for types, camelCase for functions and variables, and snake_case for modules.
- Keep CLI flags and config keys consistent with
.rabi.tomlandrabi config. - All files, issues, and pull requests must be written in English. Follow existing patterns.
Testing Guidelines
- Unit tests sit next to the module in
src/. CLI coverage lives intests/. - Cover success and error paths for workspace creation, git flows, and the project registry. Use temporary directories and the git executor.
Commit & Pull Request Guidelines
- Use conventional commits as in history:
feat:,fix:,chore:,docs:,refactor:. - Do not bump
Cargo.tomlorCargo.lockin a feature pull request. Change the version by hand in a dedicated pull request againstmain. See Releases. - PRs should include a summary, verification steps, and CLI output for UX-facing changes.
- Follow Review process, REVIEW.md, and risk-tiers.md for review, risk assessment, security review, and merge approval.
- Ensure
cargo fmt,cargo clippy --locked, andcargo test --lockedpass. Note known gaps in the PR body.
Security & Configuration Tips
- Never commit tokens or GitHub credentials.
create --prandcreate --issueuse theghCLI (GH_TOKEN/GH_HOST). - New workspaces go under
$XDG_DATA_HOME/rabi/workspaces/<checkout>-<hash>/(~/.local/share/rabi/workspaces/...whenXDG_DATA_HOMEis unset, empty, or relative) unless overridden with theworkspace-rootconfig key, which accepts absolute paths, ~/, or paths relative to the repository root.removeandgcmay also remove a workspace recorded inrabi/workspaces/<id>.jsonwhen it sits outside that directory. An unrecorded workspace outside the configured directory is left alone. Avoid leaking local paths in logs. - Config lives at
$XDG_CONFIG_HOME/rabi/config.toml(default~/.config/rabi/config.toml); state lives under$XDG_STATE_HOME/rabi/(default~/.local/state/rabi/), withrepos/andtrust.toml. Unset, empty or relative XDG values use the HOME defaults. Only current rabi paths and individual record formats are read or written. Project markers use.rabi-common-dir; clone staging uses.rabi-clone-. Do not move or delete old directories. - Workspace metadata uses
<git-common-dir>/rabi/workspaces/ws_<uuid v4>.json(schema 2); project registrations use$XDG_STATE_HOME/rabi/repos/proj_<uuid>.json. Use the shared atomic writer for state files; workspace metadata has no internal file locks (handoff appends use a dedicated lock). Different-record additions preserve both records; same-record concurrent updates use the last write. Project readers deduplicate roots by oldestcreatedAt. - Internal run schema 2 uses
<git-common-dir>/rabi/runs/run_<uuid>/state.jsonplus numberedlaunches/<n>/prompt/events/stderr/answer files. Use the shared atomic writer for state and current pointers underruns/current/<sha256-of-absolute-checkout-path>;.lockcontains the launcher pid and, once spawned, the parent process group id. Takeover requires both to be gone. Resume validates the checkout path, independently of branch-derived names. Incomplete numbered launch directories are skipped. Old schema-1 runs and user workflow files remain untouched. Workspace schema 2 stays unchanged. - Workspace records store purpose, links, base, and creation details.
show,path,list, andexecread metadata without rewriting records.gc --older-thanusescreatedAt;sync --allselects every workspace in the selected repository. - Selectors for show/path/set/setup/exec/run/sync/remove/forget are name,
., pr:N, issue:N, a PR/issue URL, or an absolute path / path starting with./or../. Linked selectors only find recorded links; multiple matches use ambiguous (2), missing matches use not_found (3). A dot with a different -R is usage (2). show/path/set/setup/exec default to dot; sync defaults to only the current workspace (primary acts as --main).showincludes unmanaged checkouts.pathtext is only the absolute path; JSON is data.path. set --unset FIELDaccepts one of purpose/base/pr/issue per occurrence; repeat the flag to clear multiple fields. Validate and normalize --base, and apply edits atomically.listsupports --kind workspace|primary, --names, --paths and --all-repos. Workspace objects include repo/current/managed/upstream/updatedAt; unknown values are null. Usage help goes to stderr.createunifies new branches,--branch,--pr,--issue, and--detach.--base/--branch/--prare exclusive.--reusereturns a matching workspace without copying files or running hooks; mismatches exit 4 exists. New-branch names matching local or observed remote branches exit 4 exists_remote without fetching. JSON includes workspace/source/setup/copy/metadata; source.kind is new/branch/pr/issue/detach.adopt PATHrecords an existing linked checkout without setup (createdAt/createdFrom null);forget SEL...only drops records, preserving files, branches and Git registration, and returns items:[{workspace,ok}].setup [SEL] [--copy-file PAT] [--no-hooks] [--source-checkout PATH]copies ignored matches from the primary checkout, then runs trusted setup hooks from --source-checkout when supplied, otherwise the invoking checkout. Primary targets exit 4 primary; untrusted hooks exit 4 before any copying or record update; hook/copy failures exit 1. Create shares preparation, takes --no-setup (conflicting with --copy-file), and returns exit 6 with a shell-quotedcd '/absolute/source/checkout' && rabi setup 'SELECTOR'retry hint (a uniquely resolving name or PR/issue selector), preserving the original hook configuration and all copy patterns. Retry hints require bash or zsh and use ANSI-C quoting for control characters or non-UTF-8 bytes. When no selector resolves uniquely, the hint uses(cd WORKSPACE && rabi setup . --source-checkout SOURCE); the source must belong to the same repository. Hooks must tolerate reruns. Records store setup {state, at, error}: pending/running/ok/failed/skipped; records without setup information, including adopted records, report unknown, unrecorded ones null. A running record with a dead pid on the same host displays interrupted without writing or blocking; no locks or in-use detection. Shared workspace objects include setup and human list shows non-ok states.remove SEL...requires explicit selectors; preflight all targets before hooks or removal. Dirty means modified/staged tracked files (including submodule changes) and non-ignored untracked files, matching list/show regardless of Git status display settings, and requires --discard-changes; ignored files are deleted with the workspace without warning or permission. Even when clean, workspaces with populated submodules or retained submodule data are refused during remove preflight (exit 4 dirty, including --dry-run) and skipped by gc (plan and --apply) with a rabi remove NAME --discard-changes hint; review the submodule contents, including unpushed commits, before using that permission. Known limitation: nested Git repositories inside ignored directories (for example, ignored vendor/x/.git) are also deleted; unpreserved detached commits require --delete-unpreserved-branch. Primary is always refused. Branches are deleted only if integrated into the recorded base (repository default fallback when absent), exactly matching their own upstream, or covered by verified merged PR evidence; otherwise keep with branch_kept_unpreserved and branchKeptReason. Local preservation requires an independent ref in the common Git directory after resolving symbolic refs; the retiring ref, detached HEAD, and bare object IDs are insufficient. Squash/rebase preservation requires exact tree-entry transitions (paths, modes, full before/after object IDs) in non-merge commits on the base first-parent history; textual patch IDs are insufficient. A squash matches one complete transition; rebased commits must match distinct base commits in ancestor-to-tip order without reusing evidence. Checks must remain read-only and retain uncertain history. --keep-branch always keeps branches. --dry-run returns a read-only plan. data.items contains workspace/removed/branchDeleted/branchKeptReason/detail/alreadyGone/error; unknown selectors with neither metadata nor a matching Git worktree exit 3 not_found (also with --dry-run), aborting all hooks/removal and listing every unknown selector in text. alreadyGone requires evidence: a missing directory with metadata and/or an eligible Git registration succeeds, cleaning only stale records/registrations without hooks or branch deletion. A record with remaining files but no Git registration also succeeds with alreadyGone while retaining the files, record and branch. A branch alone is insufficient. If branch deletion fails after checkout removal, remove keeps the branch with warning branch_kept_delete_failed, branchKeptReason: delete_failed, and the Git error in the item detail. This does not fail the item or stop later targets; branch-only failures exit 0 and have no retry command. Decide on any later branch cleanup with Git. A failure after persistent removal exits 6 and retains every item result. Completed removals also remove their records, so repeating the original command may exit 3. Fix the cause, then run error.details.retryCommand, also shown as Retry with in text. The retry is one invocation: cd<primary>&& rabi -R<primary>remove [flags] --<unfinished paths>. It selects only unfinished checkout or record work, preserves permission flags and output mode, and protects selectors with --. Run hints in bash or zsh; paths are shell-quoted and control characters use ANSI-C quoting. Metadata cleanup is retried only for recorded targets, using the absolute path spelling saved in the record before removal. Location selectors are fixed before removal. A linked checkout supplying pre-remove hooks is removed last; retries preserve its configuration with --source-checkout PATH, which must belong to the selected repository. Once that source is removed, only record cleanup remains and retries disable hooks. Retries add --no-hooks when the original command disabled hooks or its source had no pre-remove hooks, preserving hook non-execution even if primary defines hooks. With -R PRIMARY, dot also resolves a recorded checkout whose Git registration disappeared.- After local preservation checks fail, remove and gc can use GitHub evidence for a named branch. A recorded PR (
set --prorcreate --pr) must beMERGED, and itsheadRefOidmust equal the local tip or contain it as an ancestor. Ancestry is checked only when that PR commit already exists locally; nothing is fetched. Partial clones (extensions.partialCloneconfigured or any remote withpromisor=true) require an exact tip match and skip PR object and ancestry probes on every Git version. A recorded URL is passed toghand must match the checkout repository resolved bygh repo view; number-only links use that repository. Unlinked branches use onegh pr list --head BRANCH --state merged --limit 2query and require exactly one result with the same head name and exact tip ID; ancestry is never used. Repository identity is resolved once per command. Missing or unauthenticatedgh, failed queries, invalid JSON, ambiguous identities, and timeouts keep the existing local verdict. Each gh call has a 10-second deadline (shorten it with positiveRABI_GH_TIMEOUT_MS); authentication prompts are disabled and non-interactive stdin is/dev/null. Remote responses, including failures, are cached for the command, while local tips and ancestry are rechecked after hooks. JSON items addpreservationReason:merged_prfor GitHub proof,localfor remove's local proof, otherwise null or absent. Text details identify merged-PR proof. These rules also apply to plans. gcdefaults to --merged/--closed-pr/--orphaned; --older-than only narrows by createdAt, excluding null. --apply is required for mutations. Dirty/unpreserved candidates skip with targeted remove hints, with separate permissions. Plan and --apply use the same dirty rule as remove/list/show: ignored files do not count as dirty and are deleted with the workspace, including nested Git repositories inside ignored directories. Hint selectors must resolve uniquely to the target; use cd/dot only for an existing directory, and a linked selector or explicit path-scoped Git removal for a missing directory. Orphan cleanup leaves branches and files. data is {plan,items:[{workspace,reasons,action,detail}]}. No ownership, internal locks, or in-use detection.sync [SEL... | --all | --main] [--auto | --rebase | --merge] [--rewrite-published] [--keep-conflicts] [--dry-run]: no args only current; --main ff-only advances primary only while on default branch, otherwise not-default-branch. SEL may combine with --main, never --all. --all selects all workspaces, primary only with --main. Fetch involved remotes once, including dry-run; never push, change upstreams, or run hooks. Dry-run changes no checkout/index/local branch/record and reports plan:true; unknown future commit IDs are null. Auto rebases unpublished work and merges published work. Publication evidence includes observed remote-tracking refs, configured fetch destinations and the workspace upstream, even independent local branch refs or destinations of remotes not fetched by this sync. Only the current branch itself is excluded. Flags override sync.strategy. Published rebase refuses with exit 4 published unless flag/config rewrite permission allows it; permission never chooses strategy. Items expose strategySource, rewriteAllowed, rewriteSource, rewrotePublished; actual rewrites emit published_rewritten (updating the existing remote branch may require a force push). data is {plan,items:[{workspace,status,strategy,strategySource,rewriteAllowed,rewriteSource,rewrotePublished,before,after,conflicts,detail,code}],main:item|null}. Conflicts restore (5); --keep-conflicts requires exactly one workspace integration target. Persistent integration changes followed by failure/conflict/refusal exit 6. No ownership, internal locks, or in-use detection.- Both execution and dry runs use ordinary
git fetchin the invoking repository. Before any fetch or integration, sync checks every configured fetch refspec of every involved remote and refuses with exit 4refusedif a positive refspec has a destination outsiderefs/remotes/(including explicitrefs/tags/destinations and mirror mappings). Negative exclusions do not relax this conservative check; a missing or empty destination only writesFETCH_HEADand is allowed. Use a tracking destination underrefs/remotes/for custom namespaces. Sync also refuses any existing symbolic ref visible togit for-each-refunderrefs/remotes/orrefs/tags/that points outsiderefs/remotes/; repair or remove the alias before retrying. Dangling symbolic refs are omitted by Git's enumeration and are not detected: this is a known limit shared with plaingit fetch. Git retains its configured pruning, automatic tag following, negative exclusions andfollowRemoteHEADbehavior; automatic tag following is not an explicit fetch refspec. Combined dry runs evaluate local bases against tips planned for primary and earlier workspaces, in selection order. Planned branch tips are keyed by full refs: the short branch namerefs/heads/amaps torefs/heads/refs/heads/a, independently of branchaatrefs/heads/a. When an earlier planned tip is unknown, dependent items reportupdated,after:null,strategy:nulland a dependency explanation indetail, without deciding against the old base. - Exec requires -- before the child command; missing delimiters return usage (2). Reuse
validate_worktree_namefor name parsing and the shared selector resolver for workspace selection.
Releases
- The version lives in
Cargo.tomland therabientry inCargo.lock. Change it by hand in a dedicated pull request againstmain. Do not bump the version in other pull requests. - Title that pull request
chore(version): vX.Y.Z(for example,chore(version): v7.0.0; prereleases are also fine). Review and approve its exact HEAD SHA, then squash-merge it intomainunder risk-tiers.md. Merging does not create a tag. - Create a draft at the full merge commit SHA:
gh release create v<version> --draft --target <merge-commit-SHA> --title "rabi v<version>" --generate-notes. Create the draft without Latest flags; add only--prereleasefor prereleases. Choose Latest at dispatch with-f make_latest=true|false|legacy(defaulttrue); stable 7.x releases usetrueeven during the v7 beta, and prereleases are forced tofalse. Backports to an older release line (for example, a patch for an older minor after a newer minor has shipped) dispatch with-f make_latest=false. Polish the draft notes before dispatching when possible; notes remain editable after publishing. Dispatch.github/workflows/release-compile.ymlwithgh workflow run release-compile.yml --ref main -f tag=v<version> -f make_latest=trueand watch the run. CI resolves the unique draft and its commit, builds, verifies and attests all six assets, uploads them to that draft, checks its complete asset list and sizes, then publishes it. For a new tag, the draft target must be a full SHA reachable frommain; an existing tag must resolve to the intended commit, also reachable frommain, and match any full target SHA on the draft. The workflow packages the version inCargo.tomlasrabi-v<version>-<os>-<arch>.tar.gzfor linux/darwin x64/arm64, each containing onlyrabi.install.shsupports onlyrabi-v<version>-<os>-<arch>.tar.gzarchives. v7.0.0-alpha.10, v7.0.0-alpha.9 and v7.0.0-alpha.8 must each be installed with that release's owninstall.shathttps://github.com/yoiailabs/rabi/releases/download/<TAG>/install.sh(replace<TAG>with the release tag); v7.0.0-alpha.7 and older have no installer and must be installed manually. Linux binaries use static musl. Releases upload all four archives,install.shfrom the tag, and sortedSHA256SUMScovering those five files, with GitHub artifact attestations for all six assets. Artifact attestations name themainworkflow commit that ran the build; the built commit is the resolved release commit shown in the run summary alongside the tag, release ID, workflow commit and six asset SHA256s. GitHub's own immutable-release attestation binds the tag, commit and assets. Before publishing, the finalize job installs the linux-x64 archive withinstall.shfrom a localfile://mirror of the assets. PR dry runs build and verify checksums without attesting or uploading to a release; only dry runs may skip a missinginstall.sh. npm is not published. - PR dry runs still run on pull requests to
maintouching.github/workflows/release-compile.yml,Cargo.toml,Cargo.lock,rust-toolchain.toml, orinstall.sh, building all four targets and running the installer smoke test. - Before the first ship, enable release immutability in Settings → General → Releases → "Enable release immutability". Publishing locks assets and the tag. CI fails after publishing if the release API reports immutability is disabled, and warns if the field is absent. If CI fails before publishing, fix the cause and re-dispatch (draft assets can be replaced), or delete the draft. Never patch a published release's assets or tag. A deleted immutable release's tag cannot be reused; ship a new patch version instead.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

