> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugin @coder

> Builtin engineering tool for reading, editing, patching, and executing tasks with rollback.

`@coder` is the engineering suite used by [Coder Mode (/coder)](/usage/coder-mode). It provides actions for reading/searching files, safely applying patches, running commands, and reverting changes.

<Info>
  `@coder` is a **builtin plugin** -- it comes embedded in the ChatCLI binary and works immediately, without installation. If you need a custom version, simply place the binary in `~/.chatcli/plugins/` and it will take precedence over the builtin. When removed, the builtin returns automatically on the next `/plugin reload`.
</Info>

***

## Quick Reference

All subcommands and their most commonly used flags at a glance:

| Subcommand | Description | Key Flags |
| - | - | - |
| `read` | Read file contents | `--file` (req.), `--start`, `--end`, `--head`, `--tail` |
| `write` | Write file with backup | `--file` (req.), `--content` (req.), `--append`, `--encoding` |
| `patch` | Apply search/replace or unified diff | `--file`, `--search`, `--replace`, `--diff`, `--encoding` |
| `multipatch` | **Atomic transaction** of multiple search/replace edits across multiple files. All-or-nothing rollback. | `--edits` (req., JSON array) |
| `tree` | Directory structure | `--dir`, `--glob`, `--max-entries` |
| `outline` | Symbol skeleton of a file (declarations + line numbers) | `--file` (req.) |
| `map` | Budgeted structural map of a whole tree, files ranked by structure | `--dir`, `--budget` |
| `search` | Full-text search in files | `--term` (req.), `--dir`, `--glob`, `--max-results`, `--context` |
| `exec` | Execute shell commands | `--cmd` (req.), `--command` |
| `test` | Run tests | `--dir`, `--pattern`, `--timeout` |
| `git-status` | Repository status | *(no flags)* |
| `git-diff` | Pending differences | `--file`, `--staged` |
| `git-log` | Commit history | `--oneline`, `--limit` |
| `git-changed` | Changed files | `--staged` |
| `git-branch` | List branches | `--all` |
| `rollback` | Restore file from `.bak` backup | `--file` (req.) |
| `clean` | Remove `.bak` files | *(no required flags)* |
| `checkpoint` | Shadow-git workspace snapshots (automatic before mutations) | `--list`, `--create`, `--restore`, `--label` |

***

## Argument Formats

`@coder` accepts two argument formats: **JSON** and **CLI-style**. Both are equivalent.

<Tabs>
  <Tab title="JSON Format (recommended)">
    The JSON format is used inside the `args` attribute of a `<tool_call>`. The structure is:

    ```json theme={"system"}
    {
      "cmd": "<subcommand>",
      "args": {
        "<flag>": "<value>",
        ...
      }
    }
    ```

    Full example:

    ```xml theme={"system"}
    <tool_call name="@coder" args='{"cmd":"read","args":{"file":"main.go","start":10,"end":50}}'/>
    ```

    <Tip>
      The JSON format is recommended because it avoids escaping issues and is what language models generate most consistently.
    </Tip>
  </Tab>

  <Tab title="CLI-style Format">
    You can also pass arguments in command-line style, separated by spaces:

    ```
    read --file main.go --start 10 --end 50
    ```

    Here, the `cmd` field is the first word and flags follow in `--flag value` format.

    Example in tool\_call:

    ```xml theme={"system"}
    <tool_call name="@coder" args='{"cmd":"read --file main.go --start 10 --end 50"}'/>
    ```

    <Note>
      In CLI-style format, values with spaces must be quoted: `--content "hello world"`.
    </Note>
  </Tab>
</Tabs>

***

## Subcommands -- Complete Reference

<AccordionGroup>
  <Accordion title="read -- Read Files" icon="file-lines">
    Reads the contents of a file from disk. Supports partial reading by line range and byte limits.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--file` | string | **Yes** | -- | Path of the file to read |
    | `--start` | int | No | -- | Start line (1-based) |
    | `--end` | int | No | -- | End line (1-based) |
    | `--head` | int | No | -- | First N lines |
    | `--tail` | int | No | -- | Last N lines |
    | `--max-bytes` | int | No | 200000 | Maximum byte limit for output (the ceiling; a read that asks for no range is capped at 2,000 lines with a `--start` continuation hint, the way Claude Code pages reads) |
    | `--encoding` | string | No | `text` | Output encoding: `text` or `base64` |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Read entire file -->
        <tool_call name="@coder" args='{"cmd":"read","args":{"file":"README.md"}}'/>

        <!-- Read lines 10 to 50 -->
        <tool_call name="@coder" args='{"cmd":"read","args":{"file":"main.go","start":10,"end":50}}'/>

        <!-- First 20 lines -->
        <tool_call name="@coder" args='{"cmd":"read","args":{"file":"config.yaml","head":20}}'/>

        <!-- Last 30 lines -->
        <tool_call name="@coder" args='{"cmd":"read","args":{"file":"app.log","tail":30}}'/>

        <!-- Output in base64 (useful for binaries) -->
        <tool_call name="@coder" args='{"cmd":"read","args":{"file":"image.png","encoding":"base64","max-bytes":500000}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        read --file README.md
        read --file main.go --start 10 --end 50
        read --file config.yaml --head 20
        read --file app.log --tail 30
        read --file image.png --encoding base64 --max-bytes 500000
        ```
      </Tab>
    </Tabs>

    <Tip>
      Use `--head` or `--tail` to avoid very large outputs. The `--max-bytes` limit (default 200KB) acts as a safety net even when not explicitly specified.
    </Tip>
  </Accordion>

  <Accordion title="write -- Write Files" icon="pen">
    Writes content to a file. Automatically creates a `.bak` backup of the existing file before overwriting.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--file` | string | **Yes** | -- | Path of the file to write |
    | `--content` | string | **Yes** | -- | Content to write |
    | `--encoding` | string | No | `text` | Content encoding: `text` or `base64` |
    | `--append` | bool | No | `false` | If `true`, appends to the file instead of overwriting |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Write new file (text) -->
        <tool_call name="@coder" args='{"cmd":"write","args":{"file":"hello.txt","content":"Hello, World!"}}'/>

        <!-- Write with base64-encoded content -->
        <tool_call name="@coder" args='{"cmd":"write","args":{"file":"data.bin","content":"SGVsbG8gV29ybGQ=","encoding":"base64"}}'/>

        <!-- Append to an existing file -->
        <tool_call name="@coder" args='{"cmd":"write","args":{"file":"notes.txt","content":"\nNew line appended","append":true}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        write --file hello.txt --content "Hello, World!"
        write --file data.bin --content "SGVsbG8gV29ybGQ=" --encoding base64
        write --file notes.txt --content "New line" --append
        ```
      </Tab>
    </Tabs>

    <Warning>
      Use `--encoding base64` for content containing special characters, complex line breaks, or binary data. This avoids escaping issues in JSON.
    </Warning>

    <Note>
      **Post-edit diagnostics.** After a successful `write` (also `patch` and `multipatch`), ChatCLI runs the language server over the touched files and appends any findings to the tool result as a `[DIAGNOSTICS]` block — so a broken edit is caught **immediately**, in the same turn, instead of turns later when a test fails. It is silent on clean files, capped at 5 files / 3000 characters, and disabled with `CHATCLI_CODER_AUTODIAG=off`. A language server must be available for the file's language (see [LSP Diagnostics](/coder/lsp-diagnostics)).
    </Note>
  </Accordion>

  <Accordion title="patch -- Apply Patches" icon="code-compare">
    Applies changes to an existing file. Supports two modes: **search/replace** (replaces a specific section) and **unified diff** (applies a patch in diff format).

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--file` | string | Conditional | -- | File to patch. Required for search/replace; optional for diff (the diff may contain paths) |
    | `--search` | string | Conditional | -- | Text to find (search/replace mode) |
    | `--replace` | string | Conditional | -- | Replacement text (search/replace mode) |
    | `--diff` | string | Conditional | -- | Unified diff content (diff mode) |
    | `--encoding` | string | No | `text` | Encoding for `--search` and `--replace`: `text` or `base64` |
    | `--diff-encoding` | string | No | `text` | Encoding for `--diff`: `text` or `base64` |

    <Note>
      You must use **either** search/replace mode (`--search` + `--replace`) **or** diff mode (`--diff`). Do not combine both.
    </Note>

    ### Search/Replace Mode

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Replace text (plain text) -->
        <tool_call name="@coder" args='{"cmd":"patch","args":{"file":"main.go","search":"fmt.Println(\"old\")","replace":"fmt.Println(\"new\")"}}'/>

        <!-- Replace text (base64 to avoid escaping) -->
        <tool_call name="@coder" args='{"cmd":"patch","args":{"file":"main.go","search":"Zm10LlByaW50bG4oIm9sZCIp","replace":"Zm10LlByaW50bG4oIm5ldyIp","encoding":"base64"}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        patch --file main.go --search "fmt.Println(\"old\")" --replace "fmt.Println(\"new\")"
        patch --file main.go --search "base64str" --replace "base64str" --encoding base64
        ```
      </Tab>
    </Tabs>

    ### Unified Diff Mode

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Apply diff as text -->
        <tool_call name="@coder" args='{"cmd":"patch","args":{"diff":"--- a/main.go\n+++ b/main.go\n@@ -5,3 +5,3 @@\n-old line\n+new line"}}'/>

        <!-- Apply diff as base64 -->
        <tool_call name="@coder" args='{"cmd":"patch","args":{"diff":"LS0tIGEvbWFpbi5nbw...","diff-encoding":"base64"}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        patch --diff "--- a/main.go\n+++ b/main.go\n@@ -5,3 +5,3 @@\n-old\n+new"
        patch --diff "base64content" --diff-encoding base64
        ```
      </Tab>
    </Tabs>

    <Tip>
      The **base64** mode is strongly recommended for patches, especially when the content contains quotes, backslashes, or multiple lines. This eliminates JSON escaping issues entirely.
    </Tip>
  </Accordion>

  <Accordion title="tree -- Directory Structure" icon="folder-tree">
    Lists the directory structure in tree format. Useful for understanding project organization.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--dir` | string | No | `"."` | Root directory to list |
    | `--glob` | string | No | -- | Glob pattern to filter files (e.g., `"*.go"`) |
    | `--max-entries` | int | No | 2000 | Maximum number of entries returned |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- List current directory -->
        <tool_call name="@coder" args='{"cmd":"tree","args":{"dir":"."}}'/>

        <!-- List only Go files -->
        <tool_call name="@coder" args='{"cmd":"tree","args":{"dir":".","glob":"*.go"}}'/>

        <!-- List subdirectory with limit -->
        <tool_call name="@coder" args='{"cmd":"tree","args":{"dir":"./internal","max-entries":500}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        tree --dir .
        tree --dir . --glob "*.go"
        tree --dir ./internal --max-entries 500
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="search -- Full-Text Search" icon="magnifying-glass">
    Searches for a term across all files in a directory. Returns snippets with surrounding context.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--term` | string | **Yes** | -- | Search term |
    | `--dir` | string | No | `"."` | Directory to search in |
    | `--glob` | string | No | -- | Glob pattern to filter files (e.g., `"*.go"`, `"*.ts"`) |
    | `--max-results` | int | No | 100 | Maximum number of results |
    | `--context` | int | No | 2 | Context lines before and after each match |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Simple search -->
        <tool_call name="@coder" args='{"cmd":"search","args":{"term":"TODO","dir":"."}}'/>

        <!-- Search in Go files with more context -->
        <tool_call name="@coder" args='{"cmd":"search","args":{"term":"func main","dir":".","glob":"*.go","context":5}}'/>

        <!-- Search with result limit -->
        <tool_call name="@coder" args='{"cmd":"search","args":{"term":"error","dir":"./pkg","max-results":20}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        search --term "TODO" --dir .
        search --term "func main" --dir . --glob "*.go" --context 5
        search --term "error" --dir ./pkg --max-results 20
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="outline -- File Symbol Skeleton" icon="list-tree">
    Renders a file's **symbol skeleton** — its declarations with line numbers — so you understand a file's shape without reading the whole thing. For Go files the signatures are **exact** (parsed with Go's `go/ast`: functions with their receiver, structs, interfaces, consts, vars); for Python, JS/TS/JSX, Java, Ruby, Rust, Kotlin, C# and PHP a pattern-based outline recognizes the common declaration forms. **Read-only.**

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--file` | string | **Yes** | -- | Path of the file to outline |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <tool_call name="@coder" args='{"cmd":"outline","args":{"file":"cli/cli.go"}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        outline --file cli/cli.go
        ```
      </Tab>
    </Tabs>

    <Tip>
      Reach for `outline` before `read` when you only need to know *what* is in a file (which functions, types, methods) and *where* — it costs a fraction of the tokens of reading the whole file.
    </Tip>
  </Accordion>

  <Accordion title="map -- Repository Structure Map" icon="map">
    Renders a **character-budgeted structural map** of a whole tree: every source file is outlined, files are **ranked by how much structure they carry**, and their skeletons are printed until the budget is spent — with an explicit note when files are elided. It ignores `.git`, `node_modules`, `vendor`, `dist`, `build`, hidden files and `*_test.go`. **Read-only.** Use it to orient yourself in a large codebase without reading whole files.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--dir` | string | No | `"."` | Root directory to map |
    | `--budget` | int | No | 8000 | Maximum characters of structure to emit |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Map the whole project -->
        <tool_call name="@coder" args='{"cmd":"map","args":{"dir":"."}}'/>

        <!-- Map a subtree with a larger budget -->
        <tool_call name="@coder" args='{"cmd":"map","args":{"dir":"./cli","budget":16000}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        map --dir . --budget 8000
        map --dir ./cli --budget 16000
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="exec -- Execute Commands" icon="terminal">
    Executes an arbitrary command in the shell. Has built-in security protections against destructive commands.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--cmd` | string | **Yes** | -- | Command to execute |
    | `--command` | string | No | -- | Alias for `--cmd` |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Execute a simple command -->
        <tool_call name="@coder" args='{"cmd":"exec","args":{"cmd":"go build ./..."}}'/>

        <!-- List processes -->
        <tool_call name="@coder" args='{"cmd":"exec","args":{"cmd":"ps aux | grep myapp"}}'/>

        <!-- Using the --command alias -->
        <tool_call name="@coder" args='{"cmd":"exec","args":{"command":"ls -la"}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        exec --cmd "go build ./..."
        exec --cmd "ps aux | grep myapp"
        exec --command "ls -la"
        ```
      </Tab>
    </Tabs>

    <Warning>
      `exec` automatically blocks commands considered dangerous, including:

      * `rm -rf /` and destructive variants
      * `dd` targeting disk devices
      * Fork bombs (e.g., `:(){ :|:& };:`)
      * Other recognizably destructive patterns

      These blocks exist to protect the system. Use responsibly.
    </Warning>
  </Accordion>

  <Accordion title="test -- Run Tests" icon="vial">
    Runs project tests automatically, detecting the framework based on the directory contents.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--dir` | string | No | `"."` | Directory where to run tests |
    | `--pattern` | string | No | -- | Test file pattern (e.g., `"*_test.go"`) |
    | `--timeout` | int | No | 30 | Timeout in seconds |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Run all tests -->
        <tool_call name="@coder" args='{"cmd":"test","args":{"dir":"."}}'/>

        <!-- Run tests with specific pattern -->
        <tool_call name="@coder" args='{"cmd":"test","args":{"dir":"./pkg","pattern":"*_test.go","timeout":60}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        test --dir .
        test --dir ./pkg --pattern "*_test.go" --timeout 60
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="git-status -- Repository Status" icon="code-branch">
    Shows the Git repository status (modified, staged, untracked files, etc.).

    **No flags required.**

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <tool_call name="@coder" args='{"cmd":"git-status","args":{}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        git-status
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="git-diff -- Pending Differences" icon="code-compare">
    Shows the diff of modified files in the repository.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--file` | string | No | -- | Filter diff to a specific file |
    | `--staged` | bool | No | `false` | Show only staged changes (ready for commit) |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Full diff -->
        <tool_call name="@coder" args='{"cmd":"git-diff","args":{}}'/>

        <!-- Diff for a specific file -->
        <tool_call name="@coder" args='{"cmd":"git-diff","args":{"file":"main.go"}}'/>

        <!-- Staged diff -->
        <tool_call name="@coder" args='{"cmd":"git-diff","args":{"staged":true}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        git-diff
        git-diff --file main.go
        git-diff --staged
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="git-log -- Commit History" icon="clock-rotate-left">
    Displays the repository's commit history.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--oneline` | bool | No | `false` | Compact format (one line per commit) |
    | `--limit` | int | No | 10 | Maximum number of commits shown |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Last 10 commits -->
        <tool_call name="@coder" args='{"cmd":"git-log","args":{}}'/>

        <!-- Last 5 commits in compact format -->
        <tool_call name="@coder" args='{"cmd":"git-log","args":{"oneline":true,"limit":5}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        git-log
        git-log --oneline --limit 5
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="git-changed -- Changed Files" icon="file-pen">
    Lists changed files in the repository (similar to `git diff --name-only`).

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--staged` | bool | No | `false` | List only staged files |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- All changed files -->
        <tool_call name="@coder" args='{"cmd":"git-changed","args":{}}'/>

        <!-- Only staged files -->
        <tool_call name="@coder" args='{"cmd":"git-changed","args":{"staged":true}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        git-changed
        git-changed --staged
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="git-branch -- Branch Listing" icon="code-branch">
    Lists the repository's branches.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--all` | bool | No | `false` | Include remote branches |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- Local branches -->
        <tool_call name="@coder" args='{"cmd":"git-branch","args":{}}'/>

        <!-- All branches (local + remote) -->
        <tool_call name="@coder" args='{"cmd":"git-branch","args":{"all":true}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        git-branch
        git-branch --all
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="rollback -- Revert Changes" icon="rotate-left">
    Restores a file from its `.bak` backup, automatically created by `write` or `patch`.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--file` | string | **Yes** | -- | Path of the file to restore |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <tool_call name="@coder" args='{"cmd":"rollback","args":{"file":"main.go"}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        rollback --file main.go
        ```
      </Tab>
    </Tabs>

    <Note>
      `rollback` only works if a corresponding `.bak` file exists. Backups are automatically created by the `write` and `patch` commands.
    </Note>
  </Accordion>

  <Accordion title="clean -- Remove Backups" icon="broom">
    Removes `.bak` files created by the backup system.

    **No required flags.**

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <tool_call name="@coder" args='{"cmd":"clean","args":{}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        clean
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="checkpoint -- Shadow-git Snapshots" icon="clock-rotate-left">
    Workspace snapshots into a **shadow git repository**, a stronger safety net than the per-file `.bak` rollback — it covers multi-file edits and `exec` side effects, not just a single file.

    A checkpoint is taken **automatically before every mutating subcommand** (`write`, `patch`, `multipatch`, `exec`). The snapshot lives in a separate `GIT_DIR` under `~/.chatcli/checkpoints/<hash>` with your workspace as its work tree, so **your own `.git` is never touched** and your project's `.gitignore` is honored.

    ### Flags

    | Flag | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `--list` | bool | No | (default) | List snapshots, newest first |
    | `--create` | bool | No | `false` | Record a snapshot now |
    | `--restore` | string | No | -- | Rewind the working tree to the snapshot with this hash |
    | `--label` | string | No | `manual` | Label for a `--create` snapshot |

    ### Examples

    <Tabs>
      <Tab title="JSON">
        ```xml theme={"system"}
        <!-- List snapshots -->
        <tool_call name="@coder" args='{"cmd":"checkpoint","args":{"list":true}}'/>

        <!-- Record one now -->
        <tool_call name="@coder" args='{"cmd":"checkpoint","args":{"create":true,"label":"before refactor"}}'/>

        <!-- Rewind to a snapshot -->
        <tool_call name="@coder" args='{"cmd":"checkpoint","args":{"restore":"a1b2c3d"}}'/>
        ```
      </Tab>

      <Tab title="CLI-style">
        ```
        checkpoint --list
        checkpoint --create --label "before refactor"
        checkpoint --restore a1b2c3d
        ```
      </Tab>
    </Tabs>

    <Note>
      `--restore` never deletes files added **after** the snapshot; it only rewinds what the snapshot tracked. It goes through the [security gate](/coder/coder-security); `--list` and `--create` are read-only.
    </Note>

    <Info>
      Auto-snapshots are **best-effort** (a checkpoint failure never blocks the edit), **throttled** to at most one per 15 seconds (a burst of writes produces one checkpoint), a **no-op when `git` is not installed**, and switched off entirely with `CHATCLI_CODER_CHECKPOINTS=off`.

      They are also **bounded**: workspaces as broad as your home directory (or any directory containing it) are never auto-snapshotted — hashing that much of the disk would freeze every command — and each snapshot runs under a hard deadline (10s automatic, 60s for an explicit `checkpoint create`, overridable in seconds via `CHATCLI_CODER_CHECKPOINT_TIMEOUT`). Repeated snapshot failures back off exponentially and, after three in a row, disable automatic snapshots for the rest of the session with a one-line warning.
    </Info>
  </Accordion>
