Skip to content

feat: default sessions list to cwd project + fix sqlite timestamps#7

Open
buihongduc132 wants to merge 9 commits intoshuv1337:masterfrom
buihongduc132:master
Open

feat: default sessions list to cwd project + fix sqlite timestamps#7
buihongduc132 wants to merge 9 commits intoshuv1337:masterfrom
buihongduc132:master

Conversation

@buihongduc132
Copy link

@buihongduc132 buihongduc132 commented Feb 20, 2026

Summary

This PR implements cwd-based filtering for sessions list and fixes a critical bug where SQLite timestamps weren't displaying.

Changes

Feature: CWD-based session filtering

  • sessions list now defaults to showing sessions for the current working directory's project
  • Added --global flag to list all sessions (previous default behavior)
  • Added inferProjectFromCwd() helper with support for:
    • Nested projects (deepest match wins)
    • Ambiguous matches (error with helpful message)
    • Symlink resolution
    • Clear error messages when no project found

Bug fix: SQLite timestamp display

  • Fixed timestamps showing "-" in SQLite mode
  • Added time_created and time_updated to column name fallback list
  • These are the actual column names in the SQLite schema

Tests

  • Added 10 TDD tests covering:
    • Base cwd filtering behavior
    • --global flag functionality
    • Edge cases (nested projects, ambiguous matches, symlinks)
    • --search + cwd intersection semantics
    • Conflict validation (--global + --project)
  • Updated existing tests to use --global flag where needed
  • All cwd filtering tests pass

Verification

  • ✅ TypeScript type checking passes
  • ✅ All 10 new TDD tests pass
  • ✅ Manual testing confirms correct behavior with timestamps
  • ✅ No credential leaks detected
  • ✅ Follows contribution guidelines (typecheck before submit)

Example usage

# Default: list sessions for current directory's project
cd ~/my-project
opencode-manager sessions list --experimental-sqlite

# List all sessions globally
opencode-manager sessions list --global --experimental-sqlite

# Error when not in a project directory
cd /tmp
opencode-manager sessions list --experimental-sqlite
# Error: No project found for current directory: /tmp
# Use --global to list all sessions, or --project <id> to specify a project.

Commits

  • 62c69ed - test: expand CLI coverage for sqlite rename/copy and root/TUI behavior
  • 3cecb34 - feat: default sessions list to cwd project, fix sqlite timestamps
  • c7a55a1 - fix: add --global flag to tests after cwd filtering implementation

Greptile Summary

This PR implements cwd-based filtering for sessions list and fixes SQLite timestamp display. The sessions list command now defaults to showing sessions for the current directory's project, with a --global flag to list all sessions.

Key changes:

  • Added inferProjectFromCwd() helper that finds projects matching the current working directory (deepest match wins)
  • Fixed SQLite timestamp bug by adding time_created and time_updated to column fallback list
  • Added --global flag to list all sessions (previous default behavior)
  • Added comprehensive test coverage for cwd filtering edge cases

Issues found:

  • Windows compatibility: Path matching uses hardcoded / separator instead of path.sep (lines 253, 255 in sessions.ts)
  • Test documentation: Symlink test description is misleading - it claims the code "resolves symlinks" but actually relies on POSIX getcwd() behavior
  • Missing test coverage: Reverse symlink scenario not tested (project registered with symlink path)

Confidence Score: 3/5

  • Safe to merge with minor cross-platform compatibility fixes needed
  • The feature implementation is solid with good test coverage, but has Windows path compatibility issues that need fixing. The SQLite timestamp fix is straightforward and correct. No security concerns.
  • Pay close attention to src/cli/commands/sessions.ts - fix Windows path separator issues before merging

Important Files Changed

Filename Overview
src/cli/commands/sessions.ts Added cwd-based filtering with inferProjectFromCwd() helper, but has symlink handling bug and Windows path compatibility issue
src/lib/opencode-data-sqlite.ts Fixed timestamp display by adding time_created and time_updated to column fallback list
tests/cli/commands/sessions-cwd-filter.test.ts New comprehensive test suite for cwd filtering, but symlink test has misleading description and doesn't test the reverse scenario

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Start[sessions list command] --> CheckFlags{Flags provided?}
    
    CheckFlags -->|--global| Global[List all sessions]
    CheckFlags -->|--project &lt;id&gt;| Project[Filter by project ID]
    CheckFlags -->|neither| InferCwd[inferProjectFromCwd]
    
    InferCwd --> LoadProjects[Load all projects]
    LoadProjects --> GetCwd[Get process.cwd]
    GetCwd --> FindCandidates{Find matching projects}
    
    FindCandidates -->|No matches| ErrorNoProject[Error: No project found]
    FindCandidates -->|One match| UseDeepest[Use deepest match]
    FindCandidates -->|Multiple at same depth| ErrorAmbiguous[Error: Ambiguous match]
    
    UseDeepest --> FilterSessions[Filter sessions by project]
    Project --> FilterSessions
    Global --> LoadAllSessions[Load all sessions]
    
    FilterSessions --> ApplySearch{--search provided?}
    LoadAllSessions --> ApplySearch
    
    ApplySearch -->|Yes| FuzzySearch[Apply fuzzy search]
    ApplySearch -->|No| Output[Output sessions]
    FuzzySearch --> Output
