mirror of
https://github.com/cheat/cheat.git
synced 2026-03-07 03:03:32 +01:00
- Remove unused parameters, dead files, and inaccurate doc.go files - Extract shared helpers, eliminate duplication - Rename cheatpath.Cheatpath to cheatpath.Path - Optimize filesystem walks (WalkDir, skip .git) - Move sheet name validation to sheet.Validate - Move integration tests to test/integration/ - Consolidate internal/mock into mocks/ - Move fuzz.sh to test/ - Inline loadSheets helper into command callers - Extract config.New into its own file - Fix stale references in HACKING.md and CLAUDE.md - Restore plan9 build target - Remove redundant and low-value tests - Clean up project documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
81 lines
2.7 KiB
Markdown
81 lines
2.7 KiB
Markdown
# ADR-004: Recursive `.cheat` Directory Search
|
|
|
|
Date: 2026-02-15
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
Previously, `cheat` only checked the current working directory for a `.cheat`
|
|
subdirectory to use as a directory-scoped cheatpath. If a user was in
|
|
`~/projects/myapp/src/handlers/` but the `.cheat` directory lived at
|
|
`~/projects/myapp/.cheat`, it would not be found. Users requested (#602) that
|
|
`cheat` walk up the directory hierarchy to find the nearest `.cheat`
|
|
directory, mirroring the discovery pattern used by `git` for `.git`
|
|
directories.
|
|
|
|
## Decision
|
|
|
|
Walk upward from the current working directory to the filesystem root, and
|
|
stop at the first `.cheat` directory found. Only directories are matched (a
|
|
file named `.cheat` is ignored).
|
|
|
|
### Stop at first `.cheat` found
|
|
|
|
Rather than collecting multiple `.cheat` directories from ancestor directories:
|
|
|
|
- Matches `.git` discovery semantics, which users already understand
|
|
- Fits the existing single-cheatpath-named-`"cwd"` code without structural
|
|
changes
|
|
- Avoids precedence and naming complexity when multiple `.cheat` directories
|
|
exist in the ancestor chain
|
|
- `cheat` already supports multiple cheatpaths via `conf.yml` for users who
|
|
want that; directory-scoped `.cheat` serves the project-context use case
|
|
|
|
### Walk to filesystem root (not `$HOME`)
|
|
|
|
Rather than stopping the search at `$HOME`:
|
|
|
|
- Simpler implementation with no platform-specific home-directory detection
|
|
- Supports sysadmins working in `/etc`, `/srv`, `/var`, or other paths
|
|
outside `$HOME`
|
|
- The boundary only matters on the failure path (no `.cheat` found anywhere),
|
|
where the cost is a few extra `stat` calls
|
|
- Security is not a concern since cheatsheets are display-only text, not
|
|
executable code
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
- Users can place `.cheat` at their project root and it works from any
|
|
subdirectory, matching their mental model
|
|
- No configuration changes needed; existing `.cheat` directories continue to
|
|
work identically
|
|
- Minimal code change (one small helper function)
|
|
|
|
### Negative
|
|
- A `.cheat` directory in an unexpected ancestor could be picked up
|
|
unintentionally, though this is unlikely in practice and matches how `.git`
|
|
works
|
|
|
|
### Neutral
|
|
- The cheatpath name remains `"cwd"` regardless of which ancestor the `.cheat`
|
|
was found in
|
|
|
|
## Alternatives Considered
|
|
|
|
### 1. Stop at `$HOME`
|
|
**Rejected**: Adds platform-specific complexity for minimal benefit. The only
|
|
downside of walking to root is a few extra `stat` calls on the failure path.
|
|
|
|
### 2. Collect multiple `.cheat` directories
|
|
**Rejected**: Introduces precedence and naming complexity. Users who want
|
|
multiple cheatpaths can configure them in `conf.yml`.
|
|
|
|
## References
|
|
|
|
- GitHub issue: #602
|
|
- Implementation: `findLocalCheatpath()` in `internal/config/config.go`
|