</AccordionGroup>

***

## Transactional multipatch

When a refactor needs to touch **multiple files as one unit** (rename an identifier propagated across 5 files, update an import in every consumer, etc.), use `multipatch` instead of chaining `patch` calls. The contract:

<Steps>
  <Step title="Phase 1 — validation (no writes)">
    For each edit in declaration order, the engine loads the file, simulates the `search`→`replace` in memory, and verifies the `search` text is still present after prior in-flight edits to the same file. A failure on any edit aborts the transaction **before any disk write**.
  </Step>

  <Step title="Phase 2 — commit">
    Snapshot of each affected file in memory + write the new content. Any write failure restores all touched files from the snapshot.
  </Step>

  <Step title="Concurrency">
    Per-file mutex (keyed by absolute path), acquisition in sorted order — two transactions touching the same pair of files never deadlock. File permissions (chmod) are preserved across the rewrite.
  </Step>
</Steps>

```json theme={"system"}
{
  "cmd": "multipatch",
  "args": {
    "edits": [
      {"file": "internal/auth/login.go", "search": "loginV1", "replace": "loginV2"},
      {"file": "internal/auth/login_test.go", "search": "loginV1", "replace": "loginV2"},
      {"file": "cmd/server/main.go", "search": "auth.loginV1", "replace": "auth.loginV2"}
    ]
  }
}
```

