{"owner":"GitoxideLabs","repo":"gitoxide","hasSkills":true,"totalSkillsCount":4,"totalTokensCount":4412,"categories":["root-instruction","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"gitoxide":{"command":"npx","args":["-y","@modelcontextprotocol/server-gitoxide"]}}},"found":["AGENTS.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"AGENTS.md":"# Copilot Instructions for Gitoxide\n\nThis repository contains `gitoxide` - a pure Rust implementation of Git. This document provides guidance for GitHub Copilot when working with this codebase.\n\n## Project Overview\n\n- **Language**: Rust (MSRV documented in gix/Cargo.toml)\n- **Structure**: Cargo workspace with multiple crates (gix-\\*, gitoxide-core, etc.)\n- **Main crates**: `gix` (library entrypoint), `gitoxide` binary (CLI tools: `gix` and `ein`)\n- **Purpose**: Provide a high-performance, safe Git implementation with both library and CLI interfaces\n\n## Development Practices\n\n### AI Agent Communication\n\n- AI agents communicating through a person's account must identify themselves, for example in issue or PR descriptions and comments.\n- AI assistance that does not replace the person as the speaker, such as proofreading or wording polish, does not require identification.\n- Attributing AI assistance in commit metadata, for example with an `Assisted-by:` or `Co-authored-by:` trailer, is welcome but not required.\n\n### Test-First Development\n\n- Protect against regression and make implementing features easy\n- Keep it practical - the Rust compiler handles mundane things\n- Use git itself as reference implementation; run same tests against git where feasible\n- Never use `.unwrap()` in production code, avoid it in tests in favor of `.expect()` or `?`. Use `gix_error::TestResult` for test functions and helpers.\n- Use `.expect(\"why\")` with context explaining why expectations should hold, but only if it's relevant to the test.\n\n### Error Handling\n\n- Handle all errors, never `unwrap()`\n- Provide error chains making it easy to understand what went wrong\n- Applications built on `gix` use `gix::Result` and `gix::Error`, preserving error context and source locations.\n  Import error helpers, traits, and macros through `gix::error` instead of adding a separate `gix-error` dependency.\n\n#### `gix-error` (preferred for plumbing crates)\n\nPlumbing crates are migrating from `thiserror` enums to `gix-error`. Check whether a crate already\nuses `gix-error` (look at its `Cargo.toml`); if it does, follow the patterns below. If it still uses\n`thiserror`, keep using `thiserror` for consistency within that crate.\n\n- **Public error APIs**: use `gix_error::Result<T>` and `gix_error::Error` for erased or\n  message-based errors at public plumbing boundaries. Preserve concrete error types already exposed\n  by public signatures, including `ExnResult<T, Specific>` and `Exn<Specific>`. This includes public\n  traits, callbacks, iterator items, associated errors, and re-exported APIs.\n  Keep native `io::Result`, standalone concrete-error results, and generic error adapters when they do\n  not expose exceptions. This exemption covers native or operation-specific recovery errors, not\n  shared diagnostics like `Message`. Public message-based errors use `Error` even without an `Exn`\n  wrapper, including `FromStr::Err` and `TryFrom::Error`. Do not introduce public crate-specific or\n  operation-specific forwarding aliases or renamed error exports.\n- **Internal results**: use `Result<T>` for erased or message-based errors in private and\n  `pub(crate)` helpers too. Retain concrete error types when callers benefit from typed recovery\n  or payload access. Use `ExnResult<T, E>` or `ExnMessageResult<T>` when a specific exception type\n  or exception-tree manipulation is actually needed; being private alone is not a reason to\n  introduce an exception-returning wrapper. These aliases and typed construction helpers remain available.\n- **Imports**: import `Result`, `ExnResult`, and `ExnMessageResult` under their canonical names\n  directly from `gix_error` (or their `gix` re-exports), and use their bare names in signatures.\n  Prefer to import `bail` when using `bail!`, via `use gix_error::bail;` or `use gix::error::bail;`,\n  and invoke it without a qualified path.\n- **Porcelain errors**: use the central `gix::Error` and `gix::Result` re-exports at public\n  boundaries that return erased or message-based exceptions.\n- **Static messages**: `gix_error::message(\"something failed\")`\n- **Formatted messages**: `gix_error::message!(\"failed to read {path}\")`\n- **Wrapping callee errors with context**: `.or_raise(|| message(\"context about what failed\"))?`\n- **Standalone error (no callee)**: use `bail!(error)` for an early return with a concrete\n  error or message, such as `bail!(message(\"something went wrong\"))`. For a result expression\n  at a boundary returning `Result`, use `Err(error.raise())`.\n- **Wrapping an `impl Error` with context**: `err.and_raise(message(\"context\"))`\n- **Typed exceptions**: use `.raise_typed()`, `.and_raise_typed(...)`, `.or_raise_typed(...)`, or\n  `.ok_or_raise_typed(...)` when an `Exn<E>` is required; the default helpers return `Error` or `Result`.\n- **Conversion without context**: `.or_error()` converts native errors and exceptions to `Result`.\n  Propagate existing `Result` values directly when the callee already provides enough context.\n- **Closure/callback bounds**: preserve concrete callback errors; use `Result<T>` for erased or\n  message-based errors in public and private APIs. Private callbacks may use `ExnResult<T>`\n  when they need exception-tree operations, or a specific error when useful. Use\n  `.or_raise_erased(...)` to add context or `.or_erased()` to convert when an internal callback\n  requires an erased exception.\n- **`Exn<E>` does NOT implement `std::error::Error`** — this is by design.\n  Convert with `?`, `.into()`, or `.into_error()` when a boundary returns `Error`. Conversion retains\n  the original error types, causes, metadata, and locations; erased errors support downcasting for recovery.\n- **In tests**: `gix_error::TestResult` (also re-exported by `gix_testtools`) accepts exceptions\n  directly with `?`. Public `gix_error::Result` also works with `gix_testtools::Result` through `?`.\n- **Common imports**: `use gix_error::{bail, message, ErrorExt, Result, ResultExt};` plus typed\n  exception aliases as needed.\n- See `gix-error/src/lib.rs` module docs for a full migration guide from `thiserror`\n\n### Commit Messages\n\nFollow \"purposeful conventional commits\" style:\n\n- Write commit messages in Markdown and assume readers view them with syntax highlighting.\n  - Enclose anything that occurs in code, as well as crate names and shell commands, in backticks.\n  - Use Markdown generously whenever markup helps readers understand or navigate the prose.\n  - Use the body to share everything known about what motivated the change, not merely what changed.\n- Use conventional commit prefixes ONLY if message should appear in changelog\n- Breaking changes MUST use `!` before the colon: `change!:`, `remove!:`, `rename!:`, or _scoped_ forms like `feat(gix-odb)!:`\n- Features/fixes visible to users: `feat:`, `fix:`\n- For a changelog-worthy commit touching multiple crates, _scope_ it to the crate that should receive the changelog entry, like `feat!(gix-ref)`.\n- Refactors/chores: no prefix (don't affect users)\n- Examples:\n  - `feat: add Repository::foo() to do great things. (#234)`\n  - `fix: don't panic when calling foo() in a bare repository. (#456)`\n  - `change!: rename Foo to Bar. (#123)`\n  - `feat(gix-odb)!: add a new object lookup API`\n  - `fix(gix-ref)!: reject invalid reference names`\n\n### Code Style\n\n- Do not create persistent Python scripts in this repository. Use Bash for repository automation and script-based tests unless the user explicitly requests otherwise.\n- Follow existing patterns in the codebase\n- Skip stylistic rewrites that increase SLOC after formatting; keep simpler existing forms instead of applying style rules unconditionally.\n- Start new Rust modules as `foo.rs`. Create a module directory only when it contains multiple module files; then use `foo/mod.rs` rather than a sibling `foo.rs` file.\n- No `.unwrap()` - use `.expect(\"context\")` if you are sure this can't fail.\n- Prefer references in plumbing crates to avoid expensive clones\n- Avoid calling `.detach()` unless an owned value is explicitly required. Many `gix` APIs accept attached ids and references directly, so prefer keeping repository-backed handles like `gix::Id` when possible.\n- Name variables holding untyped Git object IDs `<type>_id` or `*_<type>_id` (for example, `commit_id`, `root_tree_id`, or `note_blob_id`) so the object kind is always explicit.\n- Use `gix_parallel::*` for interior mutability primitives\n\n### Path Handling\n\n- Paths are byte-oriented in git (even on Windows via MSYS2 abstraction)\n- Use `gix::path::*` utilities to convert git paths (`BString`) to `OsStr`/`Path` or use custom types\n\n## Building and Testing\n\n### Quick Commands\n\n- `just test` - Run all tests, clippy, journey tests, and try building docs\n- `just check` - Build all code in suitable configurations\n- `just clippy` - Run clippy on all crates\n- `cargo test` - Run unit tests only\n\n### Build Variants\n\n- `cargo build --release` - Default build (big but pretty, ~2.5min)\n- `cargo build --release --no-default-features --features lean` - Lean build (~1.5min)\n- `cargo build --release --no-default-features --features small` - Minimal deps (~46s)\n\n### Test Best Practices\n\n- Test public APIs in the crate's integration tests under `tests/`, using only\n  public interfaces. Reserve in-source unit tests (`#[cfg(test)]` modules) for\n  private or `pub(crate)` functionality that integration tests cannot access.\n  Extend an existing integration test with additional assertions when it already\n  exercises the relevant behavior.\n- Tests must be isolated from the developer's checkout, other worktrees, shared\n  Git metadata, and user configuration. Use fixtures provided by `gix-testtools`;\n  never use the source checkout as a test repository.\n- **Tests of read-only functionality must use read-only fixtures**, such as\n  `gix_testtools::scripted_fixture_read_only()` or the crate's read-only repository\n  helper. Use `scripted_fixture_writable()` only when exercising functionality\n  that writes. Prepare required repository states during fixture creation, not\n  by mutating a shared read-only fixture in the test.\n- For setup that is easier in Rust (such as binary corruption), use\n  `gix_testtools::scripted_fixture_read_only_with_post(script, version, |fixture| { ... })`.\n  The script creates the repository; the Rust closure prepares it before caching\n  and returns `(fixture_path, value)` through the helper. Only mutate inside\n  `if let gix_testtools::FixtureState::Uninitialized(path) = fixture { ... }`.\n  The closure also runs for `FixtureState::Fresh` (cached or archived fixtures),\n  where it must only read or compute return values. Increment `version` whenever\n  the post-processing behavior changes to invalidate the cache. See the API docs\n  in `tests/tools/src/lib.rs` and the commit-graph regression test in\n  `gix/tests/gix/repository/revision.rs` for an example.\n- Git invocations in test code must go through `gix_testtools::git()`,\n  `git_command()`, or fixture scripts executed by `gix-testtools`. Do not spawn\n  Git directly with `Command::new(\"git\")` or ad hoc subprocess wrappers. If a test needs unsupported\n  command options, extend the shared isolated helper instead of bypassing it.\n  `run_git()` and `invoke_bash()` share this isolation. Subprocesses that invoke\n  Git indirectly must use `gix_testtools::configure_git_environment()` too.\n  Tests of APIs that read the process environment must isolate it before\n  exercising those APIs or changing environment variables. In `#[serial]` tests,\n  keep a `gix_testtools::isolate_git_environment()` guard alive for the entire test;\n  it restores only its recorded changes on drop. Chain test-specific overrides\n  onto that guard or use a separate `gix_testtools::Env` guard to restore them too.\n  All concurrent environment access must participate in the same serialization. Otherwise, use\n  `gix_testtools::run_in_isolated_process()` so changes cannot race other tests.\n  Restore working-directory changes separately with `gix_testtools::set_current_dir()`.\n- Setting a subprocess's working directory or passing `git -C` is not isolation:\n  inherited `GIT_DIR`, `GIT_WORK_TREE`, `GIT_COMMON_DIR`, `GIT_INDEX_FILE`, or\n  object-directory variables can redirect operations outside the fixture. Tests\n  that exercise such overrides must scope them to disposable test repositories.\n  Open repositories through the crate's isolated test helper or isolated `gix`\n  options, with only test-specific configuration overrides.\n- Run tests before making changes to understand existing issues\n- Use `GIX_TEST_IGNORE_ARCHIVES=1` when testing on macOS/Windows\n- Journey tests validate CLI behavior end-to-end\n- Fixture scripts should document what behavior they exercise and what makes\n  the fixture special. Leave clear-text breadcrumbs so future readers can tell\n  which details are essential to the test. Use markdown doc-strings when available.\n- Stabilize fixtures whose generated contents can vary by using the\n  `_needs_archive` variants of functions in `gix-testtools`; these always use\n  packaged archived fixtures instead of platform-local generated output.\n- Use assertion descriptions to state what is being asserted. For `assert*!`\n  macros this is the last parameter; for `insta::assert*` macros it is the\n  second parameter. Prefer messages that explain the invariant, not just that an\n  assertion failed.\n\n## Architecture Decisions\n\n### Plumbing vs Porcelain\n\n- **Plumbing crates**: Low-level, take references, expose mutable parts as arguments\n- **Porcelain (gix)**: High-level, convenient, may clone Repository for user convenience\n- Platforms: cheap to create, keep reference to Repository\n- Caches: more expensive, clone `Repository` or free of lifetimes\n\n### Options vs Context\n\n- Use `Options` for branching behavior configuration (can be defaulted)\n- Use `Context` for data required for operation (cannot be defaulted)\n\n## Crate Organization\n\n### Common Crates\n\n- `gix`: Main library entrypoint (porcelain)\n- `gix-object`, `gix-ref`, `gix-config`: Core git data structures\n- `gix-odb`, `gix-pack`: Object database and pack handling\n- `gix-diff`, `gix-merge`, `gix-status`: Operations\n- `gitoxide-core`: Shared CLI functionality\n\n## Documentation\n\n- High-level docs: README.md, CONTRIBUTING.md, DEVELOPMENT.md\n- Crate status: crate-status.md\n- Stability guide: STABILITY.md\n- Always update docs if directly related to code changes\n\n## CI and Releases\n\n- Ubuntu-latest git version is the compatibility target\n- `cargo smart-release` for releases (driven by commit messages)\n- Every commit must be self-contained and pass CI independently\n   - Feel free to run `etc/scripts/ci-check-local.sh --thorough` until it passes as proxy, as running every commit against CI isn't feasible.\n- Keep breaking changes and all adaptations required to build and test the workspace in the same commit\n- When such a commit touches multiple crates, _scope_ its conventional commit message to the crate whose changelog should receive the entry\n\n## When Suggesting Changes\n\n1. Understand the plumbing vs porcelain distinction\n2. Check existing patterns in similar crates\n3. Follow error handling conventions strictly\n4. Ensure changes work with feature flags (small, lean, max, max-pure)\n5. Consider impact on both library and CLI users\n6. Test against real git repositories when possible\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/plugin.json)"},"files":{"AGENTS.md":"# Copilot Instructions for Gitoxide\n\nThis repository contains `gitoxide` - a pure Rust implementation of Git. This document provides guidance for GitHub Copilot when working with this codebase.\n\n## Project Overview\n\n- **Language**: Rust (MSRV documented in gix/Cargo.toml)\n- **Structure**: Cargo workspace with multiple crates (gix-\\*, gitoxide-core, etc.)\n- **Main crates**: `gix` (library entrypoint), `gitoxide` binary (CLI tools: `gix` and `ein`)\n- **Purpose**: Provide a high-performance, safe Git implementation with both library and CLI interfaces\n\n## Development Practices\n\n### AI Agent Communication\n\n- AI agents communicating through a person's account must identify themselves, for example in issue or PR descriptions and comments.\n- AI assistance that does not replace the person as the speaker, such as proofreading or wording polish, does not require identification.\n- Attributing AI assistance in commit metadata, for example with an `Assisted-by:` or `Co-authored-by:` trailer, is welcome but not required.\n\n### Test-First Development\n\n- Protect against regression and make implementing features easy\n- Keep it practical - the Rust compiler handles mundane things\n- Use git itself as reference implementation; run same tests against git where feasible\n- Never use `.unwrap()` in production code, avoid it in tests in favor of `.expect()` or `?`. Use `gix_error::TestResult` for test functions and helpers.\n- Use `.expect(\"why\")` with context explaining why expectations should hold, but only if it's relevant to the test.\n\n### Error Handling\n\n- Handle all errors, never `unwrap()`\n- Provide error chains making it easy to understand what went wrong\n- Applications built on `gix` use `gix::Result` and `gix::Error`, preserving error context and source locations.\n  Import error helpers, traits, and macros through `gix::error` instead of adding a separate `gix-error` dependency.\n\n#### `gix-error` (preferred for plumbing crates)\n\nPlumbing crates are migrating from `thiserror` enums to `gix-error`. Check whether a crate already\nuses `gix-error` (look at its `Cargo.toml`); if it does, follow the patterns below. If it still uses\n`thiserror`, keep using `thiserror` for consistency within that crate.\n\n- **Public error APIs**: use `gix_error::Result<T>` and `gix_error::Error` for erased or\n  message-based errors at public plumbing boundaries. Preserve concrete error types already exposed\n  by public signatures, including `ExnResult<T, Specific>` and `Exn<Specific>`. This includes public\n  traits, callbacks, iterator items, associated errors, and re-exported APIs.\n  Keep native `io::Result`, standalone concrete-error results, and generic error adapters when they do\n  not expose exceptions. This exemption covers native or operation-specific recovery errors, not\n  shared diagnostics like `Message`. Public message-based errors use `Error` even without an `Exn`\n  wrapper, including `FromStr::Err` and `TryFrom::Error`. Do not introduce public crate-specific or\n  operation-specific forwarding aliases or renamed error exports.\n- **Internal results**: use `Result<T>` for erased or message-based errors in private and\n  `pub(crate)` helpers too. Retain concrete error types when callers benefit from typed recovery\n  or payload access. Use `ExnResult<T, E>` or `ExnMessageResult<T>` when a specific exception type\n  or exception-tree manipulation is actually needed; being private alone is not a reason to\n  introduce an exception-returning wrapper. These aliases and typed construction helpers remain available.\n- **Imports**: import `Result`, `ExnResult`, and `ExnMessageResult` under their canonical names\n  directly from `gix_error` (or their `gix` re-exports), and use their bare names in signatures.\n  Prefer to import `bail` when using `bail!`, via `use gix_error::bail;` or `use gix::error::bail;`,\n  and invoke it without a qualified path.\n- **Porcelain errors**: use the central `gix::Error` and `gix::Result` re-exports at public\n  boundaries that return erased or message-based exceptions.\n- **Static messages**: `gix_error::message(\"something failed\")`\n- **Formatted messages**: `gix_error::message!(\"failed to read {path}\")`\n- **Wrapping callee errors with context**: `.or_raise(|| message(\"context about what failed\"))?`\n- **Standalone error (no callee)**: use `bail!(error)` for an early return with a concrete\n  error or message, such as `bail!(message(\"something went wrong\"))`. For a result expression\n  at a boundary returning `Result`, use `Err(error.raise())`.\n- **Wrapping an `impl Error` with context**: `err.and_raise(message(\"context\"))`\n- **Typed exceptions**: use `.raise_typed()`, `.and_raise_typed(...)`, `.or_raise_typed(...)`, or\n  `.ok_or_raise_typed(...)` when an `Exn<E>` is required; the default helpers return `Error` or `Result`.\n- **Conversion without context**: `.or_error()` converts native errors and exceptions to `Result`.\n  Propagate existing `Result` values directly when the callee already provides enough context.\n- **Closure/callback bounds**: preserve concrete callback errors; use `Result<T>` for erased or\n  message-based errors in public and private APIs. Private callbacks may use `ExnResult<T>`\n  when they need exception-tree operations, or a specific error when useful. Use\n  `.or_raise_erased(...)` to add context or `.or_erased()` to convert when an internal callback\n  requires an erased exception.\n- **`Exn<E>` does NOT implement `std::error::Error`** — this is by design.\n  Convert with `?`, `.into()`, or `.into_error()` when a boundary returns `Error`. Conversion retains\n  the original error types, causes, metadata, and locations; erased errors support downcasting for recovery.\n- **In tests**: `gix_error::TestResult` (also re-exported by `gix_testtools`) accepts exceptions\n  directly with `?`. Public `gix_error::Result` also works with `gix_testtools::Result` through `?`.\n- **Common imports**: `use gix_error::{bail, message, ErrorExt, Result, ResultExt};` plus typed\n  exception aliases as needed.\n- See `gix-error/src/lib.rs` module docs for a full migration guide from `thiserror`\n\n### Commit Messages\n\nFollow \"purposeful conventional commits\" style:\n\n- Write commit messages in Markdown and assume readers view them with syntax highlighting.\n  - Enclose anything that occurs in code, as well as crate names and shell commands, in backticks.\n  - Use Markdown generously whenever markup helps readers understand or navigate the prose.\n  - Use the body to share everything known about what motivated the change, not merely what changed.\n- Use conventional commit prefixes ONLY if message should appear in changelog\n- Breaking changes MUST use `!` before the colon: `change!:`, `remove!:`, `rename!:`, or _scoped_ forms like `feat(gix-odb)!:`\n- Features/fixes visible to users: `feat:`, `fix:`\n- For a changelog-worthy commit touching multiple crates, _scope_ it to the crate that should receive the changelog entry, like `feat!(gix-ref)`.\n- Refactors/chores: no prefix (don't affect users)\n- Examples:\n  - `feat: add Repository::foo() to do great things. (#234)`\n  - `fix: don't panic when calling foo() in a bare repository. (#456)`\n  - `change!: rename Foo to Bar. (#123)`\n  - `feat(gix-odb)!: add a new object lookup API`\n  - `fix(gix-ref)!: reject invalid reference names`\n\n### Code Style\n\n- Do not create persistent Python scripts in this repository. Use Bash for repository automation and script-based tests unless the user explicitly requests otherwise.\n- Follow existing patterns in the codebase\n- Skip stylistic rewrites that increase SLOC after formatting; keep simpler existing forms instead of applying style rules unconditionally.\n- Start new Rust modules as `foo.rs`. Create a module directory only when it contains multiple module files; then use `foo/mod.rs` rather than a sibling `foo.rs` file.\n- No `.unwrap()` - use `.expect(\"context\")` if you are sure this can't fail.\n- Prefer references in plumbing crates to avoid expensive clones\n- Avoid calling `.detach()` unless an owned value is explicitly required. Many `gix` APIs accept attached ids and references directly, so prefer keeping repository-backed handles like `gix::Id` when possible.\n- Name variables holding untyped Git object IDs `<type>_id` or `*_<type>_id` (for example, `commit_id`, `root_tree_id`, or `note_blob_id`) so the object kind is always explicit.\n- Use `gix_parallel::*` for interior mutability primitives\n\n### Path Handling\n\n- Paths are byte-oriented in git (even on Windows via MSYS2 abstraction)\n- Use `gix::path::*` utilities to convert git paths (`BString`) to `OsStr`/`Path` or use custom types\n\n## Building and Testing\n\n### Quick Commands\n\n- `just test` - Run all tests, clippy, journey tests, and try building docs\n- `just check` - Build all code in suitable configurations\n- `just clippy` - Run clippy on all crates\n- `cargo test` - Run unit tests only\n\n### Build Variants\n\n- `cargo build --release` - Default build (big but pretty, ~2.5min)\n- `cargo build --release --no-default-features --features lean` - Lean build (~1.5min)\n- `cargo build --release --no-default-features --features small` - Minimal deps (~46s)\n\n### Test Best Practices\n\n- Test public APIs in the crate's integration tests under `tests/`, using only\n  public interfaces. Reserve in-source unit tests (`#[cfg(test)]` modules) for\n  private or `pub(crate)` functionality that integration tests cannot access.\n  Extend an existing integration test with additional assertions when it already\n  exercises the relevant behavior.\n- Tests must be isolated from the developer's checkout, other worktrees, shared\n  Git metadata, and user configuration. Use fixtures provided by `gix-testtools`;\n  never use the source checkout as a test repository.\n- **Tests of read-only functionality must use read-only fixtures**, such as\n  `gix_testtools::scripted_fixture_read_only()` or the crate's read-only repository\n  helper. Use `scripted_fixture_writable()` only when exercising functionality\n  that writes. Prepare required repository states during fixture creation, not\n  by mutating a shared read-only fixture in the test.\n- For setup that is easier in Rust (such as binary corruption), use\n  `gix_testtools::scripted_fixture_read_only_with_post(script, version, |fixture| { ... })`.\n  The script creates the repository; the Rust closure prepares it before caching\n  and returns `(fixture_path, value)` through the helper. Only mutate inside\n  `if let gix_testtools::FixtureState::Uninitialized(path) = fixture { ... }`.\n  The closure also runs for `FixtureState::Fresh` (cached or archived fixtures),\n  where it must only read or compute return values. Increment `version` whenever\n  the post-processing behavior changes to invalidate the cache. See the API docs\n  in `tests/tools/src/lib.rs` and the commit-graph regression test in\n  `gix/tests/gix/repository/revision.rs` for an example.\n- Git invocations in test code must go through `gix_testtools::git()`,\n  `git_command()`, or fixture scripts executed by `gix-testtools`. Do not spawn\n  Git directly with `Command::new(\"git\")` or ad hoc subprocess wrappers. If a test needs unsupported\n  command options, extend the shared isolated helper instead of bypassing it.\n  `run_git()` and `invoke_bash()` share this isolation. Subprocesses that invoke\n  Git indirectly must use `gix_testtools::configure_git_environment()` too.\n  Tests of APIs that read the process environment must isolate it before\n  exercising those APIs or changing environment variables. In `#[serial]` tests,\n  keep a `gix_testtools::isolate_git_environment()` guard alive for the entire test;\n  it restores only its recorded changes on drop. Chain test-specific overrides\n  onto that guard or use a separate `gix_testtools::Env` guard to restore them too.\n  All concurrent environment access must participate in the same serialization. Otherwise, use\n  `gix_testtools::run_in_isolated_process()` so changes cannot race other tests.\n  Restore working-directory changes separately with `gix_testtools::set_current_dir()`.\n- Setting a subprocess's working directory or passing `git -C` is not isolation:\n  inherited `GIT_DIR`, `GIT_WORK_TREE`, `GIT_COMMON_DIR`, `GIT_INDEX_FILE`, or\n  object-directory variables can redirect operations outside the fixture. Tests\n  that exercise such overrides must scope them to disposable test repositories.\n  Open repositories through the crate's isolated test helper or isolated `gix`\n  options, with only test-specific configuration overrides.\n- Run tests before making changes to understand existing issues\n- Use `GIX_TEST_IGNORE_ARCHIVES=1` when testing on macOS/Windows\n- Journey tests validate CLI behavior end-to-end\n- Fixture scripts should document what behavior they exercise and what makes\n  the fixture special. Leave clear-text breadcrumbs so future readers can tell\n  which details are essential to the test. Use markdown doc-strings when available.\n- Stabilize fixtures whose generated contents can vary by using the\n  `_needs_archive` variants of functions in `gix-testtools`; these always use\n  packaged archived fixtures instead of platform-local generated output.\n- Use assertion descriptions to state what is being asserted. For `assert*!`\n  macros this is the last parameter; for `insta::assert*` macros it is the\n  second parameter. Prefer messages that explain the invariant, not just that an\n  assertion failed.\n\n## Architecture Decisions\n\n### Plumbing vs Porcelain\n\n- **Plumbing crates**: Low-level, take references, expose mutable parts as arguments\n- **Porcelain (gix)**: High-level, convenient, may clone Repository for user convenience\n- Platforms: cheap to create, keep reference to Repository\n- Caches: more expensive, clone `Repository` or free of lifetimes\n\n### Options vs Context\n\n- Use `Options` for branching behavior configuration (can be defaulted)\n- Use `Context` for data required for operation (cannot be defaulted)\n\n## Crate Organization\n\n### Common Crates\n\n- `gix`: Main library entrypoint (porcelain)\n- `gix-object`, `gix-ref`, `gix-config`: Core git data structures\n- `gix-odb`, `gix-pack`: Object database and pack handling\n- `gix-diff`, `gix-merge`, `gix-status`: Operations\n- `gitoxide-core`: Shared CLI functionality\n\n## Documentation\n\n- High-level docs: README.md, CONTRIBUTING.md, DEVELOPMENT.md\n- Crate status: crate-status.md\n- Stability guide: STABILITY.md\n- Always update docs if directly related to code changes\n\n## CI and Releases\n\n- Ubuntu-latest git version is the compatibility target\n- `cargo smart-release` for releases (driven by commit messages)\n- Every commit must be self-contained and pass CI independently\n   - Feel free to run `etc/scripts/ci-check-local.sh --thorough` until it passes as proxy, as running every commit against CI isn't feasible.\n- Keep breaking changes and all adaptations required to build and test the workspace in the same commit\n- When such a commit touches multiple crates, _scope_ its conventional commit message to the crate whose changelog should receive the entry\n\n## When Suggesting Changes\n\n1. Understand the plumbing vs porcelain distinction\n2. Check existing patterns in similar crates\n3. Follow error handling conventions strictly\n4. Ensure changes work with feature flags (small, lean, max, max-pure)\n5. Consider impact on both library and CLI users\n6. Test against real git repositories when possible\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Copilot Instructions for Gitoxide\n\nThis repository contains `gitoxide` - a pure Rust implementation of Git. This document provides guidance for GitHub Copilot when working with this codebase.\n\n## Project Overview\n\n- **Language**: Rust (MSRV documented in gix/Cargo.toml)\n- **Structure**: Cargo workspace with multiple crates (gix-\\*, gitoxide-core, etc.)\n- **Main crates**: `gix` (library entrypoint), `gitoxide` binary (CLI tools: `gix` and `ein`)\n- **Purpose**: Provide a high-performance, safe Git implementation with both library and CLI interfaces\n\n## Development Practices\n\n### AI Agent Communication\n\n- AI agents communicating through a person's account must identify themselves, for example in issue or PR descriptions and comments.\n- AI assistance that does not replace the person as the speaker, such as proofreading or wording polish, does not require identification.\n- Attributing AI assistance in commit metadata, for example with an `Assisted-by:` or `Co-authored-by:` trailer, is welcome but not required.\n\n### Test-First Development\n\n- Protect against regression and make implementing features easy\n- Keep it practical - the Rust compiler handles mundane things\n- Use git itself as reference implementation; run same tests against git where feasible\n- Never use `.unwrap()` in production code, avoid it in tests in favor of `.expect()` or `?`. Use `gix_error::TestResult` for test functions and helpers.\n- Use `.expect(\"why\")` with context explaining why expectations should hold, but only if it's relevant to the test.\n\n### Error Handling\n\n- Handle all errors, never `unwrap()`\n- Provide error chains making it easy to understand what went wrong\n- Applications built on `gix` use `gix::Result` and `gix::Error`, preserving error context and source locations.\n  Import error helpers, traits, and macros through `gix::error` instead of adding a separate `gix-error` dependency.\n\n#### `gix-error` (preferred for plumbing crates)\n\nPlumbing crates are migrating from `thiserror` enums to `gix-error`. Check whether a crate already\nuses `gix-error` (look at its `Cargo.toml`); if it does, follow the patterns below. If it still uses\n`thiserror`, keep using `thiserror` for consistency within that crate.\n\n- **Public error APIs**: use `gix_error::Result<T>` and `gix_error::Error` for erased or\n  message-based errors at public plumbing boundaries. Preserve concrete error types already exposed\n  by public signatures, including `ExnResult<T, Specific>` and `Exn<Specific>`. This includes public\n  traits, callbacks, iterator items, associated errors, and re-exported APIs.\n  Keep native `io::Result`, standalone concrete-error results, and generic error adapters when they do\n  not expose exceptions. This exemption covers native or operation-specific recovery errors, not\n  shared diagnostics like `Message`. Public message-based errors use `Error` even without an `Exn`\n  wrapper, including `FromStr::Err` and `TryFrom::Error`. Do not introduce public crate-specific or\n  operation-specific forwarding aliases or renamed error exports.\n- **Internal results**: use `Result<T>` for erased or message-based errors in private and\n  `pub(crate)` helpers too. Retain concrete error types when callers benefit from typed recovery\n  or payload access. Use `ExnResult<T, E>` or `ExnMessageResult<T>` when a specific exception type\n  or exception-tree manipulation is actually needed; being private alone is not a reason to\n  introduce an exception-returning wrapper. These aliases and typed construction helpers remain available.\n- **Imports**: import `Result`, `ExnResult`, and `ExnMessageResult` under their canonical names\n  directly from `gix_error` (or their `gix` re-exports), and use their bare names in signatures.\n  Prefer to import `bail` when using `bail!`, via `use gix_error::bail;` or `use gix::error::bail;`,\n  and invoke it without a qualified path.\n- **Porcelain errors**: use the central `gix::Error` and `gix::Result` re-exports at public\n  boundaries that return erased or message-based exceptions.\n- **Static messages**: `gix_error::message(\"something failed\")`\n- **Formatted messages**: `gix_error::message!(\"failed to read {path}\")`\n- **Wrapping callee errors with context**: `.or_raise(|| message(\"context about what failed\"))?`\n- **Standalone error (no callee)**: use `bail!(error)` for an early return with a concrete\n  error or message, such as `bail!(message(\"something went wrong\"))`. For a result expression\n  at a boundary returning `Result`, use `Err(error.raise())`.\n- **Wrapping an `impl Error` with context**: `err.and_raise(message(\"context\"))`\n- **Typed exceptions**: use `.raise_typed()`, `.and_raise_typed(...)`, `.or_raise_typed(...)`, or\n  `.ok_or_raise_typed(...)` when an `Exn<E>` is required; the default helpers return `Error` or `Result`.\n- **Conversion without context**: `.or_error()` converts native errors and exceptions to `Result`.\n  Propagate existing `Result` values directly when the callee already provides enough context.\n- **Closure/callback bounds**: preserve concrete callback errors; use `Result<T>` for erased or\n  message-based errors in public and private APIs. Private callbacks may use `ExnResult<T>`\n  when they need exception-tree operations, or a specific error when useful. Use\n  `.or_raise_erased(...)` to add context or `.or_erased()` to convert when an internal callback\n  requires an erased exception.\n- **`Exn<E>` does NOT implement `std::error::Error`** — this is by design.\n  Convert with `?`, `.into()`, or `.into_error()` when a boundary returns `Error`. Conversion retains\n  the original error types, causes, metadata, and locations; erased errors support downcasting for recovery.\n- **In tests**: `gix_error::TestResult` (also re-exported by `gix_testtools`) accepts exceptions\n  directly with `?`. Public `gix_error::Result` also works with `gix_testtools::Result` through `?`.\n- **Common imports**: `use gix_error::{bail, message, ErrorExt, Result, ResultExt};` plus typed\n  exception aliases as needed.\n- See `gix-error/src/lib.rs` module docs for a full migration guide from `thiserror`\n\n### Commit Messages\n\nFollow \"purposeful conventional commits\" style:\n\n- Write commit messages in Markdown and assume readers view them with syntax highlighting.\n  - Enclose anything that occurs in code, as well as crate names and shell commands, in backticks.\n  - Use Markdown generously whenever markup helps readers understand or navigate the prose.\n  - Use the body to share everything known about what motivated the change, not merely what changed.\n- Use conventional commit prefixes ONLY if message should appear in changelog\n- Breaking changes MUST use `!` before the colon: `change!:`, `remove!:`, `rename!:`, or _scoped_ forms like `feat(gix-odb)!:`\n- Features/fixes visible to users: `feat:`, `fix:`\n- For a changelog-worthy commit touching multiple crates, _scope_ it to the crate that should receive the changelog entry, like `feat!(gix-ref)`.\n- Refactors/chores: no prefix (don't affect users)\n- Examples:\n  - `feat: add Repository::foo() to do great things. (#234)`\n  - `fix: don't panic when calling foo() in a bare repository. (#456)`\n  - `change!: rename Foo to Bar. (#123)`\n  - `feat(gix-odb)!: add a new object lookup API`\n  - `fix(gix-ref)!: reject invalid reference names`\n\n### Code Style\n\n- Do not create persistent Python scripts in this repository. Use Bash for repository automation and script-based tests unless the user explicitly requests otherwise.\n- Follow existing patterns in the codebase\n- Skip stylistic rewrites that increase SLOC after formatting; keep simpler existing forms instead of applying style rules unconditionally.\n- Start new Rust modules as `foo.rs`. Create a module directory only when it contains multiple module files; then use `foo/mod.rs` rather than a sibling `foo.rs` file.\n- No `.unwrap()` - use `.expect(\"context\")` if you are sure this can't fail.\n- Prefer references in plumbing crates to avoid expensive clones\n- Avoid calling `.detach()` unless an owned value is explicitly required. Many `gix` APIs accept attached ids and references directly, so prefer keeping repository-backed handles like `gix::Id` when possible.\n- Name variables holding untyped Git object IDs `<type>_id` or `*_<type>_id` (for example, `commit_id`, `root_tree_id`, or `note_blob_id`) so the object kind is always explicit.\n- Use `gix_parallel::*` for interior mutability primitives\n\n### Path Handling\n\n- Paths are byte-oriented in git (even on Windows via MSYS2 abstraction)\n- Use `gix::path::*` utilities to convert git paths (`BString`) to `OsStr`/`Path` or use custom types\n\n## Building and Testing\n\n### Quick Commands\n\n- `just test` - Run all tests, clippy, journey tests, and try building docs\n- `just check` - Build all code in suitable configurations\n- `just clippy` - Run clippy on all crates\n- `cargo test` - Run unit tests only\n\n### Build Variants\n\n- `cargo build --release` - Default build (big but pretty, ~2.5min)\n- `cargo build --release --no-default-features --features lean` - Lean build (~1.5min)\n- `cargo build --release --no-default-features --features small` - Minimal deps (~46s)\n\n### Test Best Practices\n\n- Test public APIs in the crate's integration tests under `tests/`, using only\n  public interfaces. Reserve in-source unit tests (`#[cfg(test)]` modules) for\n  private or `pub(crate)` functionality that integration tests cannot access.\n  Extend an existing integration test with additional assertions when it already\n  exercises the relevant behavior.\n- Tests must be isolated from the developer's checkout, other worktrees, shared\n  Git metadata, and user configuration. Use fixtures provided by `gix-testtools`;\n  never use the source checkout as a test repository.\n- **Tests of read-only functionality must use read-only fixtures**, such as\n  `gix_testtools::scripted_fixture_read_only()` or the crate's read-only repository\n  helper. Use `scripted_fixture_writable()` only when exercising functionality\n  that writes. Prepare required repository states during fixture creation, not\n  by mutating a shared read-only fixture in the test.\n- For setup that is easier in Rust (such as binary corruption), use\n  `gix_testtools::scripted_fixture_read_only_with_post(script, version, |fixture| { ... })`.\n  The script creates the repository; the Rust closure prepares it before caching\n  and returns `(fixture_path, value)` through the helper. Only mutate inside\n  `if let gix_testtools::FixtureState::Uninitialized(path) = fixture { ... }`.\n  The closure also runs for `FixtureState::Fresh` (cached or archived fixtures),\n  where it must only read or compute return values. Increment `version` whenever\n  the post-processing behavior changes to invalidate the cache. See the API docs\n  in `tests/tools/src/lib.rs` and the commit-graph regression test in\n  `gix/tests/gix/repository/revision.rs` for an example.\n- Git invocations in test code must go through `gix_testtools::git()`,\n  `git_command()`, or fixture scripts executed by `gix-testtools`. Do not spawn\n  Git directly with `Command::new(\"git\")` or ad hoc subprocess wrappers. If a test needs unsupported\n  command options, extend the shared isolated helper instead of bypassing it.\n  `run_git()` and `invoke_bash()` share this isolation. Subprocesses that invoke\n  Git indirectly must use `gix_testtools::configure_git_environment()` too.\n  Tests of APIs that read the process environment must isolate it before\n  exercising those APIs or changing environment variables. In `#[serial]` tests,\n  keep a `gix_testtools::isolate_git_environment()` guard alive for the entire test;\n  it restores only its recorded changes on drop. Chain test-specific overrides\n  onto that guard or use a separate `gix_testtools::Env` guard to restore them too.\n  All concurrent environment access must participate in the same serialization. Otherwise, use\n  `gix_testtools::run_in_isolated_process()` so changes cannot race other tests.\n  Restore working-directory changes separately with `gix_testtools::set_current_dir()`.\n- Setting a subprocess's working directory or passing `git -C` is not isolation:\n  inherited `GIT_DIR`, `GIT_WORK_TREE`, `GIT_COMMON_DIR`, `GIT_INDEX_FILE`, or\n  object-directory variables can redirect operations outside the fixture. Tests\n  that exercise such overrides must scope them to disposable test repositories.\n  Open repositories through the crate's isolated test helper or isolated `gix`\n  options, with only test-specific configuration overrides.\n- Run tests before making changes to understand existing issues\n- Use `GIX_TEST_IGNORE_ARCHIVES=1` when testing on macOS/Windows\n- Journey tests validate CLI behavior end-to-end\n- Fixture scripts should document what behavior they exercise and what makes\n  the fixture special. Leave clear-text breadcrumbs so future readers can tell\n  which details are essential to the test. Use markdown doc-strings when available.\n- Stabilize fixtures whose generated contents can vary by using the\n  `_needs_archive` variants of functions in `gix-testtools`; these always use\n  packaged archived fixtures instead of platform-local generated output.\n- Use assertion descriptions to state what is being asserted. For `assert*!`\n  macros this is the last parameter; for `insta::assert*` macros it is the\n  second parameter. Prefer messages that explain the invariant, not just that an\n  assertion failed.\n\n## Architecture Decisions\n\n### Plumbing vs Porcelain\n\n- **Plumbing crates**: Low-level, take references, expose mutable parts as arguments\n- **Porcelain (gix)**: High-level, convenient, may clone Repository for user convenience\n- Platforms: cheap to create, keep reference to Repository\n- Caches: more expensive, clone `Repository` or free of lifetimes\n\n### Options vs Context\n\n- Use `Options` for branching behavior configuration (can be defaulted)\n- Use `Context` for data required for operation (cannot be defaulted)\n\n## Crate Organization\n\n### Common Crates\n\n- `gix`: Main library entrypoint (porcelain)\n- `gix-object`, `gix-ref`, `gix-config`: Core git data structures\n- `gix-odb`, `gix-pack`: Object database and pack handling\n- `gix-diff`, `gix-merge`, `gix-status`: Operations\n- `gitoxide-core`: Shared CLI functionality\n\n## Documentation\n\n- High-level docs: README.md, CONTRIBUTING.md, DEVELOPMENT.md\n- Crate status: crate-status.md\n- Stability guide: STABILITY.md\n- Always update docs if directly related to code changes\n\n## CI and Releases\n\n- Ubuntu-latest git version is the compatibility target\n- `cargo smart-release` for releases (driven by commit messages)\n- Every commit must be self-contained and pass CI independently\n   - Feel free to run `etc/scripts/ci-check-local.sh --thorough` until it passes as proxy, as running every commit against CI isn't feasible.\n- Keep breaking changes and all adaptations required to build and test the workspace in the same commit\n- When such a commit touches multiple crates, _scope_ its conventional commit message to the crate whose changelog should receive the entry\n\n## When Suggesting Changes\n\n1. Understand the plumbing vs porcelain distinction\n2. Check existing patterns in similar crates\n3. Follow error handling conventions strictly\n4. Ensure changes work with feature flags (small, lean, max, max-pure)\n5. Consider impact on both library and CLI users\n6. Test against real git repositories when possible\n","isInternal":false,"tokens":3512,"sizeBytes":15320},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":200},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":186},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":179}],"systemPromptSnippet":"<yakaai_skills repo=\"GitoxideLabs/gitoxide\">\n<!-- File: AGENTS.md (Tokens: ~3512 | Category: root-instruction) -->\n# Copilot Instructions for Gitoxide\n\nThis repository contains `gitoxide` - a pure Rust implementation of Git. This document provides guidance for GitHub Copilot when working with this codebase.\n\n## Project Overview\n\n- **Language**: Rust (MSRV documented in gix/Cargo.toml)\n- **Structure**: Cargo workspace with multiple crates (gix-\\*, gitoxide-core, etc.)\n- **Main crates**: `gix` (library entrypoint), `gitoxide` binary (CLI tools: `gix` and `ein`)\n- **Purpose**: Provide a high-performance, safe Git implementation with both library and CLI interfaces\n\n## Development Practices\n\n### AI Agent Communication\n\n- AI agents communicating through a person's account must identify themselves, for example in issue or PR descriptions and comments.\n- AI assistance that does not replace the person as the speaker, such as proofreading or wording polish, does not require identification.\n- Attributing AI assistance in commit metadata, for example with an `Assisted-by:` or `Co-authored-by:` trailer, is welcome but not required.\n\n### Test-First Development\n\n- Protect against regression and make implementing features easy\n- Keep it practical - the Rust compiler handles mundane things\n- Use git itself as reference implementation; run same tests against git where feasible\n- Never use `.unwrap()` in production code, avoid it in tests in favor of `.expect()` or `?`. Use `gix_error::TestResult` for test functions and helpers.\n- Use `.expect(\"why\")` with context explaining why expectations should hold, but only if it's relevant to the test.\n\n### Error Handling\n\n- Handle all errors, never `unwrap()`\n- Provide error chains making it easy to understand what went wrong\n- Applications built on `gix` use `gix::Result` and `gix::Error`, preserving error context and source locations.\n  Import error helpers, traits, and macros through `gix::error` instead of adding a separate `gix-error` dependency.\n\n#### `gix-error` (preferred for plumbing crates)\n\nPlumbing crates are migrating from `thiserror` enums to `gix-error`. Check whether a crate already\nuses `gix-error` (look at its `Cargo.toml`); if it does, follow the patterns below. If it still uses\n`thiserror`, keep using `thiserror` for consistency within that crate.\n\n- **Public error APIs**: use `gix_error::Result<T>` and `gix_error::Error` for erased or\n  message-based errors at public plumbing boundaries. Preserve concrete error types already exposed\n  by public signatures, including `ExnResult<T, Specific>` and `Exn<Specific>`. This includes public\n  traits, callbacks, iterator items, associated errors, and re-exported APIs.\n  Keep native `io::Result`, standalone concrete-error results, and generic error adapters when they do\n  not expose exceptions. This exemption covers native or operation-specific recovery errors, not\n  shared diagnostics like `Message`. Public message-based errors use `Error` even without an `Exn`\n  wrapper, including `FromStr::Err` and `TryFrom::Error`. Do not introduce public crate-specific or\n  operation-specific forwarding aliases or renamed error exports.\n- **Internal results**: use `Result<T>` for erased or message-based errors in private and\n  `pub(crate)` helpers too. Retain concrete error types when callers benefit from typed recovery\n  or payload access. Use `ExnResult<T, E>` or `ExnMessageResult<T>` when a specific exception type\n  or exception-tree manipulation is actually needed; being private alone is not a reason to\n  introduce an exception-returning wrapper. These aliases and typed construction helpers remain available.\n- **Imports**: import `Result`, `ExnResult`, and `ExnMessageResult` under their canonical names\n  directly from `gix_error` (or their `gix` re-exports), and use their bare names in signatures.\n  Prefer to import `bail` when using `bail!`, via `use gix_error::bail;` or `use gix::error::bail;`,\n  and invoke it without a qualified path.\n- **Porcelain errors**: use the central `gix::Error` and `gix::Result` re-exports at public\n  boundaries that return erased or message-based exceptions.\n- **Static messages**: `gix_error::message(\"something failed\")`\n- **Formatted messages**: `gix_error::message!(\"failed to read {path}\")`\n- **Wrapping callee errors with context**: `.or_raise(|| message(\"context about what failed\"))?`\n- **Standalone error (no callee)**: use `bail!(error)` for an early return with a concrete\n  error or message, such as `bail!(message(\"something went wrong\"))`. For a result expression\n  at a boundary returning `Result`, use `Err(error.raise())`.\n- **Wrapping an `impl Error` with context**: `err.and_raise(message(\"context\"))`\n- **Typed exceptions**: use `.raise_typed()`, `.and_raise_typed(...)`, `.or_raise_typed(...)`, or\n  `.ok_or_raise_typed(...)` when an `Exn<E>` is required; the default helpers return `Error` or `Result`.\n- **Conversion without context**: `.or_error()` converts native errors and exceptions to `Result`.\n  Propagate existing `Result` values directly when the callee already provides enough context.\n- **Closure/callback bounds**: preserve concrete callback errors; use `Result<T>` for erased or\n  message-based errors in public and private APIs. Private callbacks may use `ExnResult<T>`\n  when they need exception-tree operations, or a specific error when useful. Use\n  `.or_raise_erased(...)` to add context or `.or_erased()` to convert when an internal callback\n  requires an erased exception.\n- **`Exn<E>` does NOT implement `std::error::Error`** — this is by design.\n  Convert with `?`, `.into()`, or `.into_error()` when a boundary returns `Error`. Conversion retains\n  the original error types, causes, metadata, and locations; erased errors support downcasting for recovery.\n- **In tests**: `gix_error::TestResult` (also re-exported by `gix_testtools`) accepts exceptions\n  directly with `?`. Public `gix_error::Result` also works with `gix_testtools::Result` through `?`.\n- **Common imports**: `use gix_error::{bail, message, ErrorExt, Result, ResultExt};` plus typed\n  exception aliases as needed.\n- See `gix-error/src/lib.rs` module docs for a full migration guide from `thiserror`\n\n### Commit Messages\n\nFollow \"purposeful conventional commits\" style:\n\n- Write commit messages in Markdown and assume readers view them with syntax highlighting.\n  - Enclose anything that occurs in code, as well as crate names and shell commands, in backticks.\n  - Use Markdown generously whenever markup helps readers understand or navigate the prose.\n  - Use the body to share everything known about what motivated the change, not merely what changed.\n- Use conventional commit prefixes ONLY if message should appear in changelog\n- Breaking changes MUST use `!` before the colon: `change!:`, `remove!:`, `rename!:`, or _scoped_ forms like `feat(gix-odb)!:`\n- Features/fixes visible to users: `feat:`, `fix:`\n- For a changelog-worthy commit touching multiple crates, _scope_ it to the crate that should receive the changelog entry, like `feat!(gix-ref)`.\n- Refactors/chores: no prefix (don't affect users)\n- Examples:\n  - `feat: add Repository::foo() to do great things. (#234)`\n  - `fix: don't panic when calling foo() in a bare repository. (#456)`\n  - `change!: rename Foo to Bar. (#123)`\n  - `feat(gix-odb)!: add a new object lookup API`\n  - `fix(gix-ref)!: reject invalid reference names`\n\n### Code Style\n\n- Do not create persistent Python scripts in this repository. Use Bash for repository automation and script-based tests unless the user explicitly requests otherwise.\n- Follow existing patterns in the codebase\n- Skip stylistic rewrites that increase SLOC after formatting; keep simpler existing forms instead of applying style rules unconditionally.\n- Start new Rust modules as `foo.rs`. Create a module directory only when it contains multiple module files; then use `foo/mod.rs` rather than a sibling `foo.rs` file.\n- No `.unwrap()` - use `.expect(\"context\")` if you are sure this can't fail.\n- Prefer references in plumbing crates to avoid expensive clones\n- Avoid calling `.detach()` unless an owned value is explicitly required. Many `gix` APIs accept attached ids and references directly, so prefer keeping repository-backed handles like `gix::Id` when possible.\n- Name variables holding untyped Git object IDs `<type>_id` or `*_<type>_id` (for example, `commit_id`, `root_tree_id`, or `note_blob_id`) so the object kind is always explicit.\n- Use `gix_parallel::*` for interior mutability primitives\n\n### Path Handling\n\n- Paths are byte-oriented in git (even on Windows via MSYS2 abstraction)\n- Use `gix::path::*` utilities to convert git paths (`BString`) to `OsStr`/`Path` or use custom types\n\n## Building and Testing\n\n### Quick Commands\n\n- `just test` - Run all tests, clippy, journey tests, and try building docs\n- `just check` - Build all code in suitable configurations\n- `just clippy` - Run clippy on all crates\n- `cargo test` - Run unit tests only\n\n### Build Variants\n\n- `cargo build --release` - Default build (big but pretty, ~2.5min)\n- `cargo build --release --no-default-features --features lean` - Lean build (~1.5min)\n- `cargo build --release --no-default-features --features small` - Minimal deps (~46s)\n\n### Test Best Practices\n\n- Test public APIs in the crate's integration tests under `tests/`, using only\n  public interfaces. Reserve in-source unit tests (`#[cfg(test)]` modules) for\n  private or `pub(crate)` functionality that integration tests cannot access.\n  Extend an existing integration test with additional assertions when it already\n  exercises the relevant behavior.\n- Tests must be isolated from the developer's checkout, other worktrees, shared\n  Git metadata, and user configuration. Use fixtures provided by `gix-testtools`;\n  never use the source checkout as a test repository.\n- **Tests of read-only functionality must use read-only fixtures**, such as\n  `gix_testtools::scripted_fixture_read_only()` or the crate's read-only repository\n  helper. Use `scripted_fixture_writable()` only when exercising functionality\n  that writes. Prepare required repository states during fixture creation, not\n  by mutating a shared read-only fixture in the test.\n- For setup that is easier in Rust (such as binary corruption), use\n  `gix_testtools::scripted_fixture_read_only_with_post(script, version, |fixture| { ... })`.\n  The script creates the repository; the Rust closure prepares it before caching\n  and returns `(fixture_path, value)` through the helper. Only mutate inside\n  `if let gix_testtools::FixtureState::Uninitialized(path) = fixture { ... }`.\n  The closure also runs for `FixtureState::Fresh` (cached or archived fixtures),\n  where it must only read or compute return values. Increment `version` whenever\n  the post-processing behavior changes to invalidate the cache. See the API docs\n  in `tests/tools/src/lib.rs` and the commit-graph regression test in\n  `gix/tests/gix/repository/revision.rs` for an example.\n- Git invocations in test code must go through `gix_testtools::git()`,\n  `git_command()`, or fixture scripts executed by `gix-testtools`. Do not spawn\n  Git directly with `Command::new(\"git\")` or ad hoc subprocess wrappers. If a test needs unsupported\n  command options, extend the shared isolated helper instead of bypassing it.\n  `run_git()` and `invoke_bash()` share this isolation. Subprocesses that invoke\n  Git indirectly must use `gix_testtools::configure_git_environment()` too.\n  Tests of APIs that read the process environment must isolate it before\n  exercising those APIs or changing environment variables. In `#[serial]` tests,\n  keep a `gix_testtools::isolate_git_environment()` guard alive for the entire test;\n  it restores only its recorded changes on drop. Chain test-specific overrides\n  onto that guard or use a separate `gix_testtools::Env` guard to restore them too.\n  All concurrent environment access must participate in the same serialization. Otherwise, use\n  `gix_testtools::run_in_isolated_process()` so changes cannot race other tests.\n  Restore working-directory changes separately with `gix_testtools::set_current_dir()`.\n- Setting a subprocess's working directory or passing `git -C` is not isolation:\n  inherited `GIT_DIR`, `GIT_WORK_TREE`, `GIT_COMMON_DIR`, `GIT_INDEX_FILE`, or\n  object-directory variables can redirect operations outside the fixture. Tests\n  that exercise such overrides must scope them to disposable test repositories.\n  Open repositories through the crate's isolated test helper or isolated `gix`\n  options, with only test-specific configuration overrides.\n- Run tests before making changes to understand existing issues\n- Use `GIX_TEST_IGNORE_ARCHIVES=1` when testing on macOS/Windows\n- Journey tests validate CLI behavior end-to-end\n- Fixture scripts should document what behavior they exercise and what makes\n  the fixture special. Leave clear-text breadcrumbs so future readers can tell\n  which details are essential to the test. Use markdown doc-strings when available.\n- Stabilize fixtures whose generated contents can vary by using the\n  `_needs_archive` variants of functions in `gix-testtools`; these always use\n  packaged archived fixtures instead of platform-local generated output.\n- Use assertion descriptions to state what is being asserted. For `assert*!`\n  macros this is the last parameter; for `insta::assert*` macros it is the\n  second parameter. Prefer messages that explain the invariant, not just that an\n  assertion failed.\n\n## Architecture Decisions\n\n### Plumbing vs Porcelain\n\n- **Plumbing crates**: Low-level, take references, expose mutable parts as arguments\n- **Porcelain (gix)**: High-level, convenient, may clone Repository for user convenience\n- Platforms: cheap to create, keep reference to Repository\n- Caches: more expensive, clone `Repository` or free of lifetimes\n\n### Options vs Context\n\n- Use `Options` for branching behavior configuration (can be defaulted)\n- Use `Context` for data required for operation (cannot be defaulted)\n\n## Crate Organization\n\n### Common Crates\n\n- `gix`: Main library entrypoint (porcelain)\n- `gix-object`, `gix-ref`, `gix-config`: Core git data structures\n- `gix-odb`, `gix-pack`: Object database and pack handling\n- `gix-diff`, `gix-merge`, `gix-status`: Operations\n- `gitoxide-core`: Shared CLI functionality\n\n## Documentation\n\n- High-level docs: README.md, CONTRIBUTING.md, DEVELOPMENT.md\n- Crate status: crate-status.md\n- Stability guide: STABILITY.md\n- Always update docs if directly related to code changes\n\n## CI and Releases\n\n- Ubuntu-latest git version is the compatibility target\n- `cargo smart-release` for releases (driven by commit messages)\n- Every commit must be self-contained and pass CI independently\n   - Feel free to run `etc/scripts/ci-check-local.sh --thorough` until it passes as proxy, as running every commit against CI isn't feasible.\n- Keep breaking changes and all adaptations required to build and test the workspace in the same commit\n- When such a commit touches multiple crates, _scope_ its conventional commit message to the crate whose changelog should receive the entry\n\n## When Suggesting Changes\n\n1. Understand the plumbing vs porcelain distinction\n2. Check existing patterns in similar crates\n3. Follow error handling conventions strictly\n4. Ensure changes work with feature flags (small, lean, max, max-pure)\n5. Consider impact on both library and CLI users\n6. Test against real git repositories when possible\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/GitoxideLabs/gitoxide/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}