-
-
Notifications
You must be signed in to change notification settings - Fork 0
Workspace
coco workspace (alias: coco ws) is a multi-repo overview TUI. It scans your configured root directories, surfaces each repository's branch / dirty / ahead-behind / last-commit / open-PR data in a single sortable table, and lets you drill into any one as a full coco ui session — with the cursor returning to the same repo on exit.
If coco ui is the "deep view" of a single repository, coco workspace is the "wide view" across all of them. Use it when you switch context between 3–10 projects in a typical week and want one screen to see what needs attention.
# Default: scan the current directory (or workspace.roots, if configured)
coco workspace
# Alias
coco ws
# Override the root list inline (repeatable)
coco workspace --root ~/code --root ~/work
# Cap the recursion depth into each root (default 3)
coco workspace --max-depth 2
# Force a theme preset
coco workspace --theme catppuccin
NO_COLOR=1 coco workspaceThe discovery walks each root, identifies git working trees (regular .git/ dirs, worktree pointer files, submodules), prunes node_modules / dist / build / hidden dirs, and stops descending the moment a directory is identified as a repo.
On a non-TTY (CI logs, piped output), coco workspace prints a plain repo list and exits.
┌────────────────────────────────────────────────────────────────────┐
│ coco · workspace · ~/code · 64/64 repos · sort: Recent · [List] │
├──────┬─────────────────────────────────────────────────────────────┤
│ Tabs │ Workspace 64 visible │
│ │ REPO BRANCH STATUS LAST SUBJECT PATH │
│ │ │
│ ○ All 64 │ ↵ coco main ●2 ↓3 2d feat: thing ~/co… │
│ ● Dirty 3│ github-prof. main 2d Add localpr… ~/co… │
│ ↓ Behind 12│ BinWars main 3d Merge pull … ~/co… │
│ ⊙ PRs 5│ … │
├──────┴─────────────────────────────────────────────────────────────┤
│ s sort · / filter · r/R refresh · a add · d remove · ? help · q │
│ │
└────────────────────────────────────────────────────────────────────┘
-
Header: chip-style identity row —
coco · workspace · <roots> · N/M repos · sort: <mode> · [<focus>]. Identity + focus chips render in the accent color; chrome stays muted. -
Sidebar (
Tabs): four filter tabs — All / Dirty / Behind / PRs — each with a glyph (◯ ● ↓ ⊙) and a count. Below 100 columns the sidebar collapses to a 4-cell rail showing just the glyphs; tab focus expands it back. -
Main panel (
Workspace): the repo table. Columns adapt to the terminal width — drop priority ispath → subject → date → branch → status(status is kept longest because it's the most actionable signal). -
Footer: keymap hint on the first line, status line below (refreshed on workflow outcomes —
Refreshed 64 repos.,Added /Users/me/code/x.).
When discovery is in flight, every row that's still waiting for its gh pr list call gets a Braille spinner (⠋ ⠙ ⠹) in the status cell. The spinner drops as each row's data lands.
Two focusable panels mirror coco ui:
| Focus | Keys | What they do |
|---|---|---|
List (default) |
j / k / ↑ / ↓
|
Move the cursor through repos |
g / G
|
Jump to top / bottom | |
enter |
Drill into the cursored repo (opens coco ui) |
|
h / ←
|
Jump focus to the sidebar | |
Tabs |
j / k
|
Cycle the active tab |
enter / l / →
|
Jump focus back to the list | |
tab / shift-tab (any) |
Toggle focus between sidebar and list |
Modal focuses (filter, add-repo, confirm-delete) own the input until dismissed with esc.
The full keymap also lives behind ? inside the app.
| Keys | Action |
|---|---|
j / k / ↑ / ↓
|
Move cursor (list) · cycle tab (sidebar) |
tab / shift-tab
|
Toggle focus between sidebar and list |
h / ←
|
Jump focus to the sidebar |
l / →
|
Jump focus to the list |
g / G
|
Jump to top / bottom of the list |
enter |
Drill into the cursored repo (coco ui) |
| Keys | Action |
|---|---|
/ |
Filter the list by name or branch |
s |
Cycle sort mode (recency → name → dirty) |
| Keys | Action |
|---|---|
r |
Refresh all repos (discovery + PR counts) |
R |
Refresh just the cursored repo (faster) |
a |
Add a repo via path prompt (tab-completes) |
c |
Clone a remote repo (URL → destination prompt; adds it on success) |
d |
Remove the cursored repo from the known-repos store (y-confirm) |
| Keys | Action |
|---|---|
? |
Toggle the help overlay |
esc |
Clear filter · close overlay · cancel prompt |
q · ctrl+c
|
Quit the workspace surface |
Pressing enter on a repo:
- Captures the current sort / tab / filter / cursor position
-
chdirs into the repo - Mounts
coco uifor that repo (history view by default) - When you quit
ui, restorescwdand re-mounts the workspace surface with the cursor anchored back on the same repo
The ↵ glyph in the cursor column is a hint that pressing enter will drill in — the cursored row is the one that gets opened.
Sort modes (cycled with s):
- Recency (default): newest commit first. Best for "what have I touched this week?"
- Name: alphabetical. Best for memory / muscle-memory navigation.
- Dirty: most working-tree changes first. Best for "what needs commits before EOD?"
Filter (/): case-insensitive substring match against repo name, branch, and path. Live-updates as you type. Press enter to commit, esc to cancel and restore the cursor to where it was before filtering.
Sidebar tabs filter on top of the sort + free-text filter:
-
◯ All(default) — every repo -
● Dirty— repos with uncommitted changes -
↓ Behind— repos behind their upstream -
⊙ PRs— repos with open pull requests (requiresghauthenticated; tab dims when not)
Three ways to populate the workspace:
-
workspace.rootsin.coco.config.json— directories to walk. When unset (and no--rootflag), the workspace scans the current working directory — so a barecoco/coco wsdiscovers repos wherever you launched it. Pin this (e.g.["~/code"]) for a fixed tree regardless of where you run from. -
Add-repo prompt (
a) — type a path, tab to complete. Supports~/prefix and walks the filesystem to suggest matching directories. Validates the path is a git working tree before adding. Saved per-user to~/.cache/coco/workspace/known-repos.json(separate from your config file so the tool doesn't mutate something you might be version-controlling). -
Clone prompt (
c) — clone a remote you don't have yet. A two-field prompt takes the URL (https://…orgit@…) and the destination (pre-filled with<launch-dir>/<repo-name>derived from the URL, editable with tab-completion).Enteron the URL advances to the destination;Enterthere clones. It refuses to overwrite an existing path, shows aCloning…state while it runs, and on success drops the new repo into the list with the cursor on it — same as the add flow.
Remove an added repo with d (y-confirm). Only entries in the known-repos store can be removed via the prompt — repos discovered via workspace.roots get a status hint pointing you at the config.
In your .coco.config.json:
| Field | Default | Description |
|---|---|---|
workspace.roots |
current directory (cwd) |
Directories the discovery walks. Defaults to wherever you launched coco when unset; set it to pin a fixed tree. |
workspace.knownRepos |
[] |
Explicit repo paths to include regardless of discovery. Merged with the per-user add-repo store. |
workspace.maxDepth |
3 |
Cap on recursion depth into each root. |
Per-launch state — sort mode, sidebar tab, filter text — persists to ~/.cache/coco/workspace/preferences.<root-hash>.json so reopening the workspace lands where you left it. Two different workspace.roots configurations keep separate preferences (no collision).
- Three-stage boot: paint cached repo list immediately → mount Ink → run fresh discovery + PR fetch in the background. No "loading…" spinner on cold start once you've used it once.
-
gh pr listper-call timeout: 5s per repo, withAbortControllerkilling the child process if it hangs. One slow repo can't stall the rest of the overview. - Concurrency-bounded: discovery and PR fetches run with at most 4 (PR) / 8 (discovery) workers in flight.
-
Best-effort persistence: every cache / preference / known-repos write swallows errors. A read-only
$HOMEor sandbox never blocks boot. -
ghunavailable: the PRs tab dims, the PR badge column hides, and a one-line status notifies the user once.
-
"No repositories discovered". By default the workspace scans your current directory —
cdto a folder that contains git repos, setworkspace.rootsin config, pass--root <dir>, or pressato add one by path. Common cause: launching from a directory with no git repos beneath it. -
PR counts don't show up. Check
gh auth status. If unauthenticated, the PRs tab dims and the per-row PR badge stays hidden until you log in. -
yarn dev workspacerestarts the app on every keypress.tsx watchintercepts Return and Ctrl+C before forwarding to the child. Useyarn dev:tui workspaceinstead — same code, no watch wrapper. -
Workspace looks slow on a network filesystem. Lower
workspace.maxDepth, or move the workspace cache off the network mount withXDG_CACHE_HOME=/local/path.
-
Coco UI — single-repo full-screen workstation.
coco workspacedrills intococo ui. -
Configuration Overview — full schema for
.coco.config.jsonincluding theworkspace.*section.
{ "workspace": { "roots": ["~/code", "~/work"], "knownRepos": ["~/oss/coco"], "maxDepth": 3 } }