<Note>
  Each edit applies its `search`→`replace` **exactly once** (`strings.Replace` with `n=1`). To replace multiple occurrences in the same file, declare multiple edits. Per-edit `base64` encoding is supported (`"encoding":"base64"`) for payloads with non-UTF8 bytes.
</Note>

***

## Backup System

`@coder` implements an automatic backup system to protect against unwanted changes.

<Steps>
  <Step title="Write or Patch">
    When you execute `write` or `patch`, the plugin checks whether the target file already exists.
  </Step>

  <Step title="Backup Creation">
    If the file exists, a copy is saved with the `.bak` extension (e.g., `main.go` -> `main.go.bak`).
  </Step>

  <Step title="Change Application">
    The new content is written (or the patch is applied) to the original file.
  </Step>

  <Step title="Rollback Available">
    At any point, you can use `rollback --file main.go` to restore the previous version from the `.bak` file.
  </Step>

  <Step title="Cleanup">
    Use `clean` to remove all `.bak` files when you no longer need the backups.
  </Step>
</Steps>

<Tip>
  The backup is overwritten on each new `write` or `patch` operation on the same file. If you make multiple changes, only the version immediately before the last operation will be available for rollback.
</Tip>

***

## Path Validation and Security

`@coder` applies several security validations to all file paths:

