Skip to content

feat(cli): global --repo flag (every subcommand inherits)#952

Merged
gfargo merged 1 commit into
mainfrom
feat/repo-flag-global
May 14, 2026
Merged

feat(cli): global --repo flag (every subcommand inherits)#952
gfargo merged 1 commit into
mainfrom
feat/repo-flag-global

Conversation

@gfargo
Copy link
Copy Markdown
Owner

@gfargo gfargo commented May 14, 2026

Follow-up to #948 which added `--repo` to `coco ui` + `coco log` only. Contributor asked to lift it so `commit` / `review` / `recap` / `changelog` all inherit too — particularly for scripts and editor / shell wrappers that want to drive coco non-interactively against arbitrary repos.

What this PR adds

  • `--repo ` (alias `--cwd`) declared globally at the yargs root (`y.option('repo', { ..., global: true })`). Every subcommand inherits automatically; `coco --help` and per-subcommand help both surface it.
  • `repo?: string` lifted to `BaseArgvOptions` so the TypeScript layer matches — every command's argv type sees the field through normal inheritance.
  • Shared `applyRepoFlag(argv)` helper at `src/commands/utils/applyRepoFlag.ts`. Encapsulates "resolve path → chdir → getRepo(repoPath)" so every handler does it identically. Returns the bound SimpleGit instance for direct use.

Handlers updated

The per-command `--repo` declarations from #948 are removed in favor of the single global declaration. Behavior unchanged; just deduplicated.

Why chdir + bound git + global flag together

A repo target isn't a single value — it touches three independent subsystems:

  1. simple-git's baseDir — controls where git operations run
  2. `process.cwd()` — what every `findUp` config-discovery walks from
  3. Path resolution — relative paths in argv (e.g. `--branch`) interpret against cwd

Setting only one would create "coco operates on repo A but reads config from repo B" surprises. `applyRepoFlag` does all three in one shot so the rest of each handler can ignore the question.

Now usable across the board

```bash

Generate a commit message for a different repo

coco commit --repo ~/work/api

Review a PR-bound branch in another project

coco review --repo ~/work/api --branch feat/new

Recap a different repo's last week

coco recap --repo ~/work/api --since 1w

Generate changelog for another project

coco changelog --repo ~/work/api --branch main

Open workstation against any directory (#948)

coco ui --repo ~/work/api

Inspect another repo's log (#948)

coco log --repo ~/work/api --limit 10
```

Compatibility

Users on the `cd && coco ...` path see zero change — `argv.repo === undefined` makes `applyRepoFlag` skip the chdir and call `getRepo()` with no baseDir, preserving original behavior exactly. `--cwd` alias preserved from #948.

Test plan

  • `npm run lint` clean
  • `tsc --noEmit` clean
  • `npm run test:jest` — 1681 tests pass (+4 from new applyRepoFlag tests)
  • Verified end-to-end: `coco log --repo /tmp/scenario --limit 5` from coco repo cwd shows scenario commits
  • Verified `coco --help` lists the global flag

Out of scope

  • `commit --repo` doesn't auto-stage anything in the target repo — the user still controls staging via the usual `git add` workflow before invoking. Same for the other commands. `--repo` just retargets where commands READ from / WRITE to.
  • Cross-repo workflows (e.g. "commit in repo A using a draft from repo B") are still out of scope — single `--repo` flag means one target per invocation. Could lift later if a real use case shows up.

Follow-up to #948 which added --repo to coco ui + coco log only. Contributor asked to lift it so commit / review / recap / changelog all inherit too — particularly for scripts and editor / shell wrappers that want to drive coco non-interactively against arbitrary repos.

## What this PR adds

- **\`--repo <dir>\` (alias \`--cwd\`) declared globally** at the yargs root in src/index.ts (\`y.option('repo', { ..., global: true })\`). Every subcommand inherits it automatically; \`coco --help\` and per-subcommand help both surface it.
- **\`repo?: string\` lifted to \`BaseArgvOptions\`** so the TypeScript layer matches — every command's argv type sees the field through normal inheritance.
- **Shared \`applyRepoFlag(argv)\` helper** at src/commands/utils/applyRepoFlag.ts. Encapsulates the "resolve path → chdir → getRepo(repoPath)" dance so every handler does it identically. Returns the bound SimpleGit instance for direct use.

## Handlers updated to use the shared helper

- commit/handler.ts
- recap/handler.ts
- changelog/handler.ts
- review/handler.ts
- ui/handler.ts (replaces #948's inline implementation)
- log/handler.ts (replaces #948's inline implementation)

The inline / per-command --repo declarations from #948 are removed in favor of the single global declaration. Behavior unchanged; just deduplicated.

## Why chdir + bound git instance + global flag together

A repo target isn't a single value — it touches three independent subsystems:

1. **simple-git's baseDir** — controls where git operations run
2. **process.cwd()** — what every \`findUp\` config-discovery walks from
3. **Path resolution** — relative paths in argv (e.g. \`--branch\`) interpret against cwd

Setting only one of these would create "coco operates on repo A but reads config from repo B" surprises. \`applyRepoFlag\` does all three in one shot so the rest of each handler can ignore the question.

## Compatibility

Users on the \`cd && coco ...\` path see zero change — \`argv.repo === undefined\` makes \`applyRepoFlag\` skip the chdir and call \`getRepo()\` with no baseDir, preserving original behavior exactly.

The \`--cwd\` alias is preserved (added in #948 for users who think "change directory" before "target this repo").

## Tests

+4 unit tests for \`applyRepoFlag\`:
- returns getRepo() when --repo is omitted
- chdir's + returns getRepo(absolutePath) when --repo is set
- resolves relative paths to absolute before chdir
- treats empty string the same as omitted (defensive)

1681 tests pass, lint + tsc clean.

## Verified end-to-end

\`coco log --repo /tmp/scenario --limit 5\` from inside the coco repo shows the scenario's commits. \`coco --help\` lists the global flag under each subcommand's usage block.
@gfargo gfargo merged commit 6228a20 into main May 14, 2026
5 of 7 checks passed
@gfargo gfargo deleted the feat/repo-flag-global branch May 14, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant