Skip to content

Releases: gfargo/coco

Release 0.72.3

18 Jun 05:02

Choose a tag to compare

What's Changed

0.72.3 is a robustness patch — the "coco fails gracefully now" release. A pre-launch sweep of the first-run experience turned up three rough edges where a small mistake (a typo'd config, an unexpected error, a Ctrl-C) produced a raw stack trace or a scary message instead of something actionable. All three are fixed. The rest is dependency upkeep and contributor-facing repo polish. No breaking changes — every command and the coco ui workstation behave exactly as before.

Highlights — graceful failures

A malformed .coco.json no longer crashes coco

A single JSON typo in your project config — a stray comma, an unquoted key — used to crash coco with a raw SyntaxError and stack trace. Worse, config loads early, so the crash bypassed every error handler and dumped a Node trace before the command even started. coco now warns with the file, the parse error, and how to fix it, then falls back to your other config sources (defaults / global / git / env) so the tool still runs (#1301).

[coco] Warning: could not parse .coco.json as JSON — ignoring it.
  Parse error: Expected property name or '}' in JSON at position 2 (line 1 column 3)
  Fix the file's syntax (or run `coco init` to regenerate it). Other config sources still apply.

No more raw stack traces — and a faster path to reporting bugs

The top-level error handler printed the raw error object (full stack) for anything that slipped past a command's own handling. It now prints a short, actionable message with a "report a bug" link, and keeps the full stack behind --verbose / COCO_DEBUG so a plain run stays readable while a bug report can still include the trace (#1299). Intentional exits (e.g. the "missing API key" guidance) pass through untouched.

Cancelling a prompt exits cleanly

Pressing Ctrl-C out of coco init (or running it without a TTY) surfaced as Failed to execute command / Error: User force closed the prompt. Cancelling is a normal action, not a crash — coco now prints a tidy Cancelled. and exits with the conventional interrupt code, for every interactive command (#1302).

Under the hood

  • Build: restored type compatibility after the @langchain/core bump. The 1.1.48 update changed StructuredOutputParser's inferred types (Zod 4 internals), breaking the commit-draft chain's typecheck; brought the one strict call site in line with the existing parser call-site convention (#1300). The runtime is unchanged.
  • Dependencies: ink 7.0.5 → 7.0.6 (#1260), ajv 8.18.0 → 8.20.0 (#1262), @langchain/community 1.1.28 → 1.1.29 (#1258), @langchain/core 1.1.48 → 1.1.49 (#1261), @babel/core 7.28.0 → 7.29.7 (#1298), and @types/node (dev) 25.6.2 → 25.9.3 (#1259).
  • Repo: issue forms, a PR template, and a tighter CONTRIBUTING (#1256) — structured bug-report / feature-request forms so incoming reports land with the context needed to act on them.

Breaking Changes

None. 0.72.3 is behavior-preserving: the three fixes only change how coco behaves when something goes wrong (turning crashes and raw errors into actionable messages), and the dependency bumps are routine. Existing configs and every TUI flow are unchanged.

Full Changelog: 0.72.2...0.72.3

Release 0.72.2

17 Jun 17:43

Choose a tag to compare

What's Changed

0.72.2 is a small maintenance release. It fixes a workstation chrome glitch (a "loading context" indicator that never cleared) and completes the runtime/app.ts decomposition (#1237) by migrating every workstation surface onto the runtime context.

Highlights

Fix: the "loading context" indicator no longer sticks

On launch, the workstation header could show a permanent "loading context" hint — even on a fully-loaded, clean repo — because three lazily-loaded context slices (the issue list, the PR triage list, and the full PR overview) were seeded as "loading" but only fetched when you actually open their view. The header's "is anything still loading?" check therefore never cleared.

They're now seeded idle at boot, alongside the PR overview that was already handled this way (#1297). The indicator clears once the initial context finishes loading, and still flashes briefly — correctly — only while you're entering the issues / PR / PR-triage views.

Under the hood

The runtime/app.ts decomposition is fully complete (#1237)

0.72.1 finished moving the runtime's useState / useEffect clusters into dedicated hooks. 0.72.2 finishes the other half: the surface-context migration. Every workstation surface — all 19 main-panel views plus the detail/inspector cluster — now reads its state / theme / context / loading-status / dimensions from a single LogInkRuntimeContext instead of having those values threaded through app.ts → dispatcher → render*Surface as positional props.

The payoff is contributor-facing: adding a surface-wide value is now a one-line context addition rather than a change threaded through every surface signature. It's a pure refactor — the surfaces' render logic is untouched, so output is byte-identical (the 68-snapshot suite is unchanged across all five PRs).

  • Foundation: grew the runtime context and added the useSurfaceRenderContext / defineSurfaceComponent helpers (#1292).
  • Migrated in batches by shape: zero-extra surfaces (#1293), single-extra surfaces (#1294), the history surface (#1295), and the detail-panel cluster (#1296).
  • Each PR was validated with tsc + the workstation render-snapshot suite + eslint + a full build, then independently reviewed for behavior preservation.

With this, #1237 is fully closedruntime/app.ts is a thin composition root.

Breaking Changes

None. 0.72.2 is behavior-preserving: the surface-context migration is internal (zero render-snapshot diffs), and the one fix only stops a stuck loading indicator. Existing configs and every TUI flow are unchanged.

Full Changelog: 0.72.1...0.72.2

Release 0.72.1

17 Jun 12:46

Choose a tag to compare

What's Changed

0.72.1 is a polish-and-foundation release. It smooths the local Ollama path so a fully-local setup works on the first try, hardens model validation and grammar downloads, and finishes the workstation runtime decomposition (#1237) — the internal cleanup that 0.72.0 started. The only behavior change is a small short-flag cleanup (-t / -c); see Breaking Changes. Everything else — every command and the coco ui workstation — works exactly as before.

Highlights

Local Ollama, smoother out of the box

Running coco fully local against Ollama no longer assumes you've already got everything wired up — coco now meets you where you are and tells you exactly what's missing.

  • coco init handles a first-run Ollama setup gracefully instead of failing when the daemon or a model isn't ready yet (#1264).
  • coco doctor runs live checks against the Ollama daemon and your installed models, so a misconfigured local setup is diagnosable in one command (#1265).
  • When a configured Ollama model isn't pulled yet, coco prints an actionable hint (the exact ollama pull to run) rather than a raw error (#1266).

Sturdier model validation & grammar downloads

  • Per-provider model validity. Model names are now validated against the specific provider, backed by a shared map of deprecated models — so a typo or a retired model is caught early with a clear message instead of failing mid-request (#1272).
  • Tree-sitter grammar mirror fallback. Syntax-highlight grammar downloads fall back to a mirror when the primary source is unreachable, so first-run highlighting setup is more reliable on flaky networks (#1271).

The workstation runtime decomposition is finished (#1237)

0.72.0 decomposed the bulk of the workstation runtime; 0.72.1 finishes the job. The remaining useState/useEffect clusters moved into dedicated, individually-tested hooks — a behavior-preserving refactor (zero render-snapshot diffs) that leaves runtime/app.ts a thin composition root: it wires hooks together and renders.

  • This phase: useState 28 → 3 (only the core reducer state and the theme-picker preview remain), app.ts trimmed to ~1,711 LOC. Together with 0.72.0, the runtime is down from its ~5,368-LOC peak.
  • Extracted hooks: commit-detail, file-preview, diff syntax-highlight, bisect-candidate, history pagination, first-run onboarding, resume repaint, the worktree/stash/compare diff state, and the foundational repo-stack runtimes (#1273, #1275, #1276, #1277, #1278, #1279, #1280, #1281, #1282).
  • New automated coverage for the submodule drill-in/out path (#1283).

Notable

  • Short-flag aliases reconciled (#1268, fixes #1245 / #1246). Each short letter now resolves to one flag across commands: -t--tag (changelog) and -c--conventional (commit). The CommitOptions interface was also completed (append / appendTicket / additional are now typed, no more loose casts). See Breaking Changes for the flag change.
  • Workstation: no more stuck "Loading…" in the inspector. Four lazy diff/detail loaders could leave their loading flag stuck true if the selection cleared mid-fetch — surfacing as a permanent "Loading commit details…" until the next selection. Fixed by resetting the flag on the loader bail (#1284).
  • coco init now persists the recommended .coco.json config. Choosing the recommended .coco.json project-config format previously wrote nothing while still reporting success (only the legacy .coco.config.json was handled). Both JSON formats are now written, with a defensive guard so an unhandled format fails loudly instead of silently (#1285).
  • coco init model picker: corrected the o-series ids. The OpenAI model list had o3 / o3-mini mistyped as 03 / 03-mini (digit zero) and a duplicate gpt-4.1, so the picker offered non-existent ids and validation didn't recognize the real ones. Fixed and deduped (#1286).
  • Docs: the README now leads with a coco commit hero GIF pointed at a real code change (#1267).

Under the hood

  • LangChain internals: dropped a dead llm param and tightened createSchemaParser's return type (#1269); unified the transient "is-retryable-error" notion into one shared helper (#1270).
  • Flag-alias guard broadened to assert no within-command short-flag collision across all command configs, and redundant CommitOptions casts dropped (#1287).
  • The decomposition above is contributor-facing only: each cluster was lifted verbatim into a hook called at its original slot (preserving React hook order), validated per-PR with tsc + the workstation render-snapshot suite + eslint + a full build.

Breaking Changes

  • Two short-flag aliases were removed to end conflicting letters (#1268):

    • coco commit -t no longer resolves — use the long form --appendTicket (-t is now --tag on coco changelog).
    • coco log -c no longer resolves — use the long form --commit (-c is now --conventional on coco commit).

    The long flags are unchanged; only the ambiguous short letters moved. A flagAliasConsistency.test.ts guard prevents regressions.

Otherwise behavior-preserving — the workstation runtime decomposition is internal (zero render-snapshot diffs), and existing configs and TUI flows are unchanged.

Full Changelog: 0.72.0...0.72.1

Release 0.72.0

14 Jun 01:03

Choose a tag to compare

What's Changed

0.72.0 is primarily an under-the-hood release. There are no new commands, flags, or changes to how the CLI behaves — the coco ui workstation looks and behaves exactly as it did in 0.71.0. The headline work is a large, behavior-preserving refactor that breaks the workstation's monolithic runtime component into focused, testable pieces. Alongside it, this release makes coco easier to install (Homebrew + a curl one-liner) and adds a release-safety guard. It's a drop-in upgrade.

Highlights

The workstation runtime, decomposed

src/workstation/runtime/app.ts — the single React component behind coco ui — had grown to 5,368 lines. This release decomposes it into 26 focused hook modules, landed across 18 separately-reviewed, individually-green pull requests:

  • app.ts: 5,368 → 1,804 lines (−66%)
  • useEffect 41 → 15, useCallback ~41 → 6
  • Each cluster — filtered lists, status-surface data, idle-tip / spinner / auto-dismiss timers, repo persistence, the on-demand detail/diff/context hydration loaders, cursor-sync + load-more pagination, and the whole action layer (staging, compose/editor, commit-split, AI-draft, pull-request, yank/changelog, and the ~1,200-line workflow dispatcher) — now lives in its own use* hook with its own focused unit tests.

Why it matters

  • Maintainability: the runtime is now a thin component that wires together named, single-responsibility hooks instead of one 5k-line file. Future workstation features land in (or next to) a small hook rather than the monolith.
  • Testability: the pure cores of each cluster (filter logic, spinner/idle cadence, hydration guards, pagination math) are now unit-tested in isolation.
  • A foundation for less prop-drilling: a LogInkRuntimeContext provider (installed in an earlier release) now has its first real consumer — the header surface reads state / context / theme / layout from context instead of receiving them as positional props. Other surfaces can migrate onto it incrementally.

Easier to install

npm install -g git-coco is no longer the only way in. 0.72.0 adds two lower-friction paths (#1250):

  • Homebrew — the zero-prerequisite path. Homebrew pulls in Node as a dependency, so you don't need a Node toolchain first:

    brew install gfargo/tap/coco
  • curl installer — checks for Node 22+, installs git-coco with whatever package manager you have (npm/pnpm/yarn), and prints next steps. Pin a version with COCO_VERSION:

    curl -fsSL https://coco.griffen.codes/install.sh | sh

The README now leads with the core flow — git add . && coco commit across seven providers including fully-local Ollama — with the workstation reframed as the "grows into" payoff (#1251).

Notable

  • Behavior-preserving by construction. Every effect and callback was moved byte-for-byte — bodies and dependency arrays unchanged, hook call-order preserved, multi-region clusters split into position-preserving hooks rather than reordered. The on-demand hydration loaders keep their frame-tagging and cancellation semantics exactly; the AI-draft / pull-request abort handles and mountedRef unmount guards are reproduced verbatim.
  • Verified. The full suite (3,471 tests across 276 suites) and the type-checker pass on every step, across the Node 22/24 × Linux/macOS/Windows CI matrix. A post-merge audit (structural integrity, a byte-for-byte behavior diff of the highest-risk extractions, and a security read of the extracted action + spawn paths) found no regressions and no must-fix items.
  • One hardening fix rode along. The commit-split flow's diagnostic dump (repo metadata written to /tmp for the silent-failure debugging aid) now lands in an mkdtemp directory with 0o600 perms instead of a predictable, world-readable, timestamp-named path — matching the editor temp-file hooks. User-invisible; closes a low-severity info-leak / symlink-redirect risk on shared hosts (#1236).
  • Releases are now guarded against no-op publishes. A new release:verify step (wired into the release flow) builds, packs, and diffs the local dist/ against the latest published tarball, aborting if they're byte-identical or the version already exists on npm — the exact failure mode behind the 0.70.0 incident. release-it's pre-release pull is also hardened to --ff-only (#1252).

Under the hood

  • 26 new src/workstation/runtime/hooks/use*.ts modules; the runtime component now composes them.
  • Header surface migrated from a render function to a memoized React.memo component consuming LogInkRuntimeContext — the first step of a gradual surface→context migration.
  • Added eslint-plugin-react-hooks (rules-of-hooks as error, exhaustive-deps as warning) — a lint safety net for the newly-extracted hooks and future runtime work (#1235).
  • New distribution tooling: install.sh (curl installer), packaging/homebrew/coco.rb (canonical formula), and bin/genHomebrewFormula.mjs / bin/verifyRelease.mjs with release:formula / release:verify npm scripts.

Breaking Changes

None.

Full Changelog: 0.71.0...0.72.0

Release 0.71.0

12 Jun 16:37

Choose a tag to compare

What's Changed

0.71.0 expands the coco ui workstation with four new git-ops surfaces, so more day-to-day git work happens in the TUI without dropping to a shell. No breaking changes; everything is additive.

Highlights

Submodule actions

The submodules view is no longer read-only. With a submodule highlighted:

  • i init, u update (--init, so an uninitialized submodule is registered and checked out in one step), s sync.

Each acts on just the cursored submodule (scoped by its path), so a sibling is never disturbed. None are destructive, so they run without a confirmation prompt.

Remotes view (gn)

A new surface listing every configured remote with its fetch / push URLs:

  • a add (name url), e set-url (for the cursored remote), x remove, p prune, y yank the URL.
  • remove and prune are destructive and ask for confirmation first; add / set-url are gated by the text prompt itself.
  • Remote names and URLs are validated so a value beginning with - can't be misread as a git flag.

Blame drill-down (b)

Press b on a file in the status view to open a git blame drill-down for it:

  • Each line shows a dimmed <shorthash> <author> gutter plus the source line.
  • Blame is fetched on demand and cached per file (it is not loaded at startup), and the view is windowed around the cursor, so even a very large file stays responsive.

Rebase onto a ref (r)

In the branches view, press r to rebase the current branch onto the highlighted branch / ref:

  • Non-interactive (git rebase <ref>; it never opens an editor).
  • Confirms first, naming both branches, and guards against rebasing a branch onto itself or rebasing from a detached HEAD.
  • If the rebase stops on a conflict, the existing in-progress-operation view, the conflicts surface (gx), and abort (A) handle it, exactly as for merge / cherry-pick / revert.

Notable

  • All four surfaces follow the existing workstation conventions (filterable lists, windowed rendering, footer key hints), and their keys are scoped to each view so they don't collide with global bindings.
  • The destructive actions (remote remove / prune, rebase) cannot run without passing the y / n confirmation gate.

Under the hood

  • CI gained a dedicated Integration job, a Windows matrix cell, and a Claude-based PR review action (these landed in 0.70.3; this is the first feature release on top of them).

Breaking Changes

None.

Full Changelog: 0.70.3...0.71.0

Release 0.70.3

11 Jun 22:14

Choose a tag to compare

What's Changed

0.70.3 is a small fixes-and-hardening patch on the 0.70 multi-forge line, plus development and CI housekeeping. There are no new features and no breaking changes; GitHub behavior is unchanged. Upgrading from 0.70.2 requires nothing on your end.

Fixes

  • Self-hosted GitLab auth hints. The error-path auth re-probe (resolveGlabActionError) is now scoped to the repository's host, threaded end-to-end through the forge adapter. On a self-managed GitLab instance, a failed MR or issue action now surfaces a recovery hint for the right host instead of the default one. (Completes the host-scoping started in 0.70.2, which covered the list and detail paths.)
  • Forge-aware idle tip. The workstation idle hint that read "C creates a PR ..." now says "MR" on GitLab repositories.
  • Crash safety. The workstation's forge-action dispatch gained a catch arm, so a forge action that ever rejects surfaces a clean error status rather than risking an unhandled rejection in the TUI.
  • Robustness. The GitHub list parsers now guard a non-array API response (a clear message instead of a cryptic "raw.map is not a function"), matching the GitLab parsers. Commit hashes are percent-encoded in generated web URLs for consistency with the other path segments.

Under the hood (no user-facing change)

  • Dependencies. Cleared the flatted and picomatch Dependabot advisories via Yarn resolutions. Both are devDependency-tree only; the published package ships dist/ and never included them. (One minimatch dev-tree advisory remains, deferred to an eslint major upgrade; it has no user exposure.)
  • CI. Added a dedicated Integration test job (the live GitLab suite activates when COCO_GITLAB_IT + COCO_GITLAB_TEST_PROJECT repo secrets are set) and a Windows matrix cell. The test suite was made cross-platform (path-separator portability) so the Windows cell runs green.
  • CI. Swapped the automated PR code-review workflow from the OpenAI action to the official Claude Code action (anthropics/claude-code-action), label-gated on claude review with an ANTHROPIC_API_KEY secret.
  • Tooling. Lossy GIF size optimization in the screenshot pipeline (collapses near-identical VHS sleep-frames for the marketing captures).

Breaking Changes

None. GitHub and GitHub Enterprise users see no behavior change; the GitLab fix and the housekeeping are transparent.

Full Changelog: 0.70.2...0.70.3

Release 0.70.2

11 Jun 17:43

Choose a tag to compare

What's Changed

0.70.2 is a polish and hardening patch for the 0.70 multi-forge release. It tightens GitLab parity (forge-aware wording, self-hosted auth, pagination, pipeline status) and hardens the terminal-rendering and CLI-argument paths against malicious forge content. There are no new features and no breaking changes; GitHub behavior is unchanged. Upgrading from 0.70.1 requires nothing on your end.

GitLab parity and fixes

  • Forge-aware terminology everywhere. GitLab repositories now say "merge request" / "MR" instead of "pull request" / "PR" across the workstation TUI, coco pr create, coco prs, and the empty / unauthenticated states. The recovery hints point at glab and glab auth login rather than gh.
  • Open-in-browser works on GitLab. Pressing O on a GitLab repository now opens the right page. It was previously gated to GitHub and failed with a misleading "No GitHub remote detected" even though the URL builder already supported GitLab.
  • --limit above 100 is honored on GitLab. The GitLab list loaders for coco prs and coco issues now page through results instead of silently truncating at a single 100-row page.
  • Self-hosted GitLab auth detection. The glab auth status probe is scoped to the repository's own host, so a user authenticated to a self-managed instance no longer sees a spurious "not authenticated".
  • Pipeline status in the inspector. A failed GitLab pipeline is reported as "fail" rather than "other"; GitLab's pipeline vocabulary is normalized to the shared check status the inspector buckets on.
  • MR / issue detail notes paginate. Discussion threads longer than 100 comments are no longer cut off in the inspector.
  • Clearer GitLab API errors. A non-array error body from glab api now surfaces the real message instead of a cryptic "raw.map is not a function".

Security hardening

  • Terminal / ANSI injection. Forge-authored text (titles, bodies, comments, author names, labels, and branch names from the GitHub and GitLab APIs) is stripped of control and escape bytes before it is rendered in the CLI output and the workstation TUI. This prevents a hostile MR / issue / comment author from injecting escape sequences to wipe scrollback, spoof triage rows, rewrite the terminal title, or drive clipboard writes.
  • Argument hardening. gh and glab invocations pass user-controlled values in the --flag=value form and validate usernames and branch / label refs, as defense-in-depth against argument / flag injection. (No shell is ever used; this closes the residual flag-parsing surface.)
  • Dependency advisory. Pinned shell-quote to >= 1.8.4 to clear a critical advisory that reached the dependency tree transitively through react-devtools-core.

Notable

  • No new commands, flags, or configuration. The README and the Multi-Forge-Support wiki page already describe the multi-forge surface (including self-hosted GitLab and the forgeHosts override) and remain accurate.

Breaking Changes

None. GitHub and GitHub Enterprise users see no behavior change; the GitLab improvements and the security hardening are transparent.

Full Changelog: 0.70.1...0.70.2

Release 0.70.1

11 Jun 13:40

Choose a tag to compare

What's Changed

0.70.1 ships the multi-forge support that 0.70.0 was meant to deliver. The 0.70.0 tag was published with only a version bump: the multi-forge feature branch was prepared and fully tested but never merged, so the published 0.70.0 was byte-for-byte identical to 0.69.0. 0.70.1 corrects that by landing the feature. If you are on 0.70.0, upgrade to 0.70.1 to actually get GitLab and GitHub Enterprise support.

With this release coco is multi-forge. GitLab (through the glab CLI) and GitHub Enterprise join GitHub, built on a new host-agnostic provider layer. Everything that worked against GitHub now works against GitLab too: the coco prs, coco issues, and coco pr create commands, and the full workstation TUI (triage lists, inspectors, and every per-row action). GitHub behavior is unchanged.

Highlights

GitLab support

  • coco prs and coco issues list GitLab merge requests and issues with the same filters, output, and --json as the GitHub path. Data is read through glab api against the documented GitLab REST endpoints and mapped to the same view models.
  • coco pr create opens a GitLab merge request, generating the title and body from the branch diff exactly as it does for GitHub.
  • coco detects the forge from the remote and routes to the matching CLI automatically: gh for GitHub / GitHub Enterprise, glab for GitLab. GitLab support requires glab to be installed and authenticated (glab auth login), mirroring how GitHub features require gh.

GitLab in the workstation

  • The coco ui PR and issue triage views, the per-row inspectors (body, comments, approvals, pipeline status), and every mutating action work against GitLab. Merge requests support merge / approve / close / comment / label / assign; issues support comment / label / assign / close / reopen.
  • Action dispatch routes through a single provider-keyed forge adapter, so the same keybindings drive GitHub or GitLab depending on the repo's remote.

GitHub Enterprise

  • The forge layer detects the remote host instead of assuming github.com, and the gh authentication probe targets that host. GitHub Enterprise remotes work without configuration.

Host-agnostic provider foundation

  • Added a host-agnostic remote-URL parser (scp, ssh, git, and https forms for any host, preserving GitLab subgroup namespaces).
  • The provider is detected from the remote host (github.com, gitlab.com, *gitlab*, and *github* Enterprise hosts), and web URLs are built per forge (GitLab routes sub-paths under /-/ and uses merge-request paths).

Notable

  • GitLab needs glab. Install it from https://gitlab.com/gitlab-org/cli and run glab auth login. When it is missing or unauthenticated, coco prints the same kind of recovery hint it shows for gh.
  • GitLab has no native "request changes" review. That action posts a note carrying the reviewer's text (prefixed Requested changes:), since GitLab models review as approvals plus discussion.
  • Self-hosted forges on vanity hostnames (a host with neither gitlab nor github in its name, e.g. git.acme.com) can be mapped explicitly with the forgeHosts config, for example { "git.acme.com": "gitlab" }. github.com, gitlab.com, GitHub Enterprise, and GitLab self-managed hosts named like gitlab.* are detected automatically.

Upgrade note

  • 0.70.0 is being deprecated on npm and points here. There is nothing to migrate: install git-coco@0.70.1 (or npx git-coco@latest) and the GitLab and GitHub Enterprise paths activate automatically based on your remote.

Breaking Changes

None. GitHub and GitHub Enterprise users see no behavior change; the GitLab paths are additive and only activate for GitLab remotes.

Full Changelog: 0.70.0...0.70.1

Release 0.70.0

11 Jun 12:54

Choose a tag to compare

What's Changed

0.70.0 makes coco multi-forge. GitLab (through the glab CLI) and GitHub Enterprise join GitHub, built on a new host-agnostic provider layer. Everything that worked against GitHub now works against GitLab too: the coco prs, coco issues, and coco pr create commands, and the full workstation TUI (triage lists, inspectors, and every per-row action). GitHub behavior is unchanged.

Highlights

GitLab support

  • coco prs and coco issues list GitLab merge requests and issues with the same filters, output, and --json as the GitHub path. Data is read through glab api against the documented GitLab REST endpoints and mapped to the same view models.
  • coco pr create opens a GitLab merge request, generating the title and body from the branch diff exactly as it does for GitHub.
  • coco detects the forge from the remote and routes to the matching CLI automatically: gh for GitHub / GitHub Enterprise, glab for GitLab. GitLab support requires glab to be installed and authenticated (glab auth login), mirroring how GitHub features require gh.

GitLab in the workstation

  • The coco ui PR and issue triage views, the per-row inspectors (body, comments, approvals, pipeline status), and every mutating action work against GitLab. Merge requests support merge / approve / close / comment / label / assign; issues support comment / label / assign / close / reopen.
  • Action dispatch routes through a single provider-keyed forge adapter, so the same keybindings drive GitHub or GitLab depending on the repo's remote.

GitHub Enterprise

  • The forge layer detects the remote host instead of assuming github.com, and the gh authentication probe targets that host. GitHub Enterprise remotes work without configuration.

Host-agnostic provider foundation

  • Added a host-agnostic remote-URL parser (scp, ssh, git, and https forms for any host, preserving GitLab subgroup namespaces).
  • The provider is detected from the remote host (github.com, gitlab.com, *gitlab*, and *github* Enterprise hosts), and web URLs are built per forge (GitLab routes sub-paths under /-/ and uses merge-request paths).

Notable

  • GitLab needs glab. Install it from https://gitlab.com/gitlab-org/cli and run glab auth login. When it is missing or unauthenticated, coco prints the same kind of recovery hint it shows for gh.
  • GitLab has no native "request changes" review. That action posts a note carrying the reviewer's text (prefixed Requested changes:), since GitLab models review as approvals plus discussion.
  • Self-hosted forges on vanity hostnames (a host with neither gitlab nor github in its name, e.g. git.acme.com) can be mapped explicitly with the forgeHosts config, for example { "git.acme.com": "gitlab" }. github.com, gitlab.com, GitHub Enterprise, and GitLab self-managed hosts named like gitlab.* are detected automatically.

Breaking Changes

None. GitHub and GitHub Enterprise users see no behavior change; the GitLab paths are additive and only activate for GitLab remotes.

Full Changelog: 0.69.0...0.70.0

Release 0.69.0

10 Jun 13:26

Choose a tag to compare

What's Changed

0.69.0 turns the local usage ledger introduced in 0.68 into a default-on, opt-out feature and adds a per-repo view to the cost report. Recording stays entirely local: the ledger is a plain JSONL file under the cache directory that holds metadata only (task, model, prompt-token estimate, latency, and a repo identifier) and never leaves the machine. It records no prompt, diff, or code content.

Highlights

Opt-out local usage stats

  • Added a telemetry.usage config key that turns the cross-run usage ledger on or off. Recording resolves in this order: the COCO_USAGE_LOG environment variable wins either way (a path, 1, or true forces it on; 0 or false forces it off), then telemetry.usage, then off.
  • Added a first-run consent step to every command. The first time a command runs on an interactive terminal with no preference set anywhere, coco defaults recording on, saves the choice to the global config, and prints a one-time notice. Non-interactive and CI runs stay off, so piped and automated commands are never opted in.
  • Added an opt-out prompt to coco init (defaults to on). The choice is stored per machine in the global config, not in the shared project config, so a cloned repo cannot flip a collaborator's recording on.

Per-repo cost breakdown

  • Tagged each usage record with a readable owner/repo identifier, resolved from the git remote with the working directory name as a fallback. The identifier works for any forge (GitHub, GitLab, Bitbucket, self-hosted).
  • Added a By repo section to coco doctor --cost and a byRepo array to its --json output, so usage can be attributed per project.

Manage the ledger

  • Added coco doctor --clear to delete the local usage ledger.
  • Capped and rotated the ledger automatically. Once the file passes 5 MB it is rewritten with only its most recent records, so a long-lived install stays bounded.

Notable

  • The recording posture changed from opt-in to opt-out. In 0.68 nothing was written unless COCO_USAGE_LOG was set. In 0.69 an interactive first run defaults recording on after a one-time notice, and coco init asks. Recording is still local-only and reversible: opt out with coco init, set telemetry.usage to false, or set COCO_USAGE_LOG=0. The COCO_USAGE_LOG environment variable remains authoritative and overrides the config either way.
  • The preference is per machine. It lives in the global XDG config ($XDG_CONFIG_HOME/coco/config.json), so it follows the user across repos rather than being committed to any one project.

Breaking Changes

None. Existing installs that never set telemetry.usage and never run an interactive command keep recording off, and COCO_USAGE_LOG keeps its 0.68 meaning. The only behavior change is the first-run default for interactive sessions, which prints a notice and is reversible.

Full Changelog: 0.68.0...0.69.0