Worktree project inference was limited to built-in parser behavior, which left machine-specific worktree layouts with no durable way to collapse feature checkout paths back into canonical projects. This adds explicit machine-scoped mappings stored in SQLite, with sync and resync paths applying them consistently while preserving session archive data.
Mappings are managed manually from settings and only rewrite existing sessions through an explicit apply action or normal sync/resync ingestion. The API derives the machine from the running server so synced sessions do not introduce cross-machine configuration drift.
Validation: go test ./internal/db ./internal/sync ./internal/server -run 'Test(WorktreeProjectMappings|ResolveWorktreeProjectMapping|ApplyWorktreeProjectMappings|ApplyWorktreeProjectMappingsToSession|CopySessionMetadataPreservesWorktreeProjectMappings|SyncEngineAppliesWorktreeProjectMapping|SyncSingleSessionAppliesWorktreeProjectMapping|SyncSingleSessionSkippedClaudeAppliesWorktreeProjectMapping|SyncSingleSessionIncrementalAppliesWorktreeProjectMapping|SyncAllIncrementalAppliesWorktreeProjectMapping|SyncAllSkipped.*Worktree.*Mapping|SyncPathsSkipped.*Worktree.*Mapping|ResyncAllAppliesWorktreeProjectMappingDuringBulkWrites|WorktreeMappingsAPI)' -count=1
Validation: bun run check
Validation: bun run build
🤖 Generated with [OpenAI Codex](https://openai.com/codex)
Co-authored-by: OpenAI Codex <noreply@openai.com>
Closes #416.
Adds user-configurable rules that map worktree paths back to a canonical
project, so worktree sessions group with the parent repo instead of becoming
a separate project derived from the branch name.
The built-in parser infers a session's project from its
cwd, which works forstandard layouts but not custom worktree conventions like
~/code/{project}.worktrees/feat/my-feature/— those sessions end up undermy-featurerather than{project}. This branch adds a manual override thatlives in SQLite, is scoped to the current machine, and is applied both as new
sessions stream in and to existing sessions on demand.
How it works
worktree_project_mappingstable keyed by(machine, path_prefix)withan
enabledflag. Path prefixes are cleaned and have trailing separatorsstripped so matches are stable regardless of how a user types the prefix.
and rewrites
projectfor any session whosecwdfalls under an enabledprefix. The resolver is wired into all ingestion paths: single-session
writes, incremental sync, bulk resync, and the rebuild-and-swap full
resync. Excluded, trashed, and skipped session files are left alone so the
rewriter does not resurrect intentionally removed data.
/api/v1/settings/worktree-mappings(list / create / update /delete / apply). The server derives the machine identifier itself instead
of accepting it from the client, so a mapping created on one machine never
bleeds into another machine's view of synced sessions.
mappings, plus an Apply action that runs the rewrite over already-imported
sessions and reports how many were matched and updated.
Notes
is to let users formalize their personal layout once and have it stick.
project; the rest of the session record, includingdata carried through the bulk resync's rebuild-and-copy path, is preserved.