Skip to content

Brainstorm: Project grouping view #5

Open

Description

@rhuss

Brainstorm: Project Grouping View

Date: 2026-07-02
Status: active

Problem Framing

With 850+ sessions, the flat chronological list makes it hard to find sessions for a specific project. PR #2 implemented project grouping but bundled it with archiving, titles, forking, and move-to-project. We want to extract just the grouping concept, redesigned to fit the existing minimalist UI: off by default, toggle-able, and non-disruptive to the current search/filter workflow.

Approaches Considered

A: Virtual row model (chosen)

Insert ProjectHeader entries into the existing flat display_entries Vec. Headers are first-class display entries alongside session entries. Grouping is a view-layer concern; filter/search logic stays untouched. Navigation, scrolling, and click targeting work naturally because header rows have concrete positions in the list.

  • Pros: Minimal change to existing architecture. Filter/search code unchanged. Easy to toggle since it just rebuilds display entries.
  • Cons: Arrow key navigation must skip/stop at headers. Scroll offset calculations need to account for header rows.

B: Separate view state

Two independent display entry lists (flat and grouped), toggled between. Each with its own rendering and navigation logic.

  • Pros: Clean separation, each mode is self-contained.
  • Cons: Duplicates rendering and navigation logic. Filter changes need to update both models. Code drift risk.

C: Render-time grouping only

No data model changes. Detect project boundaries during rendering and insert header lines on the fly. Collapse state in a separate HashSet<String>.

  • Pros: Zero data model changes. Purely cosmetic.
  • Cons: Cursor position doesn't map 1:1 to display rows. Mouse click targeting and scroll calculations become complex.

Decision

Approach A: Virtual row model. Keeps the existing architecture intact while making headers first-class entries.

Key Requirements

  • Toggle: Ctrl-T switches between flat (default) and grouped view
  • Header style: Chevron + project name + relative time of most recent session
    • ▶ cc-session 2 hours ago (collapsed)
    • ▼ cc-session 2 hours ago (expanded, sessions indented below)
  • Default state: All groups collapsed when no filter/search is active (compact project overview)
  • Filter/search active: Matching groups auto-expand, empty groups hidden
  • Expand/collapse: Enter or mouse click on a project header toggles. Enter on a session row opens the conversation (unchanged)
  • Content search: Works identically in both modes. Results appear under their project groups, auto-expanding those groups
  • Ordering: Projects ordered by most recent session timestamp. Sessions within a project ordered newest-first
  • Data model: DisplayEntry gets a ProjectHeader variant. rebuild_display_entries handles insertion/grouping

Open Questions

  • Should the grouped/flat preference persist across restarts (e.g., in a config file), or always start flat?
  • Should Left/Right arrow keys also collapse/expand groups (in addition to Enter), or keep them free for future use?
  • How should the session count be shown in the border title? Currently shows (filtered/total). In grouped mode, should it also show project count?

Activity

  1. mabulgu commented on Jul 2, 2026

    @mabulgu

    Nice write-up @rhuss. A few thoughts on the approaches:

    The virtual row model (Approach A) is close to what PR #2 already does with TreeRow, but I see the appeal of making headers first-class entries in display_entries instead of a separate enum. It would simplify navigation since everything lives in one flat list. The current TreeRow + project_groups approach works but does add complexity around scroll offset and cursor mapping between the two models.

    Some things I'd push back on or want to discuss:

    Default collapsed vs expanded: With 850+ sessions across many projects, all-collapsed gives a nice compact overview. But if someone has only 5-10 projects, collapsed-by-default adds an extra click every time. Maybe collapsed-by-default when project count > N (say 10), expanded otherwise?

    Ctrl-T vs Tab: Tab is more discoverable and standard for toggling views in TUI apps (like htop, lazygit). Ctrl-T might conflict with terminal tab management in some setups. What's the reasoning for Ctrl-T specifically?

    Unbundling from PR #2: I'm fine with extracting grouping into its own thing if that's cleaner. But archiving, move-to-project, and titles are independent features that don't depend on grouping. Should those stay in PR #2 as a separate scope, or do you want those split into individual PRs too?

    On the open questions: I'd start flat on every launch (no persistence) and support both Enter and Left/Right for collapse/expand since Left/Right feels natural in tree navigation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions