Skip to content

feat: add glob/prefix support to session path mapping#24

Open
xlyk wants to merge 3 commits into
plastic-labs:mainfrom
xlyk:feat/glob-session-paths
Open

feat: add glob/prefix support to session path mapping#24
xlyk wants to merge 3 commits into
plastic-labs:mainfrom
xlyk:feat/glob-session-paths

Conversation

@xlyk

@xlyk xlyk commented Apr 3, 2026

Copy link
Copy Markdown

Summary

  • Adds glob pattern support to the sessions config field so entries like ~/Code/project.worktrees/* match multiple directories to the same session name
  • Exact paths take priority over globs; among globs, the most specific pattern (longest literal prefix) wins
  • Tilde expansion and path.resolve() normalization on both keys and cwd
  • Empty keys/values silently skipped to prevent ghost matches
  • Uses Bun.Glob for matching — zero new dependencies
  • 23 tests covering exact match, globs (*, **, ?, [...], {a,b}), specificity ordering, normalization, and edge cases

Motivation

Users with git worktree setups need to map multiple directories to the same session without adding an explicit config entry per path:

{
  "sessions": {
    "~/Code/project": "my-project",
    "~/Code/project.worktrees/*": "my-project"
  }
}

Test plan

  • bun test src/config.test.ts — 23/23 passing
  • bunx tsc --noEmit — clean
  • Manual: add glob entries to ~/.honcho/config.json, launch Claude Code in matching directories, verify session name via /honcho:status

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Per-path session name overrides via exact paths and glob patterns for flexible session configuration; exact matches outrank globs and the most specific glob wins; applies only to the per-directory session strategy
  • Documentation

    • Added "Per-path overrides" guide with example mappings and a pattern-matching reference table
  • Tests

    • Added comprehensive tests covering exact matches, glob semantics, precedence, normalization, and edge cases

allows users to map multiple directories to the same session name
using glob patterns in the sessions config field. useful for git
worktree setups and monorepos.

- exact paths take priority over globs
- globs sorted by specificity (longest literal prefix wins)
- tilde expansion and path.resolve() normalization
- empty keys/values are silently skipped
- uses Bun.Glob for matching (zero new deps)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 3, 2026

Copy link
Copy Markdown

Walkthrough

Added a sessions config object enabling per-path session name overrides via exact paths and glob patterns; implemented matching utilities and precedence (exact > glob, most specific glob wins); applied only to per-directory strategy; README docs and a comprehensive Bun test suite added. (50 words)

Changes

Cohort / File(s) Summary
Documentation
README.md
Added "Per-path overrides" under session strategy with examples, pattern-matching table, and precedence rules (exact matches outrank globs; most specific glob wins). Specifies applicability only to per-directory session strategy.
Implementation
plugins/honcho/src/config.ts
Extended path imports (resolve, isAbsolute); added normalizePath() (expands ~/, resolves absolutes), isGlobPattern() (uses GLOB_META_RE); exported `matchSessionForPath(cwd, sessions): string
Tests
plugins/honcho/src/config.test.ts
New Bun test suite for matchSessionForPath: exact key matching (including ~ expansion), normalization (trailing slashes, ..), glob behaviors (*, **, ?, braces, char classes), specificity and tie-breaking rules, ignored/invalid entries, worktree patterns, and proper null fallback.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • VVoruganti

Poem

🐇 I hopped through paths both near and far,

Exact keys led me like a steady star,
Wildcards danced in patterned light,
The longest prefix won the fight,
Per-directory nests found their name,
I tunneled home—session set, all tame. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main feature addition: glob and prefix pattern support for session path mapping.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/honcho/src/config.ts`:
- Around line 546-575: The matcher currently compares against raw session keys
so different spellings of the same path can collide; update matchSessionForPath
to first collapse/deduplicate entries by normalized key (use normalizePath(key)
as the map key and let later entries override earlier ones) so the last saved
mapping wins predictably, then perform the existing exact-match pass on
non-globs and the glob pass on entries derived from that deduplicated map (keep
using isGlobPattern, GLOB_META_RE and Bun.Glob for ordering and matching).

In `@README.md`:
- Around line 268-287: Update the "Per-path overrides" docs for the sessions
field to mention that session pattern keys are normalized with path.resolve(),
so any relative pattern (e.g., "**/my-project") is anchored to process.cwd()
rather than matching anywhere in the filesystem; state that users should prefer
absolute paths or ~/... keys (or be aware of the cwd-anchor behavior) and that
this normalization only applies to the per-directory strategy and does not
change precedence rules (exact > more specific glob).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 943af0fa-b080-4766-944b-9b2f8ee59517

📥 Commits

Reviewing files that changed from the base of the PR and between 7f78a2d and bd1a09d.

📒 Files selected for processing (3)
  • README.md
  • plugins/honcho/src/config.test.ts
  • plugins/honcho/src/config.ts

Comment thread plugins/honcho/src/config.ts
Comment thread README.md
relative paths in the global config are always a mistake — resolve()
would silently anchor them to process.cwd(), producing non-deterministic
matches. now only keys starting with / or ~ are considered.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
plugins/honcho/src/config.ts (1)

555-568: ⚠️ Potential issue | 🟠 Major

