> ## 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.

# JSON Recovery

> Automatic recovery system for malformed JSON generated by LLMs in tool calls

ChatCLI implements a **JSON recovery system** that automatically fixes malformed arguments generated by LLMs during tool calls. This dramatically increases the success rate of tool calls, especially with smaller models or via XML parsing.

***

## Why Malformed JSON?

LLMs frequently generate invalid JSON in their tool call arguments. This happens because language models work with tokens, not syntax validation:

| Problem | Example | Frequency |
| :- | :- | :- |
| Single quotes instead of double | `{'cmd': 'read'}` | Very common |
| Unquoted keys | `{cmd: "read", file: "main.go"}` | Common |
| Trailing commas | `{"cmd":"read","file":"main.go",}` | Common |
| Raw value without object | `main.go` instead of `{"file":"main.go"}` | Frequent |
| Mixed styles | `{cmd: 'read', "file": main.go}` | Occasional |
| CLI text instead of JSON | `read --file main.go` | Frequent |
| JS object literals | `{cmd: read, file: main.go}` | Occasional |

<Warning>
  Without JSON recovery, these errors cause parsing failures that break the agent loop. With smaller models, up to 30% of tool calls may have invalid JSON.
</Warning>

***

## The 7 Recovery Strategies

The `NormalizeToolArgs` system applies up to 7 strategies in sequence, stopping at the first one that produces valid JSON:

<AccordionGroup>
  <Accordion title="1. Standard JSON Parse" icon="check">
    Attempts direct parsing with `json.Unmarshal`. If the JSON is already valid, it returns immediately without modifications.

    ```
    {"cmd":"read","args":{"file":"main.go"}}  =>  valid, returns directly
    ```
  </Accordion>

  <Accordion title="2. Single Quotes to Double Quotes" icon="quote-right">
    Converts single quotes to double quotes with proper escape handling. Preserves single quotes inside strings and escapes internal double quotes.

    ```
    Input:  {'cmd':'read','file':'main.go'}
    Output: {"cmd":"read","file":"main.go"}
    ```

    <Tip>
      The converter uses a stateful parser that tracks context (inside/outside string) to avoid incorrect substitutions.
    </Tip>
  </Accordion>

  <Accordion title="3. Unquoted Keys" icon="key">
    Adds double quotes to keys that are not quoted. Uses regex to detect the `{key:` or `, key:` pattern.

    ```
    Input:  {cmd: "read", file: "main.go"}
    Output: {"cmd": "read", "file": "main.go"}
    ```
  </Accordion>

  <Accordion title="4. Combined: Quotes + Keys" icon="layer-group">
    Applies the single quote fix first, then the unquoted keys fix. Resolves cases where both problems coexist.

    ```
    Input:  {cmd: 'read', file: 'main.go'}
    Output: {"cmd": "read", "file": "main.go"}
    ```
  </Accordion>

  <Accordion title="5. Trailing Commas" icon="comma">
    Removes commas before `}` or `]` that make the JSON invalid.

    ```
    Input:  {"cmd":"read","file":"main.go",}
    Output: {"cmd":"read","file":"main.go"}
    ```
  </Accordion>

  <Accordion title="6. Plain String Wrapping" icon="box">
    When the model sends only a raw value instead of a JSON object, the system wraps it in the correct field based on the tool name.

    ```
    Tool: read_file    Input: main.go     => {"file":"main.go"}
    Tool: run_command  Input: ls -la      => {"cmd":"ls -la"}
    Tool: search_files Input: TODO        => {"term":"TODO"}
    ```

    The mapping covers 30+ tools and aliases, including native functions (`read_file`, `write_file`) and coder subcommands (`read`, `exec`, `search`).
  </Accordion>

  <Accordion title="7. Aggressive Object Literal Fix" icon="hammer">
    For object literals with no quotes at all, the system manually parses `key: value` pairs and rebuilds valid JSON.

    ```
    Input:  {cmd: read, file: main.go, append: true}
    Output: {"cmd":"read","file":"main.go","append":true}
    ```

    Values are interpreted intelligently:

    * `true`/`false` -> booleans
    * Numbers -> JSON numbers
    * `null`/`none` -> null
    * Quoted strings -> strings (quotes removed)
    * Everything else -> string
  </Accordion>
