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); ~/projects migrated to host/owner/repo.
  • Backup: fresh-jlcc work 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/git when I have hostname/username/email).