Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ make check # fmt, vet, lint, test
|---------|------|---------|
| `cmd/todo` | CLI command tree (`add`, `init`, `list`, `pickup`, `release`, `remove`, `detail`, `complete`, `reopen`, `bump`, `clear`, `doctor`), flag parsing, all terminal I/O | everything below |
| `internal/todo` | domain logic: task model, Markdown parse/serialize, ID allocation, filtering, note disposition | `internal/fs`, `internal/git`, `park/schema` |
| `internal/registry` | machine-local cache of tracked repo folders (`~/.config/.todocache`) | stdlib only |
| `internal/registry` | machine-local cache of tracked repo folders (`$XDG_CACHE_HOME/todo/registry.json`, falling back to `~/.cache/todo/registry.json`) | stdlib only |
| `internal/git` | git CLI helpers: repo root, remote URL, remote parsing | stdlib only |
| `internal/fs` | filesystem helpers (exists check) | stdlib only |

Expand Down Expand Up @@ -74,6 +74,6 @@ Control flow: per-repo commands resolve the repo root through `requireRepoConfig
## Implementation notes

- The only external dependencies are `urfave/cli/v3` (plus `urfave/cli-validation`) and the public `github.com/polymorcodeus/park/schema` package, which supplies the record frontmatter contract and render helpers. Keep `internal/*` free of new dependencies where stdlib will do.
- The registry path defaults to `~/.config/.todocache` and is overridable via `TODO_REGISTRY`.
- The registry path defaults to `$XDG_CACHE_HOME/todo/registry.json` (or `~/.cache/todo/registry.json`) and is overridable via `TODO_REGISTRY`.
- Version is dual-sourced: the embedded `VERSION` file serves local and `go install` builds, while `main.version`/`main.buildTime` ldflags (set by GoReleaser, and by the Makefile for `make build`) win when present.
- `AGENTS.md` is a private, symlinked file and is not part of this repository. Contributor-facing context belongs in this file and in `README.md`.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Status is `[ ]` open, `[o]` in progress, `[x]` done. `claimed:` records when a t

## Registry

Every `todo init` registers the repo in a machine-local JSON cache at `~/.config/.todocache`. The registry stores the absolute repo path, project name, git remote URL, parsed host/owner, and a `last_seen` timestamp. `todo list --all` and `todo doctor` use this cache to operate across tracked folders without `cd`ing.
Every `todo init` registers the repo in a machine-local JSON cache at `$XDG_CACHE_HOME/todo/registry.json` (falling back to `~/.cache/todo/registry.json`). The registry stores the absolute repo path, project name, git remote URL, parsed host/owner, and a `last_seen` timestamp. `todo list --all` and `todo doctor` use this cache to operate across tracked folders without `cd`ing.

## Note disposition

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.0.3
v1.0.4
2 changes: 1 addition & 1 deletion cmd/todo/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func setupGitRepo(t *testing.T) string {
t.Fatalf("git init: %v", err)
}
t.Chdir(dir)
t.Setenv("TODO_REGISTRY", filepath.Join(dir, ".todocache"))
t.Setenv("TODO_REGISTRY", filepath.Join(dir, "registry.json"))
return dir
}

Expand Down
10 changes: 7 additions & 3 deletions internal/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ type Entry struct {
LastSeen string `json:"last_seen"`
}

// DefaultPath returns the default registry file path: ~/.config/.todocache.
// DefaultPath returns the default registry file path:
// $XDG_CACHE_HOME/todo/registry.json, or ~/.cache/todo/registry.json.
func DefaultPath() string {
if cacheHome := os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
return filepath.Join(cacheHome, "todo", "registry.json")
}
home, err := os.UserHomeDir()
if err != nil {
return ".todocache"
return "todo-registry.json"
}
return filepath.Join(home, ".config", ".todocache")
return filepath.Join(home, ".cache", "todo", "registry.json")
}

// Load reads the registry from path. A missing file is treated as an empty
Expand Down
4 changes: 2 additions & 2 deletions internal/registry/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

func TestLoadMissingReturnsEmpty(t *testing.T) {
path := filepath.Join(t.TempDir(), "missing", ".todocache")
path := filepath.Join(t.TempDir(), "missing", "registry.json")
entries, err := Load(path)
if err != nil {
t.Fatalf("Load missing: %v", err)
Expand All @@ -18,7 +18,7 @@ func TestLoadMissingReturnsEmpty(t *testing.T) {
}

func TestSaveAndLoad(t *testing.T) {
path := filepath.Join(t.TempDir(), ".todocache")
path := filepath.Join(t.TempDir(), "registry.json")
want := []Entry{
{Path: "/code/foo", Project: "foo", Repo: "git@example.com:org/foo", LastSeen: "2026-09-01T00:00:00Z"},
}
Expand Down
Loading