<CardGroup cols={2}>
  <Card title="Workspace Boundary" icon="shield">
    All paths are resolved relative to the working directory (workspace). Attempts to access files outside the workspace are blocked (e.g., `../../etc/passwd`).
  </Card>

  <Card title="Symlink Resolution" icon="link">
    Symlinks are resolved before validation. A symlink pointing outside the workspace will be rejected, even if the apparent path is within the allowed directory.
  </Card>

  <Card title="Sensitive Paths" icon="lock">
    Paths to sensitive system files (e.g., `/etc/shadow`, `/etc/passwd`) are blocked by default, preventing read or write operations.
  </Card>

  <Card title="Dangerous Commands" icon="triangle-exclamation">
    The `exec` subcommand filters known destructive patterns such as `rm -rf /`, `dd`, fork bombs, and others. These commands are rejected before execution.
  </Card>
</CardGroup>

***

## Complete Usage Example (in /coder)

In `/coder` mode, the assistant responds with a `reasoning` block followed by a `tool_call`. The block is sized to the task: a single-step request (one lookup, one command, one answer) gets one line and no task list, while anything with two or more steps gets a short numbered plan with `[✓]` marks as it progresses. The rule lives in the stable system prompt on purpose — deciding it per query would change the prompt and rewrite the cached prefix. The same prompt binds claims to evidence: when tool results ground the answer, specific figures, dates, deadlines, rules and place names come only from that evidence, and whatever comes from the model's own knowledge is labeled unverified or an estimate in the sentence that uses it, never presented with the authority of a fetched source. Here is a complete engineering workflow:

