Development record
abcd's User-Level Home Lives Where You Want It
Press Release
One user-level home for everything abcd keeps outside your repos — blessed by default, movable by choice. abcd's repo-tree
.abcd/tiers cover what belongs to a project. But some state belongs to the person: the confidential-sources corpus (itd-76), and whatever user-scoped configuration follows it. That state lives in abcd's user-level home —~/.abcd.noindex/by default, the same dotfile convention as every tool a developer already trusts with home-directory state. The default is only a default: a guided, wizard-style flow moves the home wherever the user's filing system wants it — say, alongside their projects root — updates the recorded location, and verifies every consumer (guards, skills, verbs) resolves the new path before declaring the move done. The user tier is additive: repo.abcd/tiers are untouched, and a repo remains fully functional on machines where no user home exists at all."My whole development world lives under one directory, and I wanted abcd's user state in there too, not scattered in my home directory," said Alice. "One command moved it, re-pointed everything that reads it, and proved the pre-commit guard still found my banlist before it called the move complete."
Why This Matters
The moment abcd grew a user-level surface, it inherited a question every long-lived tool answers eventually: whose filing system wins, the tool's or the user's? Hard-coding ~/.abcd.noindex/ answers "the tool's" forever; making the path a per-callsite option answers "nobody's" and scatters resolution logic across every consumer. The right shape is a single blessed default plus a single recorded override that every consumer resolves through one function — cheap now, and it prevents the class of bug where one consumer honours the moved home and another silently recreates the old one. A rehearsed, verified move matters more than the move itself: user state includes material whose guards must not lapse mid-relocation (itd-76's banlist source), so the flow proves consumers resolve the new location before the old one is retired.
What It Looks Like
- One resolution rule. Every abcd component that touches user-level state resolves the home through a single lookup: explicit config, else environment override, else
~/.abcd.noindex/. No consumer hard-codes the path. - A guided move. An interactive, wizard-style flow relocates the home: copies (never moves-then-prays) the tree to the target, records the new location, re-runs each consumer's own verification (the itd-76 guard finding its banlist source, skills resolving the corpus), and only then retires the old tree — a rehearsed cutover with a rollback path, not a rename.
- Additive to repo tiers. The user home complements the repo's
.abcd/layout; nothing repo-side moves, and every repo continues to work on machines with no user home (guards no-op exactly as the itd-74 banlist does on fresh clones). - Doctor-visible. The install-health check reports where the user home resolves and flags a dangling override (recorded path that no longer exists).
SOTA
Surveyed on 2026-10-23; sources, evidence tiers and the local fit risks are in the install-update-release SOTA note.
- Every surveyed tool relocates through an environment variable; none
documents a move command or a pointer file:
RUSTUP_HOMEandCARGO_HOME(rustup),MISE_DATA_DIR,MISE_CONFIG_DIR,MISE_CACHE_DIRandMISE_STATE_DIRwith XDG fallbacks (mise, which warns to set them "in the environment that starts mise", never in the tool's own config, or "one command [may] use a different directory than the next"),GH_CONFIG_DIRthen$XDG_CONFIG_HOME/ghthen$AppData/GitHub CLIthen~/.config/gh(gh), and the harness's own configuration-directory variable. - XDG names what a home holds: data (
~/.local/share), config (~/.config), state (~/.local/state: logs, history, "state... that can be reused on a restart") and cache (~/.cache, "non-essential"); all paths "must be absolute" and a relative one is "invalid" and ignored. Go'sos.UserConfigDirandos.UserCacheDirapply this on Unix, return~/Library/...on macOS and%AppData%/%LocalAppData%on Windows, and error on a relative value. - macOS's own guidance is
~/Library/Application Support/<bundle id>, and of the tools surveyed only mise follows it, and only for its cache; rustup, uv, gh and the harness keep dot-directories or~/.localthere. - No tool lets a project pin a person's home: the override is always in the person's environment or settings.
- The one-resolver half already exists:
internal/abcdhomeis the one place that spells the home, held by test; the override and the move are what is missing.
Path 2 — native, shaped to the XDG and GH_CONFIG_DIR precedence, with the
resolver as the seam: the variable first (the field's consensus), a pointer
file at a fixed location second (what no tool has, but what a move abcd
verifies needs, since it cannot assume the person exported anything), the
default third; relative values refused with the reason; a repo-level pin
refused (open question 2); no eager reference sweep on move, since no
surveyed tool does one and the per-repo banlist refresh covers it (open
question 3). No new dependency. The independent fit-challenge runs at plan
time.
Open Questions
- (SOTA 2026-10-23) What is the fixed location of the pointer file that the
variable cannot move:
os.UserConfigDir()/abcd, or a file inside the default home that is read only when the home has not moved? - (SOTA 2026-10-23) Does the symlinked-home refusal (a dotfiles checkout
cannot host
~/.abcd.noindex) apply to the moved location, so the move is not the way round the rule? - Where the override is recorded: a user-level config file at a fixed bootstrap location (a pointer must live somewhere unmovable), an environment variable, or both with defined precedence.
- Whether repo-level config may pin a user-home path for reproducibility, or whether that inverts the tiers (a repo dictating personal filing) and should be refused.
- Migration of stale references after a move — e.g. per-repo banlists regenerated on next commit by the itd-76 auto-refresh, or swept eagerly by the move flow.
Frontmatter
| id | itd-77 |
|---|---|
| type | intent |
| lifecycle | drafts |
| kind | standalone |
| severity | minor |
.abcd/development/intents/drafts/itd-77-relocatable-user-home.md
open on GitHub ↗ · commit history ↗
Referenced by6
- iss-2610262041051263The glossary forbids 'corpus' as a synonym for the library; the relocatable-home draft calls the person's sources the 'confidential-sources corpus'.related
- iss-2610262043555411itd-117 puts the user-scope rules at `~/.abcd/rules.json`; itd-77 puts abcd's user-level home at `~/.abcd.noindex/`related
- iss-2610262043562914itd-200 puts the status line's user-level defaults under `~/.abcd/`; itd-77 puts the user-level home at `~/.abcd.noindex/`related
- iss-2610262044265126The relocatable-home draft has abcd move its home on command, but the shipped rename ruled that abcd moves nothing and fixed the name at ~/.abcd.noindexrelated
- iss-2610262044449331itd-77 says abcd's user-level home defaults to `~/.abcd.noindex/`; shipped itd-76 says it defaults to `~/.abcd/`, with the sources corpus at `~/.abcd/sources/`related
- itd-76abcd Lets You Consult Sources You Cannot Cite — and Remembers Every Debtbuilt on by
mentions5
- dcn-26070800000000092026-07-08 — `~/.abcd/` blessed as abcd's user-level home (fourth tier,
- dcn-26081600000000072026-08-16 — itd-76 planned at the live interview (spc-31 minted, `intent ready` exit 0). The itd-84 hand-run rendered SPLIT, confirmed: itd-76 narrows to the personal core (source add / ledger / sync-banlist / cite-check + guards); team share/ingest files as itd-126 and paper reconstruction as itd-127 (both `refines` itd-76, seeded criteria marked unconfirmed); the trust rule extracts to adr-41 (proposed) + brief invariant 9 — documents and ledgers never leave the user tier, a public citation requires both gates — which the intents cite rather than declare; the stance files as the consult-freely-cite-deliberately principle. Interview rulings: the share surface is the existing `.abcd/development/research/references.csl.json` research store, not a second `.abcd/work/references.json` exchange file (one committed bibliography — resolves the store clash the sources-plan adversarial review flagged); the draft's "Dogfood (already running)" claim was stale and is rewritten as target (no corpus on the development machine); multi-machine ledger ownership explicitly deferred until a second machine exists; persona Maya corrected to Alice. Seven Given-When-Then criteria authored and accepted in full. Rejected: planning the monolith (both remaining open questions gated only the share/ingest part), and holding for itd-77 (the corpus default path works without relocation). Hand-run graded into the decomposition-calibration note.
- itd-74abcd Keeps the Names You Ban Out of Everything You Publish
- itd-2609091416295622A session sees the records its peers hold before it mints or fixes one
- spc-31source-provenance-ledger