{"id":24822233,"url":"https://github.com/hemandev/codeowners-git","last_synced_at":"2026-02-27T10:45:48.709Z","repository":{"id":274626573,"uuid":"923527503","full_name":"hemandev/codeowners-git","owner":"hemandev","description":"A CLI tool that simplifies large-scale monorepo migrations by creating team-specific branches based on CODEOWNERS for streamlined and efficient PR reviews.","archived":false,"fork":false,"pushed_at":"2025-02-25T05:13:36.000Z","size":78,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T01:07:46.778Z","etag":null,"topics":["codeowners","monorepo","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hemandev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-28T12:09:58.000Z","updated_at":"2025-02-25T05:13:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"17a607f9-dd85-468b-8660-9ed395e19942","html_url":"https://github.com/hemandev/codeowners-git","commit_stats":null,"previous_names":["hemandev/codeowners-git"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hemandev%2Fcodeowners-git","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hemandev%2Fcodeowners-git/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hemandev%2Fcodeowners-git/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hemandev%2Fcodeowners-git/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hemandev","download_url":"https://codeload.github.com/hemandev/codeowners-git/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248501864,"owners_count":21114683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codeowners","monorepo","typescript"],"created_at":"2025-01-30T18:27:02.712Z","updated_at":"2026-02-27T10:45:48.699Z","avatar_url":"https://github.com/hemandev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# codeowners-git\n\n[![Release](https://github.com/hemandev/codeowners-git/actions/workflows/release.yml/badge.svg)](https://github.com/hemandev/codeowners-git/actions/workflows/release.yml)\n[![npm version](https://img.shields.io/npm/v/codeowners-git)](https://www.npmjs.com/package/codeowners-git)\n[![license](https://img.shields.io/npm/l/codeowners-git)](LICENSE)\n\nManaging large-scale migrations in big monorepos with multiple codeowners can be overwhelming. Massive PRs touching thousands of files make it hard for teams to review changes efficiently.\n\n`codeowners-git` (or `cg` for short) solves this by:\n\n- Identifying files owned by specific teams using the CODEOWNERS file.\n- Creating compact, team-specific branches with only their affected files.\n- Streamlining the review process with smaller, targeted PRs.\n- **Graceful error handling** with automatic recovery from failures.\n- **Dry-run previews** to see exactly what will happen before committing.\n- **JSON output** for piping to other tools, scripts, and agent workflows.\n\n\u003e ❗❗ ❗ **Note:** Starting from v2.0.0, this tool works with **staged files**. Stage your changes with `git add` before running commands.\n\nhttps://github.com/user-attachments/assets/7cc0a924-f03e-47f3-baad-63eca9e8e4a8\n\n## Installation\n\n### Using npx (recommended)\n\nRun commands directly without installation:\n\n```bash\nnpx codeowners-git \u003ccommand\u003e\n```\n\n### Install globally via npm\n\n```bash\nnpm install -g codeowners-git\n```\n\nThen run commands directly:\n\n```bash\ncodeowners-git \u003ccommand\u003e\n# or use the short alias\ncg \u003ccommand\u003e\n```\n\n## Configuration\n\nThe tool automatically detects CODEOWNERS files in:\n\n1. `.github/CODEOWNERS`\n2. `docs/CODEOWNERS`\n3. `CODEOWNERS` (root directory)\n\n### Pull Request Features\n\nThe `--pr` and `--draft-pr` options require the [GitHub CLI (`gh`)](https://cli.github.com/) to be installed and authenticated:\n\n```bash\n# Install GitHub CLI (macOS)\nbrew install gh\n\n# Install GitHub CLI (Windows)\nwinget install --id GitHub.cli\n\n# Install GitHub CLI (Linux)\nsudo apt install gh\n\n# Authenticate with GitHub\ngh auth login\n```\n\nThe tool will automatically:\n\n- Use PR templates if they exist in your repository (`.github/pull_request_template.md`, etc.)\n- Set the PR title to your commit message\n- Create PRs against the repository's default branch\n\n### Owner Pattern Matching\n\nThe `--include` and `--ignore` options support glob patterns for flexible owner filtering:\n\n| Pattern      | Description       | Example Match                      |\n| ------------ | ----------------- | ---------------------------------- |\n| `@org/team`  | Exact match       | `@org/team` only                   |\n| `*team`      | Ends with         | `@org/team`, `@company/team`       |\n| `@org/*`     | Starts with (org) | `@org/team-a`, `@org/team-b`       |\n| `*ce-*`      | Contains          | `@org/ce-orca`, `@company/ce-team` |\n| `*orca,*rme` | Multiple patterns | Either pattern matches             |\n\n**Key behavior:**\n\n- `*` matches any character **including `/`** (slashes are normalized)\n- `*/ce-orca` and `*ce-orca` behave identically\n- Patterns are case-sensitive\n- Multiple patterns can be comma-separated\n\n### Path Pattern Matching\n\nPath patterns use [micromatch](https://github.com/micromatch/micromatch) syntax:\n\n| Pattern                 | Description                    | Example Match                                   |\n| ----------------------- | ------------------------------ | ----------------------------------------------- |\n| `src`                   | Directory (auto-appends `/**`) | All files in `src/`                             |\n| `src/`                  | Directory with trailing slash  | All files in `src/`                             |\n| `**/*.ts`               | Glob pattern                   | All `.ts` files                                 |\n| `{src,docs}`            | Brace expansion                | Files in `src/` or `docs/`                      |\n| `packages/{a,b}/**`     | Combined                       | Files in `packages/a/` or `packages/b/`         |\n| `packages/**/{foo,bar}` | Nested braces                  | Directories named `foo` or `bar` under packages |\n\n**Key behavior:**\n\n- Directories without glob chars automatically match all files inside (`src` → `src/**`)\n- Use brace expansion `{a,b}` for multiple patterns (not comma-separated)\n- Supports full micromatch/glob syntax: `*`, `**`, `?`, `[...]`, `{...}`\n\n## Commands\n\n### `--version`\n\nDisplay the version of codeowners-git.\n\nUsage:\n\n```bash\ncodeowners-git --version\n# or\ncodeowners-git -V\n# or using the short alias\ncg --version\n```\n\n### `list`\n\nList changed files with their CODEOWNERS.\n\nUsage:\n\n```bash\ncodeowners-git list [pattern] [options]\n# or\ncg list [pattern] [options]\n```\n\nArguments:\n\n- `[pattern]` Optional path pattern to filter files (micromatch syntax)\n\nOptions:\n\n- `--include, -i` Filter by owner patterns (glob syntax)\n- `--group, -g` Group files by code owner\n- `--exclusive, -e` Only include files with a single owner (no co-owned files)\n- `--co-owned, -c` Only include files with multiple owners (co-owned files)\n- `--json` Output results as JSON (suppresses all other output)\n\nExamples:\n\n```bash\n# List all changed files with owners\ncg list\n\n# Filter by path pattern\ncg list src/\ncg list \"packages/{basics,shared}/**\"\n\n# Filter by owner pattern\ncg list --include \"*ce-*\"\n\n# Group output by owner\ncg list --group\n\n# Combine filters\ncg list \"packages/\" --include \"@myorg/*\" --group\n\n# List only files with a single owner (exclude co-owned files)\ncg list --exclusive\n\n# List only files where @myteam is the sole owner\ncg list --include \"@myteam\" --exclusive\n\n# List only co-owned files (files with multiple owners)\ncg list --co-owned\n\n# List co-owned files where @myteam is one of the owners\ncg list --include \"@myteam\" --co-owned\n\n# Output as JSON for piping to other tools\ncg list --json\n\n# JSON output with filters (pipe to jq)\ncg list -i \"@myteam\" --group --json | jq '.grouped'\n```\n\n### `branch`\n\nCreate a branch with changes owned by a specific codeowner.\n\nUsage:\n\n```bash\ncodeowners-git branch [pattern] [options]\n# or\ncg branch [pattern] [options]\n```\n\nArguments:\n\n- `[pattern]` Optional path pattern to filter files (micromatch syntax). Examples: `packages`, `**/*.tsx`, `{packages,apps}`\n\nOptions:\n\n- `--include, -i` Code owner pattern to filter files (supports glob patterns like `*team`, `@org/*`)\n- `--branch, -b` Specify branch pattern\n- `--message, -m` Commit message for changes\n- `--no-verify, -n` Skips lint-staged and other checks before committing\n- `--push, -p` Push branch to remote after commit\n- `--remote, -r` Remote name to push to (default: \"origin\")\n- `--upstream, -u` Upstream branch name (defaults to local branch name)\n- `--force, -f` Force push to remote\n- `--keep-branch-on-failure, -k` Keep the created branch even if operation fails\n- `--append` Add commits to existing branch instead of creating a new one\n- `--pr` Create a pull request after pushing (requires `--push` and GitHub CLI)\n- `--draft-pr` Create a draft pull request after pushing (requires `--push` and GitHub CLI)\n- `--exclusive, -e` Only include files where the owner is the sole owner (no co-owned files)\n- `--co-owned, -c` Only include files with multiple owners (co-owned files)\n- `--dry-run` Preview the operation without making any changes\n- `--json` Output results as JSON (suppresses all other output)\n\nExample:\n\n```bash\n# Create a new branch with all files owned by @myteam\ncg branch -i @myteam -b \"feature/new-feature\" -m \"Add new feature\" -p\n\n# Filter to only files in the packages directory\ncg branch \"packages\" -i @myteam -b \"feature/packages\" -m \"Update packages\" -p\n\n# Filter with glob pattern (only .tsx files)\ncg branch \"**/*.tsx\" -i @myteam -b \"feature/tsx\" -m \"Update tsx files\" -p\n\n# Filter multiple directories (brace expansion)\ncg branch \"{packages,apps}\" -i @myteam -b \"feature/update\" -m \"Update packages and apps\" -p\n\n# Create a branch and automatically create a pull request\ncg branch -i @myteam -b \"feature/new-feature\" -m \"Add new feature\" -p --pr\n\n# Create a branch and automatically create a draft pull request\ncg branch -i @myteam -b \"feature/new-feature\" -m \"Add new feature\" -p --draft-pr\n\n# Add more commits to the same branch later\ncg branch -i @myteam -b \"feature/new-feature\" -m \"Add more changes\" --append -p\n\n# Use glob patterns to match multiple teams\ncg branch -i \"*ce-*\" -b \"feature/ce-teams\" -m \"Changes for CE teams\" -p\n\n# Match all teams in an organization\ncg branch -i \"@myorg/*\" -b \"feature/org-changes\" -m \"Org-wide changes\" -p\n\n# Match multiple specific patterns\ncg branch -i \"*orca,*rme\" -b \"feature/specific-teams\" -m \"Targeted changes\" -p\n\n# Only include files where @myteam is the sole owner (exclude co-owned files)\ncg branch -i @myteam -b \"feature/exclusive\" -m \"Team exclusive changes\" -p --exclusive\n\n# Only include co-owned files where @myteam is one of the owners\ncg branch -i @myteam -b \"feature/co-owned\" -m \"Co-owned changes\" -p --co-owned\n\n# Preview what would happen without making any changes\ncg branch -i @myteam -b \"feature/new\" -m \"Add feature\" --dry-run\n\n# Dry-run with JSON output (for agents/scripts)\ncg branch -i @myteam -b \"feature/new\" -m \"Add feature\" --dry-run --json\n\n# Normal execution with JSON output\ncg branch -i @myteam -b \"feature/new\" -m \"Add feature\" -p --json\n```\n\n### `multi-branch`\n\nCreate branches for all codeowners with changes.\n\nUsage:\n\n```bash\ncodeowners-git multi-branch [pattern] [options]\n# or\ncg multi-branch [pattern] [options]\n```\n\nArguments:\n\n- `[pattern]` Optional path pattern to filter files (micromatch syntax). Examples: `packages`, `**/*.tsx`, `{packages,apps}`\n\nOptions:\n\n- `--branch, -b` Base branch name (will be suffixed with codeowner name)\n- `--message, -m` Base commit message (will be suffixed with codeowner name)\n- `--no-verify, -n` Skips lint-staged and other checks before committing\n- `--push, -p` Push branches to remote after commit\n- `--remote, -r` Remote name to push to (default: \"origin\")\n- `--upstream, -u` Upstream branch name pattern (defaults to local branch name)\n- `--force, -f` Force push to remote\n- `--keep-branch-on-failure, -k` Keep created branches even if operation fails\n- `--default-owner, -d` Default owner to use when no codeowners are found for changed files\n- `--ignore` Glob patterns to exclude codeowners (e.g., `*team-a`, `@org/*`)\n- `--include` Glob patterns to include codeowners (e.g., `*ce-*`, `@org/*`)\n- `--append` Add commits to existing branches instead of creating new ones\n- `--pr` Create pull requests after pushing (requires `--push` and GitHub CLI)\n- `--draft-pr` Create draft pull requests after pushing (requires `--push` and GitHub CLI)\n- `--exclusive, -e` Only include files where each owner is the sole owner (no co-owned files)\n- `--co-owned, -c` Only include files with multiple owners (co-owned files)\n- `--dry-run` Preview the operation without making any changes\n- `--json` Output results as JSON (suppresses all other output)\n\n\u003e **Note:** You cannot use both `--ignore` and `--include` options at the same time. You also cannot use both `--exclusive` and `--co-owned` options at the same time.\n\nExample:\n\n```bash\n# Create branches for all codeowners\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" -p\n\n# Filter to only files in the packages directory\ncg multi-branch \"packages\" -b \"feature/packages\" -m \"Update packages\" -p\n\n# Filter with glob pattern (only .tsx files)\ncg multi-branch \"**/*.tsx\" -b \"feature/tsx\" -m \"Update tsx files\" -p\n\n# Filter multiple directories (brace expansion)\ncg multi-branch \"{packages,apps}\" -b \"feature/update\" -m \"Update\" -p\n\n# Create branches and automatically create pull requests for each\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" -p --pr\n\n# Create branches and automatically create draft pull requests for each\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" -p --draft-pr\n\n# Exclude specific teams using glob patterns\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" --ignore \"*ce-orca,*ce-ece\"\n\n# Exclude all teams in an organization\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" --ignore \"@excluded-org/*\"\n\n# Include only teams matching a pattern\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" --include \"*ce-*\"\n\n# Include only specific organization\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" --include \"@myorg/*\"\n\n# Use default owner when no codeowners found\ncg multi-branch -b \"feature/new-feature\" -m \"Add new feature\" -d \"@default-team\"\n\n# Add more commits to existing branches\ncg multi-branch -b \"feature/new-feature\" -m \"Add more changes\" --append -p\n\n# Only include files where each owner is the sole owner (exclude co-owned files)\ncg multi-branch -b \"feature/exclusive\" -m \"Exclusive changes\" -p --exclusive\n\n# Only include co-owned files\ncg multi-branch -b \"feature/co-owned\" -m \"Co-owned changes\" -p --co-owned\n\n# Preview all branches that would be created\ncg multi-branch -b \"feature/migration\" -m \"Migrate\" --dry-run\n\n# Dry-run with JSON output\ncg multi-branch -b \"feature/migration\" -m \"Migrate\" --dry-run --json\n\n# Pipe dry-run JSON to see owners with matching files\ncg multi-branch -b \"mig\" -m \"Fix\" --dry-run --json | jq '.owners[] | select(.files | length \u003e 0)'\n\n# Normal execution with JSON output\ncg multi-branch -b \"feature/migration\" -m \"Migrate\" -p --json\n```\n\nThis will:\n\n1. Find all codeowners for the staged files\n2. Apply any ignore/include filters if specified\n3. For each codeowner (e.g., @team-a, @team-b):\n   - Create a branch like `feature/new-feature/team-a`\n   - Commit only the files owned by that team\n   - Add a commit message like \"Add new feature - @team-a\"\n   - Push each branch to the remote if the `-p` flag is provided\n\n### `extract`\n\nExtract file changes from a source branch or commit to your working directory. This is useful when you want to copy changes from another branch to review and then stage them for committing using the `branch` command.\n\nUsage:\n\n```bash\ncodeowners-git extract [pattern] [options]\n# or\ncg extract [pattern] [options]\n```\n\nArguments:\n\n- `[pattern]` Optional path pattern to filter files (micromatch syntax). Examples: `packages`, `**/*.tsx`, `{packages,apps}`\n\nOptions:\n\n- `--source, -s` **(required)** Source branch or commit to extract from\n- `--include, -i` Filter extracted files by code owner (supports glob patterns like `*team`, `@org/*`)\n- `--compare-main` Compare source against main branch instead of detecting merge-base\n- `--exclusive, -e` Only include files where the owner is the sole owner (no co-owned files)\n- `--co-owned, -c` Only include files with multiple owners (co-owned files)\n- `--dry-run` Preview the operation without making any changes\n- `--json` Output results as JSON (suppresses all other output)\n\nExamples:\n\n```bash\n# Extract all changes from a branch (files will be unstaged in working directory)\ncg extract -s feature/other-team\n\n# Extract only specific owner's files\ncg extract -s feature/other-team -i \"@my-team\"\n\n# Extract using glob patterns\ncg extract -s feature/other-team -i \"*ce-*\"\ncg extract -s feature/other-team -i \"@myorg/*\"\n\n# Extract from a commit hash\ncg extract -s abc123def\n\n# Extract comparing against main (instead of detecting merge-base)\ncg extract -s feature/long-running --compare-main\n\n# Filter by path pattern\ncg extract \"packages/\" -s feature/other-team\ncg extract \"{packages,apps}\" -s feature/other-team -i \"@my-team\"\n\n# Extract only files where owner is the sole owner (no co-owned files)\ncg extract -s feature/other-team -i \"@my-team\" --exclusive\n\n# Extract only co-owned files (files with multiple owners)\ncg extract -s feature/other-team --co-owned\n\n# Extract co-owned files where @my-team is one of the owners\ncg extract -s feature/other-team -i \"@my-team\" --co-owned\n\n# Preview what would be extracted without making any changes\ncg extract -s feature/other-team --dry-run\n\n# Dry-run with owner filter\ncg extract -s feature/other-team -i \"@my-team\" --dry-run\n\n# Dry-run with JSON output (for agents/scripts)\ncg extract -s feature/other-team -i \"@my-team\" --dry-run --json\n\n# Normal execution with JSON output\ncg extract -s feature/other-team -i \"@my-team\" --json\n\n# Pipe JSON to jq to get just the file list\ncg extract -s feature/other-team --json | jq '.files'\n```\n\n\u003e **Note:** Files are extracted to your working directory (unstaged), allowing you to review and modify them. Stage the files with `git add`, then use the `branch` command to create a branch, commit, push, and create PRs.\n\n### `recover`\n\nRecover from failed or incomplete operations. When `branch` or `multi-branch` commands fail, the tool tracks the operation state and allows you to clean up and return to your original branch.\n\nUsage:\n\n```bash\ncodeowners-git recover [options]\n# or\ncg recover [options]\n```\n\nOptions:\n\n- `--list` List all incomplete operations\n- `--id \u003coperationId\u003e` Recover specific operation by UUID\n- `--keep-branches` Keep created branches instead of deleting them\n- `--auto` Automatically recover most recent operation without prompts\n\nExamples:\n\n```bash\n# List all incomplete operations\ncg recover --list\n\n# Automatically recover from most recent failure\ncg recover --auto\n\n# Recover specific operation\ncg recover --id abc12345-6789-...\n\n# Recover but keep the created branches\ncg recover --id abc12345-6789-... --keep-branches\n```\n\n**When to use:**\n\n- Operation failed due to network errors\n- Process was interrupted (Ctrl+C)\n- Push failed but branch was created\n- Need to clean up after errors\n\n**What it does:**\n\n1. Returns to your original branch\n2. Optionally deletes created branches (unless `--keep-branches`)\n3. Cleans up state files\n\n**How it works:**\n\nEvery `branch` and `multi-branch` operation is tracked with a unique UUID in your home directory (`~/.codeowners-git/state/`). If an operation fails, you'll see recovery instructions:\n\n```bash\n✗ Operation failed: Push failed with exit code 128\n\nRecovery options:\n  1. Run 'codeowners-git recover --id abc12345...' to clean up\n  2. Run 'codeowners-git recover --id abc12345... --keep-branches' to keep branches\n  3. Run 'codeowners-git recover --list' to see all incomplete operations\n```\n\nThe tool automatically handles:\n\n- Graceful shutdown on Ctrl+C (SIGINT/SIGTERM)\n- State persistence across crashes\n- Detailed operation tracking (branch creation, commits, pushes, PR creation)\n- Clean recovery to original state\n\n\u003e **Note:** State files are stored in `~/.codeowners-git/state/` outside your project directory, so no `.gitignore` entries are needed.\n\n## Dry Run \u0026 JSON Output\n\n### Dry Run (`--dry-run`)\n\nAvailable on: `branch`, `multi-branch`, `extract`\n\nThe `--dry-run` flag shows a complete preview of what would happen without performing any git operations. No branches are created, no files are committed, and nothing is pushed.\n\n```bash\n# Preview branch creation\ncg branch -i @myteam -b \"feature/new\" -m \"Add feature\" --dry-run\n\n# Preview all branches in a multi-branch run\ncg multi-branch -b \"feature/migration\" -m \"Migrate\" --dry-run\n\n# Preview file extraction\ncg extract -s feature/other-team -i \"@myteam\" --dry-run\n```\n\nThe dry-run output includes:\n\n- **branch**: Owner, branch name, branch existence, commit message, matched files, excluded files, push/PR/flag settings\n- **multi-branch**: Per-owner breakdown (branch, message, files), uncovered files, unowned files, summary totals\n- **extract**: Source, compare target, files to extract, excluded files, filter settings\n\n### JSON Output (`--json`)\n\nAvailable on: `list`, `branch`, `multi-branch`, `extract`\n\nThe `--json` flag outputs machine-readable JSON to stdout and suppresses all human-readable log messages. This is useful for piping to other tools, scripts, and agent workflows.\n\n```bash\n# JSON output for any command\ncg list --json\ncg branch -i @myteam -b \"feature/new\" -m \"Add feature\" --json\ncg multi-branch -b \"feature/migration\" -m \"Migrate\" --json\ncg extract -s feature/other-team --json\n```\n\n### Combining `--dry-run` and `--json`\n\nThe two flags work together — `--dry-run --json` outputs the dry-run preview as structured JSON:\n\n```bash\ncg branch -i @myteam -b \"feature/new\" -m \"Add feature\" --dry-run --json\ncg multi-branch -b \"feature/migration\" -m \"Migrate\" --dry-run --json\ncg extract -s feature/other-team --dry-run --json\n```\n\n### JSON Schema Examples\n\nEvery JSON response includes a `command` field identifying the source command.\n\n**`list --json`**\n\n```json\n{\n  \"command\": \"list\",\n  \"files\": [\n    { \"file\": \"src/index.ts\", \"owners\": [\"@org/team-a\"] },\n    { \"file\": \"src/shared.ts\", \"owners\": [\"@org/team-a\", \"@org/team-b\"] }\n  ],\n  \"filters\": {\n    \"include\": null,\n    \"pathPattern\": null,\n    \"exclusive\": false,\n    \"coOwned\": false\n  }\n}\n```\n\n**`list --group --json`**\n\n```json\n{\n  \"command\": \"list\",\n  \"grouped\": {\n    \"@org/team-a\": [\"src/index.ts\", \"src/shared.ts\"],\n    \"@org/team-b\": [\"src/shared.ts\"]\n  },\n  \"filters\": {\n    \"include\": null,\n    \"pathPattern\": null,\n    \"exclusive\": false,\n    \"coOwned\": false\n  }\n}\n```\n\n**`branch --dry-run --json`**\n\n```json\n{\n  \"command\": \"branch\",\n  \"dryRun\": true,\n  \"owner\": \"@org/team-a\",\n  \"branch\": \"feature/new/team-a\",\n  \"branchExists\": false,\n  \"message\": \"Add feature - @org/team-a\",\n  \"files\": [\"src/index.ts\"],\n  \"excludedFiles\": [\"src/other.ts\"],\n  \"options\": {\n    \"push\": true,\n    \"remote\": \"origin\",\n    \"force\": false,\n    \"pr\": false,\n    \"draftPr\": false,\n    \"noVerify\": false,\n    \"append\": false,\n    \"exclusive\": false,\n    \"coOwned\": false,\n    \"pathPattern\": null\n  }\n}\n```\n\n**`branch --json`** (normal execution)\n\n```json\n{\n  \"command\": \"branch\",\n  \"dryRun\": false,\n  \"success\": true,\n  \"branchName\": \"feature/new/team-a\",\n  \"owner\": \"@org/team-a\",\n  \"files\": [\"src/index.ts\"],\n  \"pushed\": true,\n  \"prUrl\": \"https://github.com/org/repo/pull/42\",\n  \"prNumber\": 42,\n  \"error\": null\n}\n```\n\n**`multi-branch --dry-run --json`**\n\n```json\n{\n  \"command\": \"multi-branch\",\n  \"dryRun\": true,\n  \"owners\": [\n    {\n      \"owner\": \"@org/team-a\",\n      \"branch\": \"feature/migration/team-a\",\n      \"message\": \"Migrate - @org/team-a\",\n      \"files\": [\"src/index.ts\"]\n    },\n    {\n      \"owner\": \"@org/team-b\",\n      \"branch\": \"feature/migration/team-b\",\n      \"message\": \"Migrate - @org/team-b\",\n      \"files\": [\"src/shared.ts\"]\n    }\n  ],\n  \"uncoveredFiles\": [],\n  \"filesWithoutOwners\": [],\n  \"totalFiles\": 2,\n  \"coveredFiles\": 2,\n  \"options\": {\n    \"baseBranch\": \"feature/migration\",\n    \"baseMessage\": \"Migrate\",\n    \"push\": false,\n    \"remote\": \"origin\",\n    \"force\": false,\n    \"pr\": false,\n    \"draftPr\": false,\n    \"noVerify\": false,\n    \"append\": false,\n    \"exclusive\": false,\n    \"coOwned\": false,\n    \"pathPattern\": null,\n    \"defaultOwner\": null\n  }\n}\n```\n\n**`multi-branch --json`** (normal execution)\n\n```json\n{\n  \"command\": \"multi-branch\",\n  \"dryRun\": false,\n  \"success\": true,\n  \"totalOwners\": 2,\n  \"successCount\": 2,\n  \"failureCount\": 0,\n  \"results\": [\n    {\n      \"owner\": \"@org/team-a\",\n      \"branch\": \"feature/migration/team-a\",\n      \"success\": true,\n      \"files\": [\"src/index.ts\"],\n      \"pushed\": true,\n      \"prUrl\": null,\n      \"prNumber\": null,\n      \"error\": null\n    }\n  ]\n}\n```\n\n**`extract --dry-run --json`**\n\n```json\n{\n  \"command\": \"extract\",\n  \"dryRun\": true,\n  \"source\": \"feature/other-team\",\n  \"compareTarget\": \"main\",\n  \"files\": [\"src/component.tsx\"],\n  \"excludedFiles\": [\"src/unrelated.ts\"],\n  \"totalChanged\": 2,\n  \"options\": {\n    \"include\": \"@org/team-a\",\n    \"pathPattern\": null,\n    \"exclusive\": false,\n    \"coOwned\": false,\n    \"compareMain\": false\n  }\n}\n```\n\n**`extract --json`** (normal execution)\n\n```json\n{\n  \"command\": \"extract\",\n  \"dryRun\": false,\n  \"source\": \"feature/other-team\",\n  \"compareTarget\": \"main\",\n  \"files\": [\"src/component.tsx\"],\n  \"totalChanged\": 2\n}\n```\n\n**Error responses** (any command)\n\n```json\n{\n  \"command\": \"branch\",\n  \"error\": \"Error: No staged files found\"\n}\n```\n\n### Piping Examples\n\n```bash\n# Count files per owner\ncg list --group --json | jq '.grouped | to_entries[] | {owner: .key, count: (.value | length)}'\n\n# Get list of branches that would be created\ncg multi-branch -b \"mig\" -m \"Fix\" --dry-run --json | jq '.owners[].branch'\n\n# Find owners with more than 5 files\ncg multi-branch -b \"mig\" -m \"Fix\" --dry-run --json | jq '.owners[] | select(.files | length \u003e 5) | .owner'\n\n# Check if a branch operation succeeded\ncg branch -i @myteam -b \"feat\" -m \"Update\" -p --json | jq '.success'\n\n# List only extracted file paths\ncg extract -s feature/other --json | jq -r '.files[]'\n```\n\n\u003e **Note:** The `recover` command does not support `--dry-run` or `--json` because it is an interactive command with user prompts.\n\n## Contributing\n\n1. Clone the repository\n2. Install dependencies:\n\n```bash\nbun install\n```\n\n3. Make your changes\n4. Run tests:\n\n```bash\nbun test\n```\n\n5. Submit a pull request\n\n## Alternatives\n\n[@snyk/github-codeowners](https://github.com/snyk/github-codeowners)\n\n[codeowners](https://github.com/beaugunderson/codeowners)\n\n## License\n\nMIT ©\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhemandev%2Fcodeowners-git","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhemandev%2Fcodeowners-git","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhemandev%2Fcodeowners-git/lists"}