# AGENTS.md — diskr agent protocol
Instructions for any coding agent (Claude Code, Junie, Codex, or otherwise)
working in this repository. Follow this file exactly; it is the single source
of truth for the development workflow. Human contributors follow the same
process.
## Project summary
diskr is a macOS-only terminal disk/storage manager written in Rust
(MSRV 1.88, ~6k lines, no async runtime). The TUI is the product; CLI report
modes (`--top`, `--reclaim`, `--save`/`--diff`, `--space`, `--packages`)
mirror its intelligence for scripting. The scanner is syscall-bound
(`getattrlistbulk(2)`); do not assume more threads or bigger buffers improve
scan performance.
## Documentation map
| [README.md](README.md) | User-facing docs, key table, release flow | Keys, CLI flags, or user-visible behavior change |
| [CHANGELOG.md](CHANGELOG.md) | What shipped, per version | Every behavior change (under `[Unreleased]`) |
| [docs/ISSUES.md](docs/ISSUES.md) | Living issue tracker | Starting, finishing, or discovering work |
| [ROADMAP.md](ROADMAP.md) | Product direction, feature-level plans | A feature ships or direction changes |
| [docs/AUDIT.md](docs/AUDIT.md) | **Frozen archive** of the 2026-06 audit | Never. Read-only reference for findings #1-#70 |
**Issue numbering:** a reference like "issue #21" or `(#21)` always means an
entry in [docs/ISSUES.md](docs/ISSUES.md) (numbering inherited from the audit
findings in docs/AUDIT.md). This repo does not use GitHub issues. If an ID is
not in ISSUES.md's index, it is an already-resolved finding — check the
Resolved section and the matching finding in docs/AUDIT.md before concluding
it does not exist.
## The workflow (non-negotiable)
1. **Before starting any work**, read `docs/ISSUES.md` and the `[Unreleased]`
section of `CHANGELOG.md`. Other agent sessions run in parallel and commit
mid-task: re-read these files (and any source file) immediately before
editing them, and expect occasional transient breakage from concurrent
commits — check `git log` before assuming your change caused a failure.
2. **Claim your work — and track untracked work.** If you are working on a
tracked issue, set its status line to
`In Progress (YYYY-MM-DD, <session/agent>)` in `docs/ISSUES.md`. If Milo
asks for a change that is not in the tracker — "make [x] faster", "change
this UI element from [x] to [y]", a new flag, a behavior tweak — add an
issue for it first (next free ID, type Perf/UX/Feature/etc., a few lines
describing the request and intended approach), mark it In Progress, and
from there treat it exactly like a listed issue: same validation, same
changelog entry referencing the ID, same move to Resolved, same release.
The tracker is the complete record of all work, not just audit findings;
"it wasn't a listed issue" is never a reason to skip the protocol. Never
reuse or renumber IDs.
3. **No change goes undocumented.** Every commit that changes behavior must
update `CHANGELOG.md` under `[Unreleased]` in the same commit (Added /
Changed / Fixed / Removed). Pure refactors, test-only, and doc-only commits
need no changelog entry.
4. **Found a bug you are not fixing right now?** Add it to `docs/ISSUES.md`
with the next free ID. Found and fixed one inline? Still add it, marked
Resolved, so the ID and history exist.
5. **When you finish an issue:** move its entry to the Resolved section of
`docs/ISSUES.md` with the version (or `Unreleased`), and make sure the
changelog entry references the issue ID, e.g. `(#52)`.
6. **Keep user docs in sync.** If you add/change a key binding or CLI flag,
update the README key table and `print_help` in the same commit (issue #40
exists because this was skipped).
7. **Never edit `docs/AUDIT.md`.** It is a frozen snapshot; several of its
status checkboxes are known to be wrong. Current truth lives in
`docs/ISSUES.md` and `CHANGELOG.md`.
8. **Do not revert other sessions' documentation edits.** If `docs/ISSUES.md`
or `CHANGELOG.md` changed under you, merge your entry in; never overwrite.
9. **Ship completed work.** When Milo asks for an issue fix or a change, the
task is not done at a local commit: complete the release process below so
the change is pushed to GitHub (`main`) and published to crates.io. Only
skip the release if Milo explicitly says not to release, or if the change
is doc-only / has no behavior effect — those are still pushed to `main`,
just without a version bump and tag.
10. **Track deferred work at the moment of deferral.** If an issue, finding,
or plan splits work into phases ("Phase 2", "follow-up", "later"), the
deferred part gets its own issue in `docs/ISSUES.md` before the delivered
part is marked complete — a checked box reads as fully resolved and
buries anything still pending inside it. Likewise, promote requirements
that exist only in rationale prose ("mark stale, refresh on demand") to
explicit spec bullets or issues: completion is verified against bullets,
so prose-only requirements ship by accident or not at all. (Added after
audit finding 19's Phase 2 went untracked for weeks; see #82-#86.)
## Validation before every commit
```sh
cargo fmt -- --check
cargo check --locked
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked
```
Caution: never add tests that touch real user state (Trash, `~/Library`,
Finder automation) — see issue #44. Destructive operations must be behind
injectable runners in tests.
## Attribution policy
Codex, Claude, Claude Code, and other coding agents are tools, not project
contributors. GitHub-visible project history must attribute code, docs,
release notes, tags, and other published artifacts to the human maintainer,
not to an agent.
- Before any commit, tag, push, or release action, verify `git config user.name`
and `git config user.email` are Milo's human Git identity, and verify no
`GIT_AUTHOR_*` or `GIT_COMMITTER_*` environment variable names an agent.
- Do not add `Co-authored-by`, `Generated with`, `Signed-off-by`, release-note
credit, changelog credit, docs credit, or metadata that names Codex, Claude,
Claude Code, OpenAI, Anthropic, or another agent/vendor as an author,
co-author, contributor, generator, releaser, or implementer.
- If a local tool tries to add agent attribution automatically, remove that
attribution before committing. If it cannot be disabled, stop and ask Milo
before creating commits, tags, or releases.
- Before pushing a release tag, inspect the commits included since the previous
release tag. If any commit author, committer, trailer, or generated release
note would make Codex, Claude, or another agent appear as a contributor,
stop before publishing and ask Milo how to proceed.
- Do not rewrite or edit existing commits, tags, GitHub releases, or published
crates to remove prior attribution unless Milo explicitly requests that
history-changing work.
## Release process
Releases go directly on `main` (no feature branch): commit → tag → publish.
This is the default end state of any requested fix or change (workflow
rule 9). Publishing is automated: pushing a `vx.y.z` tag triggers the GitHub
Release workflow, which validates the tag, publishes to crates.io, and
creates the GitHub release. **Never run `cargo publish` manually.**
1. `git pull --rebase` first — parallel sessions release too. Pick the next
unused patch version (check `Cargo.toml` and `git tag` after pulling).
2. Run the full validation set plus `cargo package --locked`.
3. Move the `[Unreleased]` changelog content into a new
`## [x.y.z] - YYYY-MM-DD` section (leave `[Unreleased]` present and empty).
4. Bump `version` in `Cargo.toml`, refresh `Cargo.lock`.
5. Commit (imperative mood, short title), push to `main`, then create and
push the matching tag `vx.y.z`.
6. If the push or tag is rejected because another session released in the
meantime, rebase, re-bump to the next free version, and retry — never
force-push or delete tags.
7. Confirm the Release workflow succeeded (`gh run list --workflow Release
--limit 1` or the Actions tab) before reporting the task complete; if it
failed, fix and re-release rather than leaving a half-published version.
## Conventions
- Commits: imperative mood, short titles. Reference issue IDs where relevant.
- No emojis in code, docs, or commits.
- Prefer editing existing files over creating new ones; no new doc files
unless this protocol changes.
- Comments only where the logic is not self-evident; match surrounding style.