2026-06-26 ghq Project-Organization Research
What I set out to do
Started by investigating how the worktrunk (wt) tooling interacts with ~/projects and ~/worktrees, and how it decides whether a repo/branch is already open. That surfaced a gap: worktrunk owns the worktree layer but nothing governs where canonical repos live (~/projects is a flat, manually-maintained dir). The question became: what do people use to control project repos?
What I actually did
Researched ghq and its alternatives, adopted ghq (commit 0eedb8e), then migrated ~/projects into the host/owner/repo layout. “Controlling projects” splits into 4 conflated jobs (clone organization, worktree management, multi-repo bulk ops, navigation); ghq is the clear leader for clone organization, and its layout matches the project-id worktrunk already derives from the remote URL. Notable insight: the popular ghq + gwq + fzf “coding-agent-friendly” pattern has gwq as a peer to worktrunk, not a complement — so the existing setup is validated and only the clone layer (ghq) was missing. Full writeup in Git Project-Organization Tooling - ghq and the 4-Category Landscape.
Implemented declaratively: ghq → coreTools in packages.nix, ghq.root = ~/projects in git.nix, proj fzf-jump in shell.nix. Then hardened a one-off migration script and ran it: 45 repos moved, 13 local-only left flat, 2 duplicate pairs resolved.
What was striking
The migration dry-run exposed real data debt: a malformed https:///www.github.com/... remote, www. host variants, and four “duplicates” that on inspection were not safe to delete — rustlings held 24 uncommitted exercise files, and both jupyterlab-claude-code copies had divergent unpushed commits (jcc: 291 + stash + 3 branches; fresh-jlcc: 11 on fix/issue-57). Deleted mypath (clean) and fresh-jlcc (after bundling its refs to ~/.local/share/ghq-migrate-backups/), kept and migrated the ones with work. Lesson reinforced: duplicate-by-remote ≠ safe to delete; snapshot unpushed commits to a git bundle before any destructive dedup.
Outcome / next actions
- Shipped: core ghq config (
0eedb8e);~/projectsmigrated to host/owner/repo. - Backup:
fresh-jlccwork preserved at~/.local/share/ghq-migrate-backups/fresh-jlcc-*.bundle(delete once sure it’s not needed). - Stale: zoxide DB holds old
~/projects/<name>paths — will reseed as I re-cd. - Deferred: work GHE includeIf identity (route through
~/.config/secrets/gitwhen I have hostname/username/email).