# OpenCode

> The opencode-statejar plugin adds the memory each message needs to OpenCode's system prompt, captures your messages with secrets removed, and comes with StateJar's tools. Add it and the MCP server to opencode.json.

## What it does

- **Recall.** Before the model answers, OpenCode gets the memory your message needs, as part of its system prompt. StateJar sends the whole state while it is small, and only the fields a question needs once it is large. Every recall names the handle it came from (`shm_…`) and is written to your audit log.
- **Capture.** Your messages are queued on your machine with secrets removed: API keys and tokens, private keys, passwords and card numbers. The queue is sent in batches: after a few messages, at compaction and when OpenCode exits. StateJar extracts typed facts from them, refuses a value that fails its type, and keeps a fact said once in a weak form until it is said again. It stores no transcript.
- **Tools.**
  - The ten tools of StateJar's [MCP server](/docs/mcp.html), which OpenCode names `statejar_search`, `statejar_remember` and so on.
  - The plugin's own `statejar_status`, `statejar_pause` and `statejar_resume`.

The plugin is `opencode-statejar` on npm, open source (MIT) in [statejar-integrations](https://github.com/KING-OF-FLAME/statejar-integrations).

## Install

You need OpenCode 1.19 or later. Add the plugin and the MCP server to `opencode.json`, in your project or in `~/.config/opencode/opencode.json` for every project:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-statejar"],
  "mcp": {
    "statejar": {
      "type": "remote",
      "url": "https://statejar.com/mcp",
      "oauth": false,
      "headers": { "Authorization": "Bearer {env:STATEJAR_API_KEY}" }
    }
  }
}
```

OpenCode installs the plugin from npm at its next start. `{env:STATEJAR_API_KEY}` keeps the key out of the file.

**Tools only, without the plugin:** keep the `mcp` block and leave out `plugin`.

## Set it up

Make a developer key on the [API keys page](/api-keys) and put it in the environment OpenCode runs in:

```bash
export STATEJAR_API_KEY="sj_live_…"        # macOS, Linux
```

```powershell
setx STATEJAR_API_KEY "sj_live_…"          # Windows: a new terminal picks it up
```

The other options are variables, or the plugin's options in `opencode.json` (`"plugin": [["opencode-statejar", { "scope": "my-project" }]]`):

| Variable | Option | Default | What it does |
|---|---|---|---|
| `STATEJAR_SCOPE` | `scope` | `opencode` | The scope in your account the plugin reads and writes. A new scope builds on your newest memory. |
| `STATEJAR_AUTO_CAPTURE` | `autoCapture` | `true` | Queue your messages and send them in batches. |
| `STATEJAR_RECALL_EACH_PROMPT` | `recallEachPrompt` | `true` | Add the memory each message needs, as one audited query per message. |
| `STATEJAR_API_URL` | `apiUrl` | `https://api.statejar.com/api/v1` | The REST API the plugin calls. |

If `STATEJAR_API_KEY` is empty, the plugin uses the key that `statejar login` (the `statejar` package on PyPI) keeps. The MCP tools still need the variable.

## Check it works

1. `opencode mcp list` shows `statejar` connected.
2. In a session, say "I'm Kavya, I live in Bengaluru and my laptop budget is 80000 rupees." Then exit OpenCode.
3. Start OpenCode again and ask "what is my laptop budget?". The answer uses the budget and names the handle it came from.
4. Ask for StateJar's status. The `statejar_status` tool shows the scope, what is queued, and the last batch's status (202 when accepted).

## What it sends

- **Leaves your machine:** each recall sends the question (your message) to StateJar's query endpoint. Each batch sends your queued messages, with secrets already removed. Nothing goes anywhere else.
- **Stays on your machine:** the queue lives in `statejar/clients/opencode`, mode 600, beside the credentials file of `statejar login` (`~/.config` on macOS and Linux, `%APPDATA%` on Windows). Its `state.json` holds only counts, times and the last status code.
- **What StateJar stores:** typed facts, never your messages. Every disclosure is in your [audit log](/audit), and deleting your account deletes all of it.
- **What the plugin never reads:** the model's replies, your code and your files.
- `statejar_pause` stops recall and capture until `statejar_resume`.

## Troubleshooting

- **"no developer key yet" in the model's context:** `STATEJAR_API_KEY` is not set where OpenCode runs, and there is no `statejar login` key.
- **`401` from the tools:** the key is wrong or revoked. Make a new one and set the variable again.
- **OpenCode asks you to sign in to the MCP server:** `"oauth": false` is missing from the `statejar` entry.
- **`429` in `statejar_status`:** your plan's per-minute or monthly limit ([what each limit counts](/docs/pricing-and-payments.html)). The batch stays queued and is sent later.
- **Nothing is captured:** `statejar_status` says whether memory is paused. Messages of under three words and commands are not captured.
