Skip to content

Workspace

Griffen Fargo edited this page Jun 4, 2026 · 3 revisions

Coco 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.

Start The Workstation

# 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 workspace

The 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.

Layout

┌────────────────────────────────────────────────────────────────────┐
│ 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 is path → 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.

Focus Model

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.

Keymap

The full keymap also lives behind ? inside the app.

Navigate

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)

Filter & sort

Keys Action
/ Filter the list by name or branch
s Cycle sort mode (recency → name → dirty)

Repos

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)

General

Keys Action
? Toggle the help overlay
esc Clear filter · close overlay · cancel prompt
q · ctrl+c Quit the workspace surface

Drill-In Loop

Pressing enter on a repo:

  1. Captures the current sort / tab / filter / cursor position
  2. chdirs into the repo
  3. Mounts coco ui for that repo (history view by default)
  4. When you quit ui, restores cwd and 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 & Filter

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 (requires gh authenticated; tab dims when not)

Adding & Removing Repos

Three ways to populate the workspace:

  1. workspace.roots in .coco.config.json — directories to walk. When unset (and no --root flag), the workspace scans the current working directory — so a bare coco / coco ws discovers repos wherever you launched it. Pin this (e.g. ["~/code"]) for a fixed tree regardless of where you run from.
  2. 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).
  3. Clone prompt (c) — clone a remote you don't have yet. A two-field prompt takes the URL (https://… or git@…) and the destination (pre-filled with <launch-dir>/<repo-name> derived from the URL, editable with tab-completion). Enter on the URL advances to the destination; Enter there clones. It refuses to overwrite an existing path, shows a Cloning… 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.

Configuration

In your .coco.config.json:

{
  "workspace": {
    "roots": ["~/code", "~/work"],
    "knownRepos": ["~/oss/coco"],
    "maxDepth": 3
  }
}
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).

Performance & Resilience

  • 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 list per-call timeout: 5s per repo, with AbortController killing 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 $HOME or sandbox never blocks boot.
  • gh unavailable: the PRs tab dims, the PR badge column hides, and a one-line status notifies the user once.

Troubleshooting

  • "No repositories discovered". By default the workspace scans your current directory — cd to a folder that contains git repos, set workspace.roots in config, pass --root <dir>, or press a to 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 workspace restarts the app on every keypress. tsx watch intercepts Return and Ctrl+C before forwarding to the child. Use yarn dev:tui workspace instead — same code, no watch wrapper.
  • Workspace looks slow on a network filesystem. Lower workspace.maxDepth, or move the workspace cache off the network mount with XDG_CACHE_HOME=/local/path.

Related

  • Coco UI — single-repo full-screen workstation. coco workspace drills into coco ui.
  • Configuration Overview — full schema for .coco.config.json including the workspace.* section.

Clone this wiki locally