Loading

Last reviewed commit: c7a55a1

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

buihongduc132 added 3 commits February 21, 2026 02:56
- Add --global flag to list all sessions (default: cwd project only)
- Add inferProjectFromCwd() with nested project support
- Validate --global and --project mutual exclusion
- Fix SQLite timestamp display by adding time_created/time_updated to column fallbacks
- Add 10 tests covering cwd filtering, nested projects, ambiguous matches, symlinks
- Update tests to use --global flag for listing all sessions
- Preserves original test behavior after default changed to cwd filtering
- All cwd filtering tests still pass
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

6 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

for (const project of projects) {
const worktree = project.worktree
// Check if cwd is inside or equal to worktree
if (cwd === worktree || cwd.startsWith(worktree + "/")) {
Copy link

Choose a reason for hiding this comment

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

hardcoded / separator won't work on Windows - use path.sep instead

Suggested change
if (cwd === worktree || cwd.startsWith(worktree + "/")) {
if (cwd === worktree || cwd.startsWith(worktree + path.sep)) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/commands/sessions.ts
Line: 253

Comment:
hardcoded `/` separator won't work on Windows - use `path.sep` instead

```suggestion
    if (cwd === worktree || cwd.startsWith(worktree + path.sep)) {
```

How can I resolve this? If you propose a fix, please make it concise.

// Check if cwd is inside or equal to worktree
if (cwd === worktree || cwd.startsWith(worktree + "/")) {
// Depth is the number of path segments in worktree
const depth = worktree.split("/").length
Copy link

Choose a reason for hiding this comment

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

hardcoded / separator won't work on Windows - use path.sep instead

Suggested change
const depth = worktree.split("/").length
const depth = worktree.split(path.sep).length
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/commands/sessions.ts
Line: 255

Comment:
hardcoded `/` separator won't work on Windows - use `path.sep` instead

```suggestion
      const depth = worktree.split(path.sep).length
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +208 to +235
it("resolves symlinks when matching cwd to projects", async () => {
const { tempDir, storeRoot, cleanup } = await createTempStore();
try {
const realDir = join(tempDir, "worktrees", "real");
const linkDir = join(tempDir, "worktrees", "link");
await fs.mkdir(realDir, { recursive: true });
await fs.symlink(realDir, linkDir);

await writeProject(storeRoot, "proj_real", realDir);
await writeSession(storeRoot, "proj_real", "session_real", realDir, "Realpath match");

const shellPromise = $`bun ${CLI_PATH} sessions list --root ${storeRoot} --format json`.cwd(linkDir).quiet();
const result = await Promise.race([
shellPromise,
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error("CLI command timed out after 30s")), 30000)
),
]);
const output = result.stdout.toString();
const parsed = JSON.parse(output);

expect(parsed.ok).toBe(true);
expect(parsed.data.length).toBe(1);
expect(parsed.data[0].sessionId).toBe("session_real");
} finally {
await cleanup();
}
});
Copy link

Choose a reason for hiding this comment

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

test description is misleading - the code doesn't explicitly resolve symlinks. It works because process.cwd() automatically returns the canonical path (POSIX behavior).

Also missing reverse scenario: what if a project is registered with a symlink path but user cds into it? That would fail because stored paths aren't canonicalized.

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/cli/commands/sessions-cwd-filter.test.ts
Line: 208-235

Comment:
test description is misleading - the code doesn't explicitly resolve symlinks. It works because `process.cwd()` automatically returns the canonical path (POSIX behavior). 

Also missing reverse scenario: what if a project is registered with a symlink path but user `cd`s into it? That would fail because stored paths aren't canonicalized.

How can I resolve this? If you propose a fix, please make it concise.

buihongduc132 added 6 commits February 21, 2026 05:45
- Add tests for project registered via symlink path
- process.cwd() resolves symlinks, but worktree paths don't
- Bug: project registered via symlink won't match when running from real path
- Also add tests for path prefix collision and trailing slashes
- Use fs.realpath() to resolve worktree paths before comparison
- process.cwd() already resolves symlinks, so worktree must too
- Handle case where realpath fails (non-existent path)
- Normalize trailing slashes for consistent comparison
- Fixes: project registered via symlink wouldn't match when running from real path
- Compare latest session timestamps between SQLite and JSONL stores
- Prefer SQLite when it has fresher data than JSONL
- Fall back to JSONL when SQLite unavailable or older
- Add helper functions to scan both stores for latest timestamps
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