Releases: gfargo/coco
Release 0.72.3
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/corebump. The 1.1.48 update changedStructuredOutputParser'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:
ink7.0.5 → 7.0.6 (#1260),ajv8.18.0 → 8.20.0 (#1262),@langchain/community1.1.28 → 1.1.29 (#1258),@langchain/core1.1.48 → 1.1.49 (#1261),@babel/core7.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
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/defineSurfaceComponenthelpers (#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 closed — runtime/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
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 inithandles a first-run Ollama setup gracefully instead of failing when the daemon or a model isn't ready yet (#1264).coco doctorruns 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 pullto 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:
useState28 → 3 (only the core reducer state and the theme-picker preview remain),app.tstrimmed to ~1,711 LOC. Together with0.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). TheCommitOptionsinterface was also completed (append/appendTicket/additionalare 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
trueif 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 initnow persists the recommended.coco.jsonconfig. Choosing the recommended.coco.jsonproject-config format previously wrote nothing while still reporting success (only the legacy.coco.config.jsonwas handled). Both JSON formats are now written, with a defensive guard so an unhandled format fails loudly instead of silently (#1285).coco initmodel picker: corrected the o-series ids. The OpenAI model list hado3/o3-minimistyped as03/03-mini(digit zero) and a duplicategpt-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 commithero GIF pointed at a real code change (#1267).
Under the hood
- LangChain internals: dropped a dead
llmparam and tightenedcreateSchemaParser'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
CommitOptionscasts 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 -tno longer resolves — use the long form--appendTicket(-tis now--tagoncoco changelog).coco log -cno longer resolves — use the long form--commit(-cis now--conventionaloncoco commit).
The long flags are unchanged; only the ambiguous short letters moved. A
flagAliasConsistency.test.tsguard 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
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%)
useEffect41 → 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
LogInkRuntimeContextprovider (installed in an earlier release) now has its first real consumer — the header surface readsstate/context/theme/layoutfrom 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
-
curlinstaller — checks for Node 22+, installsgit-cocowith whatever package manager you have (npm/pnpm/yarn), and prints next steps. Pin a version withCOCO_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
mountedRefunmount 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
/tmpfor the silent-failure debugging aid) now lands in anmkdtempdirectory with0o600perms 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:verifystep (wired into the release flow) builds, packs, and diffs the localdist/against the latest published tarball, aborting if they're byte-identical or the version already exists on npm — the exact failure mode behind the0.70.0incident.release-it's pre-release pull is also hardened to--ff-only(#1252).
Under the hood
- 26 new
src/workstation/runtime/hooks/use*.tsmodules; the runtime component now composes them. - Header surface migrated from a render function to a memoized
React.memocomponent consumingLogInkRuntimeContext— 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), andbin/genHomebrewFormula.mjs/bin/verifyRelease.mjswithrelease:formula/release:verifynpm scripts.
Breaking Changes
None.
Full Changelog: 0.71.0...0.72.0
Release 0.71.0
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:
iinit,uupdate (--init, so an uninitialized submodule is registered and checked out in one step),ssync.
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:
aadd (name url),eset-url (for the cursored remote),xremove,pprune,yyank the URL.removeandpruneare destructive and ask for confirmation first;add/set-urlare 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
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
catcharm, 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
flattedandpicomatchDependabot advisories via Yarnresolutions. Both are devDependency-tree only; the published package shipsdist/and never included them. (Oneminimatchdev-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_PROJECTrepo 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 onclaude reviewwith anANTHROPIC_API_KEYsecret. - 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
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 atglabandglab auth loginrather thangh. - Open-in-browser works on GitLab. Pressing
Oon 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. --limitabove 100 is honored on GitLab. The GitLab list loaders forcoco prsandcoco issuesnow page through results instead of silently truncating at a single 100-row page.- Self-hosted GitLab auth detection. The
glab auth statusprobe 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 apinow 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.
ghandglabinvocations pass user-controlled values in the--flag=valueform 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-quoteto>= 1.8.4to clear a critical advisory that reached the dependency tree transitively throughreact-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
forgeHostsoverride) 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
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 prsandcoco issueslist GitLab merge requests and issues with the same filters, output, and--jsonas the GitHub path. Data is read throughglab apiagainst the documented GitLab REST endpoints and mapped to the same view models.coco pr createopens 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:
ghfor GitHub / GitHub Enterprise,glabfor GitLab. GitLab support requiresglabto be installed and authenticated (glab auth login), mirroring how GitHub features requiregh.
GitLab in the workstation
- The
coco uiPR 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
ghauthentication 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 runglab auth login. When it is missing or unauthenticated, coco prints the same kind of recovery hint it shows forgh. - 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
gitlabnorgithubin its name, e.g.git.acme.com) can be mapped explicitly with theforgeHostsconfig, for example{ "git.acme.com": "gitlab" }. github.com, gitlab.com, GitHub Enterprise, and GitLab self-managed hosts named likegitlab.*are detected automatically.
Upgrade note
0.70.0is being deprecated on npm and points here. There is nothing to migrate: installgit-coco@0.70.1(ornpx 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
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 prsandcoco issueslist GitLab merge requests and issues with the same filters, output, and--jsonas the GitHub path. Data is read throughglab apiagainst the documented GitLab REST endpoints and mapped to the same view models.coco pr createopens 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:
ghfor GitHub / GitHub Enterprise,glabfor GitLab. GitLab support requiresglabto be installed and authenticated (glab auth login), mirroring how GitHub features requiregh.
GitLab in the workstation
- The
coco uiPR 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
ghauthentication 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 runglab auth login. When it is missing or unauthenticated, coco prints the same kind of recovery hint it shows forgh. - 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
gitlabnorgithubin its name, e.g.git.acme.com) can be mapped explicitly with theforgeHostsconfig, for example{ "git.acme.com": "gitlab" }. github.com, gitlab.com, GitHub Enterprise, and GitLab self-managed hosts named likegitlab.*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
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.usageconfig key that turns the cross-run usage ledger on or off. Recording resolves in this order: theCOCO_USAGE_LOGenvironment variable wins either way (a path,1, ortrueforces it on;0orfalseforces it off), thentelemetry.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/repoidentifier, 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 reposection tococo doctor --costand abyRepoarray to its--jsonoutput, so usage can be attributed per project.
Manage the ledger
- Added
coco doctor --clearto 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.68nothing was written unlessCOCO_USAGE_LOGwas set. In0.69an interactive first run defaults recording on after a one-time notice, andcoco initasks. Recording is still local-only and reversible: opt out withcoco init, settelemetry.usagetofalse, or setCOCO_USAGE_LOG=0. TheCOCO_USAGE_LOGenvironment 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