```xml theme={"system"}
<!-- 1. Understand the project structure -->
<tool_call name="@coder" args='{"cmd":"tree","args":{"dir":".","glob":"*.go"}}'/>

<!-- 2. Search where a function is defined -->
<tool_call name="@coder" args='{"cmd":"search","args":{"term":"func HandleRequest","dir":".","glob":"*.go"}}'/>

<!-- 3. Read the relevant file -->
<tool_call name="@coder" args='{"cmd":"read","args":{"file":"handler.go","start":15,"end":45}}'/>

<!-- 4. Apply a fix -->
<tool_call name="@coder" args='{"cmd":"patch","args":{"file":"handler.go","search":"return nil","replace":"return fmt.Errorf(\"missing parameter: %s\", name)"}}'/>

<!-- 5. Run the tests -->
<tool_call name="@coder" args='{"cmd":"test","args":{"dir":".","timeout":60}}'/>

<!-- 6. Check what changed -->
<tool_call name="@coder" args='{"cmd":"git-diff","args":{}}'/>

<!-- 7. If something went wrong, revert -->
<tool_call name="@coder" args='{"cmd":"rollback","args":{"file":"handler.go"}}'/>
```

***

## JSON Recovery and Robust Parsing

`@coder` includes a JSON recovery system that automatically fixes malformed arguments generated by LLMs:

<CardGroup cols={2}>
  <Card title="7 Recovery Strategies" icon="screwdriver-wrench">
    Single quotes, unquoted keys, trailing commas, plain string wrapping, and more. See [JSON Recovery](/coder/json-recovery) for details.
  </Card>

  <Card title="Escaped Quotes in Shell" icon="terminal">
    Improved handling of escaped quotes in shell commands, avoiding parsing failures when the model generates `exec --cmd "echo \"hello\""`.
  </Card>

  <Card title="Unicode Quote Normalization" icon="font">
    Curly (typographic) quotes are automatically converted to straight quotes in code files, preventing compilation errors.
  </Card>

  <Card title="Concurrent Execution" icon="arrows-split-up-and-left">
    Tool calls that operate on different files are executed in parallel (file-scoped parallelization), speeding up read and search operations.
  </Card>
</CardGroup>

***

## Important Notes

<Warning>
  `@coder` grants read/write power over files and command execution, all subject to rollback when requested. Use in trusted repositories.
</Warning>

<Note>
  Being builtin, `@coder` appears in `/plugin list` with the `[builtin]` tag. It cannot be uninstalled via `/plugin uninstall`.
</Note>

***

## Plugin @coder FAQ

<AccordionGroup>
  <Accordion title="Does @coder accept JSON in args?">
    Yes. The recommended format is JSON. Example:

    ```xml theme={"system"}
    <tool_call name="@coder" args='{"cmd":"read","args":{"file":"README.md"}}'/>
    ```
  </Accordion>

  <Accordion title="When to use patch --diff vs --search/--replace?">
    Use `--search`/`--replace` for simple, targeted substitutions at a single location in the file. Use `--diff` when you need to apply multiple changes at once or when the change involves adding/removing lines in different sections of the file. The diff can be encoded as `text` or `base64`.
  </Accordion>

  <Accordion title="Is exec dangerous?">
    `@coder exec` blocks dangerous patterns by default, such as `rm -rf /`, `dd` targeting disk devices, and fork bombs. The protection is automatic and requires no configuration.
  </Accordion>

  <Accordion title="Is there a read limit?">
    Yes. The default is `--max-bytes 200000` (200KB). You can also use `--head` or `--tail` to read only portions of the file. This prevents very large outputs from overwhelming the model's context window.
  </Accordion>

  <Accordion title="What happens if I write to the same file twice?">
    The `.bak` backup is overwritten on each operation. Only the version immediately before the last write will be available for rollback. If you need full history, use `git` for version management.
  </Accordion>

  <Accordion title="Can I use @coder outside of /coder mode?">
    Yes. The `@coder` plugin can be invoked in any mode that supports tool\_calls. The `/coder` mode simply configures the system prompt to guide the model to use `@coder` as its primary tool.
  </Accordion>

  <Accordion title="How do I replace the builtin @coder with a custom version?">
    Place a binary with the same name in the `~/.chatcli/plugins/` directory. It will take precedence over the builtin. To revert to the builtin, remove the custom binary and run `/plugin reload`.
  </Accordion>

  <Accordion title="Is --encoding base64 necessary?">
    It is not mandatory, but strongly recommended for `write` and `patch` when the content contains special characters, quotes, backslashes, or multiple lines. Base64 completely eliminates JSON escaping issues.
  </Accordion>
</AccordionGroup>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Coder Mode" icon="code" href="/usage/coder-mode">
    How `/coder` orchestrates `@coder` in a full ReAct loop.
  </Card>

  <Card title="Coder Security" icon="shield-halved" href="/coder/coder-security">
    Policies, allowlist, and execution governance.
  </Card>

  <Card title="Enhanced Permissions" icon="shield-alert" href="/coder/enhanced-permissions">
    40+ immune patterns and 90+ read-only allowlist.
  </Card>

  <Card title="JSON Recovery" icon="wrench" href="/coder/json-recovery">
    7 strategies to recover malformed JSON in tool calls.
  </Card>

  <Card title="File Staleness" icon="clock-rotate-left" href="/coder/file-staleness">
    Track mtime + SHA-256 between read/write to avoid conflicts.
  </Card>

  <Card title="Cookbook: Fix tests" icon="vial" href="/cookbook/coder-fix-tests">
    Practical recipe using `@coder` to autonomously fix tests.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.