</AccordionGroup>

***

## Tool-to-Field Mapping

Plain string wrapping uses an extensive mapping of tool names to their primary input field:

<Tabs>
  <Tab title="Native Tools">
    | Tool | Field | Example |
    | :- | :- | :- |
    | `read_file` | `file` | `main.go` -> `{"file":"main.go"}` |
    | `write_file` | `file` | `output.txt` -> `{"file":"output.txt"}` |
    | `list_directory` | `dir` | `./src` -> `{"dir":"./src"}` |
    | `search_files` | `term` | `TODO` -> `{"term":"TODO"}` |
    | `run_command` | `cmd` | `go build` -> `{"cmd":"go build"}` |
    | `run_tests` | `dir` | `./pkg` -> `{"dir":"./pkg"}` |
  </Tab>

  <Tab title="Coder Subcommands">
    | Subcommand | Field | Example |
    | :- | :- | :- |
    | `read` | `file` | `config.yaml` -> `{"file":"config.yaml"}` |
    | `write` | `file` | `data.json` -> `{"file":"data.json"}` |
    | `exec` | `cmd` | `make test` -> `{"cmd":"make test"}` |
    | `search` | `term` | `func main` -> `{"term":"func main"}` |
    | `tree` | `dir` | `./internal` -> `{"dir":"./internal"}` |
  </Tab>

  <Tab title="Generic Aliases">
    | Alias | Field |
    | :- | :- |
    | `bash` / `shell` | `command` |
    | `Bash` | `command` |
    | `Read` / `Write` | `file_path` |
    | `Glob` / `Grep` | `pattern` |
    | `Edit` | `file_path` |
  </Tab>
</Tabs>

<Note>
  Wrapping is only applied when the value does **not** look like CLI arguments (no `--flags`) and does **not** start with `{` or `[`. This avoids conflicts with the existing CLI argument parser.
</Note>

***

## Unicode Quote Normalization

In addition to JSON recovery, ChatCLI normalizes curly (Unicode) quotes to straight (ASCII) quotes automatically. LLMs frequently generate typographic quotes that cause compilation errors:

| Character | Unicode | Replacement |
| :- | :- | :- |
| `'` `'` | U+2018, U+2019 | `'` (straight single quote) |
| `"` `"` | U+201C, U+201D | `"` (straight double quote) |
| `'` | U+2032 (prime) | `'` |
| `"` | U+2033 (double prime) | `"` |
| `<<` `>>` | U+00AB, U+00BB | `<<` `>>` |

Normalization is applied automatically to **code files** (60+ recognized extensions) and **always** to tool call arguments.

***

## Configuration

The recovery system works automatically without configuration. All strategies are applied in order until one produces valid JSON.

| Variable | Description | Default |
| :- | :- | :- |
| *(none)* | JSON recovery has no dedicated environment variables | Always active |

<Info>
  The recovery strategies are **non-destructive**: if none produces valid JSON, the original text is passed through so the CLI parser can attempt to interpret it as positional arguments.
</Info>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Plugin @coder" icon="hammer" href="/coder/coder-plugin">
    Complete reference for the tools that use JSON recovery.
  </Card>

  <Card title="Native Tool Use" icon="wrench" href="/agents/native-tool-use">
    With native tool use, JSON comes validated by the API -- less need for recovery.
  </Card>

  <Card title="Tool Result Management" icon="database" href="/context/tool-result-management">
    How tool results are managed after execution.
  </Card>

  <Card title="Coder Mode" icon="code" href="/usage/coder-mode">
    The complete engineering workflow with tool calls.
  </Card>
</CardGroup>


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