List Command
Overview
The List Command provides a quick overview of all detected projects and their current issue distribution. It queries the project database and displays a formatted table showing project metadata alongside counts of issues in each status (todo, in_progress, done), enabling users to assess workload across the workspace at a glance.
How It Works
The command follows a simple query-and-display pattern:
Data Aggregation
The getProjectList() function:
- Fetches all projects from the
projectstable using Drizzle ORM - Calls
getIssueCountsForAllProjects(db)which executes a single SQL query:SELECT projectId, status, COUNT(*) FROM issues GROUP BY projectId, status - Maps the result rows into a nested
Record<projectId, Record<status, count>>structure - For each project, performs a JavaScript map lookup to retrieve its status counts
- Constructs a
ProjectListEntryfor each project containing:- name, slug, prefix, type — project metadata
- path — filesystem location
- totalIssues — count of all issues
- issueCounts — map of status → count (e.g.,
{ todo: 5, in_progress: 2, done: 12 })
Display Logic
The printProjectList() function:
- Calls
getProjectList()to fetch aggregated data - Checks for empty list; if no projects, displays helpful message:
"No projects detected. Run 'symphony scan' to detect projects." - Formats output using
formatTable()utility with columns:- Prefix — identifier prefix for ticket numbering (e.g., "SYM")
- Name — project name
- Type — project type (backend, frontend, fullstack, other)
- Todo, Active, Done — issue counts by status
- Total — sum of all issues
- Renders as aligned ASCII table with headers and separators
- Uses ANSI color codes and bold heading via
heading()utility
Status Mapping
The display maps internal issue statuses to user-friendly column names:
todo→ "Todo" columnin_progress→ "Active" columndone→ "Done" column- Other statuses are counted but not explicitly displayed (reserved for future extension)
Key Components
| File | Responsibility |
|---|---|
cli/index.ts (lines 74-79) | Command dispatcher; initializes DB and calls handler |
cli/commands/list.ts | Main implementation; getProjectList() (query logic), printProjectList() (display logic) |
cli/utils/output.ts | Terminal formatting utilities: formatTable(), heading(), dim() |
cli/utils/initCli.ts | Database initialization and configuration |
server/database/schema.ts | Drizzle ORM table definitions (projects, issues) |
Design Decisions
1. SQL-Level Aggregation with CLI-Level Display
- Counts are computed via SQL
COUNT(*) GROUP BYat the database level; JavaScript performs only map lookups and a sum fortotalIssues - Trade-off: Efficient aggregation in DB, but display layer still selects which statuses to show (todo/in_progress/done), keeping presentation flexible
2. Status-Agnostic Data Collection
getProjectList()collects ALL statuses into a map, not just todo/in_progress/done- Allows future column additions without code changes; display layer picks which to show
- Trade-off: More memory usage for projects with many custom statuses, but rare in practice
3. Table-Based Display Format
- Uses aligned ASCII table (formatTable utility) rather than JSON or CSV
- Optimized for terminal reading: fixed-width columns, visual hierarchy
- Trade-off: Not machine-parseable; if CLI scripting is needed, would require JSON output flag
4. Empty State Messaging
- When no projects found, guides user to
symphony scancommand - Prevents confusion: empty table vs. "nothing to show"
5. Batch Query for All Projects
- A single SQL query fetches counts for all projects grouped by
projectIdandstatus, resulting in exactly 2 DB queries total (projects + issue counts) regardless of project count - Trade-off: Fetches counts for all projects even if only a subset would be displayed; acceptable given typical project counts (<50) and avoids N+1 round-trips
Related Docs
- Status Command — Shows orchestrator runtime status and agent activity
- Scan Command — Detects and syncs projects into the database
- Kanban Board — Web UI equivalent showing projects and issues
Known Gaps
- No sorting: Projects displayed in database order; no flag for sort by name/type/issue-count
- No filtering: Cannot display subset of projects (e.g., by type); full list always shown
- Status display: Hardcoded to show todo/in_progress/done; custom statuses not displayed
- Width handling: No detection of terminal width; table may overflow narrow terminals
- Project count: No pagination or summary count of total projects (could add at bottom)