You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
v0.1.0 tagged on main with a GitHub Release carrying Linux and macOS binaries (amd64 and arm64) built by GoReleaser under GitHub Actions. The binary ships a Picker, cdd scan, and cdd init fish|bash|zsh Wrappers that Jump. The repo's Community Standards checklist is fully green.
Notes
This map executes. Task tickets build the tool, not just decide it. Each task is done by a sub-agent on its own branch: micro commits in Conventional Commits format, a PR opened against main, merged by the driving session. Never push to main. No file over 300 lines. Every package has tests. Use the tdd skill for task tickets and the codebase-design skill for layout questions.
Domain.CONTEXT.md is the glossary; use its terms (Root, Kind, Project, Jump, Visit, History, Scan, Picker, Wrapper) verbatim in code, issues, and docs.
Settled while charting.
History is the sole ordering source. Never-visited Projects sort after visited ones, alphabetically, with an empty last-worked cell. No git mtime in the ordering.
Scan seeds one Visit per Project from its last commit time, or directory mtime when it is not a repository. It is idempotent and never overwrites a newer real Visit. The Picker hints to run cdd scan when History is empty.
Wrapper pattern follows starship: cdd init <shell> | source. The binary prints the chosen path; the Wrapper performs the Jump.
Stack: Go 1.26, Bubble Tea, Lip Gloss, Bubbles, a small fuzzy library (sahilm/fuzzy or equivalent). Git status by shelling out to git status --porcelain=v2 --branch; no go-git. Projects that are not repositories show no status.
Look: gh-dash style. Filter input on top, aligned table with highlighted selected row, relative times, colored status glyphs with a plain-word legend in the footer, adaptive to light and dark terminals.
Release: GoReleaser on v* tags. Linux and macOS, amd64 and arm64.
Community standards: MIT, Contributor Covenant 2.1, CONTRIBUTING.md stating the micro-commit and PR-only rules, SECURITY.md pointing at GitHub private vulnerability reporting, bug and feature issue templates, one PR template.
PR workflow is a convention, not enforced. No branch protection, no required checks.
Decisions so far
History file format and location: append-only TSV log at ~/.local/share/cdd/history (XDG data dir, same on macOS), one Visit per line as RFC3339-UTC<TAB>jump|scan<TAB>kind/project; history.max_visits (default 1000) bounds lines kept, compaction by temp-and-rename when 10% over, flock around append and compaction; Scan seeds scan lines and never overwrites a jump.
Config schema for config.toml: root required with ~ expansion, exclude globs relative to Root, include_hidden = false, [history] max_visits = 1000; Kinds discovered, no column config; pelletier/go-toml/v2 strict, unknown keys and bad values are errors; no config path override.
Command surface and Wrapper contract: cobra; cdd, pick [query], init <shell>, scan, version, plus cobra's help and completion; pick prints one absolute path on stdout, TUI on /dev/tty, exit 0/130 cancel/1 error/2 usage; binary writes the Visit before printing; exact name or kind/project match Jumps without the Picker, else prefilled filter; bare cdd on a terminal hints to install the Wrapper; Wrapper named cdd via command cdd, pass-through list generated from the command tree.
Package layout for the module: cmd/cdd/main.go plus nine internal/ packages: config, project, history, git, scan, picker, jump, shell, cli; the pick flow and ordering rule live in jump, Picker takes an injected StatusFunc, no filesystem abstraction, external test packages on stdlib testing, 300-line rule enforced in CI.
GoReleaser release workflow for a Go CLI on tag push: version: 2 config, one build from ./cmd/cdd for linux and darwin on amd64 and arm64 with CGO_ENABLED=0 and -trimpath, tar.gz archives and sha256 checksums; a v* tag workflow with checkout v7, setup-go v7 and goreleaser-action v7 under contents: write. Detail on the research/goreleaser-workflow branch.
Parsing git status porcelain v2 for clean, dirty, untracked, ahead and behind: first byte of each record decides: 1/2/u dirty, only ? untracked, none clean; # branch.ab +A -B gives ahead-behind, absent or +? -? means no upstream. Invoke GIT_OPTIONAL_LOCKS=0 git -C <dir> status --porcelain=v2 --branch -unormal -z with a 2 s timeout, render timeout as unknown, exit 128 means not a repository. Check for .git since git walks up from subdirectories. Detail on the research/git-status-porcelain branch.
Bubble Tea stack: versions to pin and the async row-update pattern: pin the v2 line on the charm.land path: charm.land/bubbletea/v2 v2.0.9, charm.land/lipgloss/v2 v2.0.6, charm.land/bubbles/v2 v2.2.1 (the github path fails with a module mismatch). Fill the status column with tea.Batch of one tea.Cmd per row from Init, each result arriving as its own message keyed by Project path, fan-out bounded by a semaphore. Fuzzy: github.com/sahilm/fuzzy v0.1.3, stdlib-only with match positions, also what Bubbles' list uses. Detail on the research/bubbletea-stack branch.
How starship and zoxide implement shell init for fish, bash and zsh: zoxide's zi is result=$(\command zoxide query --interactive) && cd "$result", TUI on /dev/tty, stdout carries only the path, cancel is exit 130 with empty stdout. Recommended Wrapper: a same-named function passing non-Jump subcommands to command cdd, otherwise capture command cdd pick, guard non-empty (fish cd with an empty list goes to $HOME), then cd --. Binary draws via tea.OpenTTY, prints one path, exits 130 silently on cancel, and records the Visit itself. zsh snippet is manual-derived, untested locally. Detail on the research/shell-init-patterns branch.
Picker look: runnable mock to react to: rows grouped by Kind (History order inside a Kind, Kinds by most recent Visit), caret-selected row with no background, aligned status glyph cluster with ahead/behind counts, right-aligned relative time, a preview pane on the right (path, branch, status words, sync, last visit, visit count), glyph legend plus keys in the footer; GitHub Primer accents via lipgloss.LightDark. Adds [keys] vim = true to config: j/k move, f focuses the filter, esc returns to the list keeping the query. Mock on the prototype/picker-look branch.
Narrow terminals: when the preview pane hides and how rows truncate: preview hides when fewer than 30 columns remain after the list takes its natural width (capped at 55%), automatic only, branch goes with it, long preview values wrap; below the list width the relative time compresses first (2h, 3d), then the name truncates with … to a floor of 8, status never shrinks, no hard minimum; under 15 rows the legend drops, under 10 the keys line too.
Write the README: merged as PR #42; README with install, shell setup, config reference; demo placeholder for the maintainer.
Lint follow-up: PR #43 cleared errcheck and staticcheck findings so CI on main is green.
Cut v0.1.0: tagged 4c2025f; Release v0.1.0 carries four binaries plus checksums, verified by installing the Linux amd64 build and Jumping with it. Destination reached.
Not yet specified
Nothing. Every fog item graduated into a ticket and was resolved. The README shape landed with the README task.
Out of scope
Reconnecting History across a Project rename or move (git remote, inode, or similar heuristics). A renamed Project starts with no History. Ruled out while resolving Stale History.
Configurable Picker columns (a columns key in config). Columns are fixed, decided by the Picker prototype. Ruled out while resolving Config schema for config.toml.
Wrappers for PowerShell, nushell, and elvish. All feasible (starship and zoxide do it); planned for a future release, no release committed. Windows binaries follow PowerShell.
Git commit or index mtime as a live ordering source. History is the source; git time only seeds via Scan.
Package manager distribution (Homebrew tap, AUR, nix). The destination is Release binaries.
Branch protection and required CI checks on main.
go-git or any in-process git implementation.
Research branches (research/*) were deleted after the tasks consuming them merged; their findings are quoted in each ticket's resolution comment. The prototype/picker-look branch is kept as the Picker's visual reference.
Destination
v0.1.0tagged onmainwith a GitHub Release carrying Linux and macOS binaries (amd64 and arm64) built by GoReleaser under GitHub Actions. The binary ships a Picker,cdd scan, andcdd init fish|bash|zshWrappers that Jump. The repo's Community Standards checklist is fully green.Notes
This map executes. Task tickets build the tool, not just decide it. Each task is done by a sub-agent on its own branch: micro commits in Conventional Commits format, a PR opened against
main, merged by the driving session. Never push tomain. No file over 300 lines. Every package has tests. Use thetddskill for task tickets and thecodebase-designskill for layout questions.Domain.
CONTEXT.mdis the glossary; use its terms (Root, Kind, Project, Jump, Visit, History, Scan, Picker, Wrapper) verbatim in code, issues, and docs.Settled while charting.
cdd scanwhen History is empty.cdd init <shell> | source. The binary prints the chosen path; the Wrapper performs the Jump.git status --porcelain=v2 --branch; no go-git. Projects that are not repositories show no status.v*tags. Linux and macOS, amd64 and arm64.Decisions so far
~/.local/share/cdd/history(XDG data dir, same on macOS), one Visit per line asRFC3339-UTC<TAB>jump|scan<TAB>kind/project;history.max_visits(default 1000) bounds lines kept, compaction by temp-and-rename when 10% over,flockaround append and compaction; Scan seedsscanlines and never overwrites ajump.rootrequired with~expansion,excludeglobs relative to Root,include_hidden = false,[history] max_visits = 1000; Kinds discovered, no column config; pelletier/go-toml/v2 strict, unknown keys and bad values are errors; no config path override.max_visits; byte-exactkind/projectcomparison.cdd,pick [query],init <shell>,scan,version, plus cobra'shelpandcompletion;pickprints one absolute path on stdout, TUI on/dev/tty, exit 0/130 cancel/1 error/2 usage; binary writes the Visit before printing; exact name orkind/projectmatch Jumps without the Picker, else prefilled filter; barecddon a terminal hints to install the Wrapper; Wrapper namedcddviacommand cdd, pass-through list generated from the command tree.cmd/cdd/main.goplus nineinternal/packages: config, project, history, git, scan, picker, jump, shell, cli; the pick flow and ordering rule live injump, Picker takes an injectedStatusFunc, no filesystem abstraction, external test packages on stdlibtesting, 300-line rule enforced in CI.version: 2config, one build from./cmd/cddfor linux and darwin on amd64 and arm64 withCGO_ENABLED=0and-trimpath, tar.gz archives and sha256 checksums; av*tag workflow with checkout v7, setup-go v7 and goreleaser-action v7 undercontents: write. Detail on theresearch/goreleaser-workflowbranch.1/2/udirty, only?untracked, none clean;# branch.ab +A -Bgives ahead-behind, absent or+? -?means no upstream. InvokeGIT_OPTIONAL_LOCKS=0 git -C <dir> status --porcelain=v2 --branch -unormal -zwith a 2 s timeout, render timeout as unknown, exit 128 means not a repository. Check for.gitsince git walks up from subdirectories. Detail on theresearch/git-status-porcelainbranch.charm.landpath:charm.land/bubbletea/v2 v2.0.9,charm.land/lipgloss/v2 v2.0.6,charm.land/bubbles/v2 v2.2.1(the github path fails with a module mismatch). Fill the status column withtea.Batchof onetea.Cmdper row fromInit, each result arriving as its own message keyed by Project path, fan-out bounded by a semaphore. Fuzzy:github.com/sahilm/fuzzy v0.1.3, stdlib-only with match positions, also what Bubbles' list uses. Detail on theresearch/bubbletea-stackbranch.ziisresult=$(\command zoxide query --interactive) && cd "$result", TUI on/dev/tty, stdout carries only the path, cancel is exit 130 with empty stdout. Recommended Wrapper: a same-named function passing non-Jump subcommands tocommand cdd, otherwise capturecommand cdd pick, guard non-empty (fishcdwith an empty list goes to$HOME), thencd --. Binary draws viatea.OpenTTY, prints one path, exits 130 silently on cancel, and records the Visit itself. zsh snippet is manual-derived, untested locally. Detail on theresearch/shell-init-patternsbranch.lipgloss.LightDark. Adds[keys] vim = trueto config:j/kmove,ffocuses the filter,escreturns to the list keeping the query. Mock on theprototype/picker-lookbranch.2h,3d), then the name truncates with…to a floor of 8, status never shrinks, no hard minimum; under 15 rows the legend drops, under 10 the keys line too.cmd/cddstub.internal/configwith go-toml/v2, strict keys, example config.internal/historyTSV log, flock, compaction, Seed rules.internal/projectDiscover with hidden and glob exclusions.internal/gitporcelain v2 parser with 2 s timeout and NotRepo.internal/shellembedded Wrapper templates, executed in tests..goreleaser.yamlv2 and tag-triggered release workflow, snapshot check in CI.internal/scanseeds from last commit or mtime with a worker pool.internal/pickeron Bubble Tea v2, grouped list, preview, vim keys, narrow-terminal rules.internal/jumpordering rule, exact-match shortcut, Visit recording.internal/clion cobra with the decided exit codes and hint.mainis green.4c2025f; Release v0.1.0 carries four binaries plus checksums, verified by installing the Linux amd64 build and Jumping with it. Destination reached.Not yet specified
Nothing. Every fog item graduated into a ticket and was resolved. The README shape landed with the README task.
Out of scope
columnskey in config). Columns are fixed, decided by the Picker prototype. Ruled out while resolving Config schema for config.toml.main.research/*) were deleted after the tasks consuming them merged; their findings are quoted in each ticket's resolution comment. Theprototype/picker-lookbranch is kept as the Picker's visual reference.