Equivalent normalized keys are still order-dependent.

Line 556 compares normalized paths, but the matcher still walks the original sessions entries. If the config contains multiple spellings of the same path or glob, the older spelling still wins, so a later save can remain invisible and deletes stay non-deterministic. Please deduplicate by normalized key before the exact/glob passes so the last write wins predictably.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/honcho/src/config.ts` around lines 555 - 568, The code still iterates
the original entries so different spellings of the same path/glob are
order-dependent; deduplicate by normalized key first so the last write wins.
Build a Map keyed by normalizePath(key) (use the same normalizePath/GLOB_META_RE
helpers) while iterating the original entries and always overwrite the Map entry
(map.set(normalizedKey, [key, name])) so later entries win; then replace uses of
entries with Array.from(map.values()) for the exact-match loop and for the
globEntries creation/sort so both exact and glob passes operate on deduplicated,
normalized keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/honcho/src/config.ts`:
- Around line 13-18: The session-key filter currently accepts any "~" prefixed
key but normalizePath only expands "~" and "~/...", causing keys like
"~worktree" to be left unresolved; update the predicate used where session keys
are filtered to match normalizePath's supported patterns by importing isAbsolute
from "path" and replacing the predicate with: key === "~" ||
key.startsWith("~/") || isAbsolute(key); reference the normalizePath function
and the session-key filter (the predicate that checks keys) when making this
change.

---

Duplicate comments:
In `@plugins/honcho/src/config.ts`:
- Around line 555-568: The code still iterates the original entries so different
spellings of the same path/glob are order-dependent; deduplicate by normalized
key first so the last write wins. Build a Map keyed by normalizePath(key) (use
the same normalizePath/GLOB_META_RE helpers) while iterating the original
entries and always overwrite the Map entry (map.set(normalizedKey, [key, name]))
so later entries win; then replace uses of entries with Array.from(map.values())
for the exact-match loop and for the globEntries creation/sort so both exact and
glob passes operate on deduplicated, normalized keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 77c0d08b-c9b3-498e-85b9-3b8f3e58d5d5

📥 Commits

Reviewing files that changed from the base of the PR and between bd1a09d and 2514529.

📒 Files selected for processing (2)
  • plugins/honcho/src/config.test.ts
  • plugins/honcho/src/config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/honcho/src/config.test.ts

Comment thread plugins/honcho/src/config.ts
…tterns

~worktree would pass startsWith("~") but normalizePath only expands
~/... and bare ~, so it'd fall through to resolve() and anchor to cwd.
use isAbsolute() instead, which also covers Windows paths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/honcho/src/config.test.ts (1)

117-126: Clarify comment: specificity is equal, length is the tie-breaker.

The test name says "** wins tie-break by length" but the comment only says "** is longer so it sorts first and wins." It might be worth noting explicitly that both patterns have equal specificity (same firstMeta position) since readers might wonder why * isn't considered more specific.

Suggested comment clarification
   test("** vs * specificity: ** wins tie-break by length for direct children", () => {
     const sessions = {
       "~/Code/*": "shallow",
       "~/Code/**": "deep",
     };
-    // Both match, ** is longer so it sorts first and wins
+    // Both have firstMeta at same position (equal specificity), ** is longer so it wins tie-break
     expect(matchSessionForPath(`${HOME}/Code/foo`, sessions)).toBe("deep");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/honcho/src/config.test.ts` around lines 117 - 126, Update the test
comment (and optionally the test name) to clarify that both patterns ("~/Code/*"
and "~/Code/**") have equal specificity (same firstMeta position) and therefore
the tie-breaker is length so the longer "**" sorts first; locate the comment
inside the test named "** vs * specificity: ** wins tie-break by length for
direct children" and change the inline comment to explicitly state "specificity
is equal, tie-break by pattern length, so ** wins."
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/honcho/src/config.test.ts`:
- Around line 144-148: The test uses process.cwd() which can be
environment-dependent and may accidentally match the "~/Code/foo" entry; update
the test that calls matchSessionForPath so it uses a synthetic,
guaranteed-nonmatching path (e.g., construct a path like `${HOME}/Code/not-this`
or another clearly distinct path) instead of process.cwd(), ensuring the
sessions map { "": "...", "relative/path": "...", "~worktree": "...",
"~/Code/foo": "real" } will not match and the expectation
matchSessionForPath(..., sessions) toBeNull() is stable.

---

Nitpick comments:
In `@plugins/honcho/src/config.test.ts`:
- Around line 117-126: Update the test comment (and optionally the test name) to
clarify that both patterns ("~/Code/*" and "~/Code/**") have equal specificity
(same firstMeta position) and therefore the tie-breaker is length so the longer
"**" sorts first; locate the comment inside the test named "** vs * specificity:
** wins tie-break by length for direct children" and change the inline comment
to explicitly state "specificity is equal, tie-break by pattern length, so **
wins."
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 711b7506-cfd8-431f-9b0d-546e1bca2535

📥 Commits

Reviewing files that changed from the base of the PR and between 2514529 and 9db610a.

📒 Files selected for processing (2)
  • plugins/honcho/src/config.test.ts
  • plugins/honcho/src/config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/honcho/src/config.ts

Comment thread plugins/honcho/src/config.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant