omni-dev 0.29.0

A powerful Git commit message analysis and amendment toolkit
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# AI Backends

omni-dev's AI features — `twiddle`, PR creation, JIRA/Confluence drafting,
`ai chat` — call out to a large language model through a pluggable
**backend**. Five backends are supported and selected at runtime by environment
variables or a CLI flag.

This guide covers what each backend is, how to wire it up, and how to choose
between them. For dev-facing notes on the dispatch implementation, see the
"AI Backend Dispatch" section of [CLAUDE.md](../CLAUDE.md).

## Table of Contents

1. [Backends at a Glance]#backends-at-a-glance
2. [Dispatch Order and Model Selection]#dispatch-order-and-model-selection
3. [Claude API (default)]#claude-api-default
4. [Claude CLI (sandboxed subprocess)]#claude-cli-sandboxed-subprocess
5. [OpenAI]#openai
6. [Ollama]#ollama
7. [AWS Bedrock]#aws-bedrock
8. [Claude CLI Deep-dive]#claude-cli-deep-dive
9. [Model Registry]#model-registry
10. [Choosing a Backend]#choosing-a-backend
11. [Troubleshooting]#troubleshooting

## Backends at a Glance

| Backend       | Selector                                                                         | Required credentials                                                                       | Default model                | Best when                                                            |
|---------------|----------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|------------------------------|----------------------------------------------------------------------|
| Claude CLI    | `--ai-backend claude-cli` or `OMNI_DEV_AI_BACKEND=claude-cli`                    | An authenticated `claude` CLI session                                                      | `claude-sonnet-4-6`          | You already use Claude Code and want to reuse its auth and billing.  |
| Ollama        | `USE_OLLAMA=true`                                                                | None (local server)                                                                        | `llama2`                     | Offline / local-only inference, experimenting with open models.      |
| OpenAI        | `USE_OPENAI=true`                                                                | `OPENAI_API_KEY` or `OPENAI_AUTH_TOKEN`                                                    | `gpt-5-mini` (registry)      | You're an OpenAI customer or want non-Claude models via OpenAI.      |
| AWS Bedrock   | `CLAUDE_CODE_USE_BEDROCK=true`                                                   | `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BEDROCK_BASE_URL`                                       | `claude-sonnet-4-6`          | Your org runs Anthropic models through AWS Bedrock.                  |
| Claude API    | *(default — no flag)*                                                            | `CLAUDE_API_KEY` or `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN`                          | `claude-sonnet-4-6`          | You have an Anthropic API key. Lowest-friction starting point.       |

## Dispatch Order and Model Selection

Backends are evaluated in a strict priority order — the first match wins.
The CLI flag or environment variable on the left is what selects the row;
later rows are ignored once an earlier one matches.

| Priority | Selector                                                | Backend       |
|----------|---------------------------------------------------------|---------------|
| 1        | `OMNI_DEV_AI_BACKEND=claude-cli` / `--ai-backend claude-cli` | Claude CLI |
| 2        | `USE_OLLAMA=true`                                       | Ollama        |
| 3        | `USE_OPENAI=true`                                       | OpenAI        |
| 4        | `CLAUDE_CODE_USE_BEDROCK=true`                          | AWS Bedrock   |
| 5        | *(none of the above)*                                   | Claude API    |

The CLI flag `--ai-backend claude-cli` takes precedence over the environment
variable when both are set.

**Model resolution.** Every backend resolves the model through the same
precedence chain, stopping at the first non-empty value:

1. `--model <id>` (CLI flag)
2. `CLAUDE_MODEL`
3. `CLAUDE_CODE_MODEL`
4. `ANTHROPIC_MODEL`
5. Provider-specific override (`OPENAI_MODEL`, `OLLAMA_MODEL`)
6. Registry default for the active provider

See the [Model Registry](#model-registry) section below for how to list,
override, or extend the catalogue.

## Claude API (default)

The default backend calls the Anthropic Messages API over HTTPS. No flags
required.

**Credentials.** Set one of (checked in order):

```bash
export CLAUDE_API_KEY="sk-ant-..."
# or
export ANTHROPIC_API_KEY="sk-ant-..."
# or
export ANTHROPIC_AUTH_TOKEN="sk-ant-..."
```

Get a key from [console.anthropic.com](https://console.anthropic.com/).

**Model.** Resolved from the precedence chain above. The registry default is
`claude-sonnet-4-6`. Override per-invocation with `--model`:

```bash
omni-dev --model claude-opus-4-6 git commit message twiddle 'origin/main..HEAD' --use-context
```

**Verification.**

```bash
export CLAUDE_API_KEY="sk-ant-..."
omni-dev git commit message twiddle 'origin/main..HEAD' --use-context
```

## Claude CLI (sandboxed subprocess)

Routes AI calls through an already-authenticated
[Claude Code](https://github.com/anthropics/claude-code) session by shelling
out to `claude -p` in a locked-down sandbox. This avoids provisioning a
separate API key when you already have Claude Code installed and signed in.

**Selection.** Either flag or env var works; the flag wins if both are set:

```bash
omni-dev --ai-backend claude-cli git commit message twiddle 'origin/main..HEAD' --use-context
# or persistently:
export OMNI_DEV_AI_BACKEND=claude-cli
```

**Credentials.** None passed by omni-dev — the nested `claude -p` process
uses whatever auth your `claude` CLI is configured with. Run `claude` once
interactively first to confirm it works on its own.

**Model.** Resolved through the standard chain. Short aliases (`sonnet`,
`opus`, `haiku`) and full identifiers (`claude-sonnet-4-6`) are both accepted
and forwarded verbatim to `claude -p --model`. The `--beta-header` flag is
**ignored** for this backend (`claude`'s `--betas` flag has different
semantics).

**Sandbox.** By default the nested session has no tools, no MCP servers, no
filesystem access, and a scrubbed environment. The [Claude CLI
Deep-dive](#claude-cli-deep-dive) section below covers what's blocked, the
escape hatches, and the spending cap.

**Verification.**

```bash
claude --version          # confirm the CLI is installed and authenticated
omni-dev --ai-backend claude-cli git commit message twiddle 'origin/main..HEAD' --use-context
```

## OpenAI

Calls the OpenAI Chat Completions API.

**Selection.**

```bash
export USE_OPENAI=true
```

**Credentials.** Set one of:

```bash
export OPENAI_API_KEY="sk-..."
# or
export OPENAI_AUTH_TOKEN="sk-..."
```

**Model.** Registry default is `gpt-5-mini`. Override with `OPENAI_MODEL` or
`--model`:

```bash
export OPENAI_MODEL="gpt-5"
# or
omni-dev --model gpt-5 git commit message twiddle ...
```

**Endpoint.** Fixed to `https://api.openai.com/v1/chat/completions`. To point
at an OpenAI-compatible third-party service running on a custom endpoint,
use the [Ollama](#ollama) backend (which exposes `OLLAMA_BASE_URL`).

**Limitations.**

- omni-dev requests structured output via JSON Schema (`response_format:
  json_schema`). Older OpenAI models that don't support `json_schema` will
  fail.
- GPT-5 series models use `max_completion_tokens` rather than `max_tokens`  omni-dev handles this automatically based on the model identifier.

**Verification.**

```bash
export USE_OPENAI=true
export OPENAI_API_KEY="sk-..."
omni-dev git commit message twiddle 'origin/main..HEAD' --use-context
```

## Ollama

Calls a local [Ollama](https://ollama.ai/) (or any OpenAI-compatible) server
over HTTP. No API key required.

**Selection.**

```bash
export USE_OLLAMA=true
```

**Endpoint.** Defaults to `http://localhost:11434`. Override with
`OLLAMA_BASE_URL` to target a remote Ollama server or a compatible service
like [LM Studio](https://lmstudio.ai/):

```bash
export OLLAMA_BASE_URL="http://gpu-box.local:11434"
```

**Model.** Defaults to `llama2`. Override with `OLLAMA_MODEL` or `--model`:

```bash
export OLLAMA_MODEL="llama3.1:70b"
```

The model must already be pulled into the local server (`ollama pull
llama3.1:70b`). omni-dev does not pull on demand.

**Context-length probing.** At startup, omni-dev queries the server for the
actually-loaded context window — LM Studio's `/api/v0/models` first, then
Ollama's `/api/show` as a fallback. The probed length is used for token
budgeting; if probing fails (older Ollama versions, custom servers), the
registry default applies and a debug log is emitted.

**Limitations.**

- Local models often have much smaller context windows than Claude / GPT —
  large `twiddle` ranges may need `--concurrency` tuning.
- Quality varies sharply by model size.
- JSON-schema enforcement depends on the model's instruction-following; small
  models may emit invalid YAML.

**Verification.**

```bash
ollama serve &              # if not already running
ollama pull llama3.1
export USE_OLLAMA=true
export OLLAMA_MODEL="llama3.1"
omni-dev git commit message twiddle 'HEAD~1..HEAD' --use-context
```

## AWS Bedrock

Routes Anthropic model calls through AWS Bedrock's bearer-token API.

**Selection.**

```bash
export CLAUDE_CODE_USE_BEDROCK=true
```

**Credentials.** Both are required:

```bash
export ANTHROPIC_AUTH_TOKEN="..."           # bearer token for the Bedrock endpoint
export ANTHROPIC_BEDROCK_BASE_URL="https://bedrock-runtime.<region>.amazonaws.com"
```

**Model.** Resolved through the standard chain (registry default
`claude-sonnet-4-6`). Bedrock identifiers are URL-encoded automatically when
invoking the API, and regional / provider prefixes are normalised by the
registry so any of these forms work for token-budget lookup:

- `claude-sonnet-4-6`
- `anthropic.claude-sonnet-4-6`
- `us.anthropic.claude-sonnet-4-6-v1:0`

Set whichever form your Bedrock deployment expects:

```bash
export ANTHROPIC_MODEL="us.anthropic.claude-sonnet-4-6-v1:0"
```

**Limitations.**

- Bedrock model availability is region-specific — not every Anthropic model
  is listed in every region.
- Inference profiles (the `us.`-prefixed regional IDs) may be required by
  your AWS account; check the Bedrock console.

**Verification.**

```bash
export CLAUDE_CODE_USE_BEDROCK=true
export ANTHROPIC_AUTH_TOKEN="..."
export ANTHROPIC_BEDROCK_BASE_URL="https://bedrock-runtime.us-east-1.amazonaws.com"
omni-dev git commit message twiddle 'origin/main..HEAD' --use-context
```

## Claude CLI Deep-dive

The `claude-cli` backend is the only one with sandbox semantics — it spawns
a real subprocess with elevated capabilities by default, so omni-dev locks
it down explicitly. This section documents what's blocked and how to relax
the sandbox when you need to.

### Sandbox defaults

Every invocation of the subprocess runs with this argv suffix and
environment treatment:

| Constraint                              | Mechanism                                                              |
|-----------------------------------------|------------------------------------------------------------------------|
| Built-in tools disabled                 | `--tools ""` (Read / Edit / Write / Bash / Glob / Grep are unavailable) |
| MCP servers blocked                     | `--strict-mcp-config` with no `--mcp-config`                           |
| User/project/local settings ignored     | `--setting-sources ""`                                                 |
| Slash commands and skills disabled      | `--disable-slash-commands`                                             |
| Session persistence off                 | `--no-session-persistence`                                             |
| Permission prompts disabled             | `--permission-mode default`                                            |
| Fresh working directory                 | Subprocess runs in a unique temp dir, not your repo root               |
| Environment scrubbed                    | `CLAUDE_PROJECT_DIR`, `CLAUDE_CODE_*`, `CLAUDE_PROJECT_*` removed      |
| Output capped                           | `OMNI_DEV_CLAUDE_CLI_STDOUT_MAX_BYTES` (default 4 MiB)                 |
| Wall-clock timeout                      | `OMNI_DEV_CLAUDE_CLI_TIMEOUT_SECS` (default 600)                       |

A defence-in-depth suffix is also appended to the system prompt instructing
the model not to emit `function_calls` XML.

### Tuning environment variables

| Variable                                  | Default        | Effect                                                              |
|-------------------------------------------|----------------|---------------------------------------------------------------------|
| `OMNI_DEV_CLAUDE_CLI_BIN`                 | `claude` (PATH) | Path to the `claude` binary.                                       |
| `OMNI_DEV_CLAUDE_CLI_TIMEOUT_SECS`        | `600`          | Wall-clock timeout for one subprocess invocation.                   |
| `OMNI_DEV_CLAUDE_CLI_STDOUT_MAX_BYTES`    | `4194304`      | Stdout cap; output beyond this aborts the invocation.               |

### Escape hatch: tool access

When the nested session needs filesystem or shell access:

```bash
omni-dev --ai-backend claude-cli --claude-cli-allow-tools git branch create pr
# or persistently:
export OMNI_DEV_CLAUDE_CLI_ALLOW_TOOLS=true
```

With this flag the `--tools ""` argument is removed from the subprocess argv,
so the nested session uses Claude Code's default tool set (Read, Edit, Write,
Bash, Glob, Grep) and can act on your filesystem and shell. All other
sandbox flags still apply unless you also enable
[MCP access](#escape-hatch-mcp-access).

A `WARN` log is emitted on every invocation while this is active. Grep for
it with `RUST_LOG=omni_dev=warn`:

```
claude -p sandbox weakened: tool-access escape hatch is enabled ...
```

### Escape hatch: MCP access

When the nested session needs MCP servers from your `~/.claude/settings.json`:

```bash
omni-dev --ai-backend claude-cli --claude-cli-allow-mcp git branch create pr
# or:
export OMNI_DEV_CLAUDE_CLI_ALLOW_MCP=true
```

With this flag the `--strict-mcp-config` argument is removed, so the nested
session can load any MCP server you have configured. **Be aware:** MCP
servers frequently hold OAuth tokens (Gmail, Drive, Slack) or expose internal
network services — enabling this exposes them to the nested session. Use
deliberately.

A `WARN` log is emitted on every invocation while this is active:

```
claude -p sandbox weakened: MCP-access escape hatch is enabled ...
```

The two escape hatches are independent — enable tools without MCP, MCP
without tools, both, or neither.

### Spending cap

Pass a per-invocation cap in USD:

```bash
omni-dev --ai-backend claude-cli --claude-cli-max-budget-usd 0.50 \
  git commit message twiddle 'HEAD~3..HEAD'
# or:
export OMNI_DEV_CLAUDE_CLI_MAX_BUDGET_USD=0.50
```

The value is forwarded to `claude -p --max-budget-usd`. If the nested
session exceeds the cap it aborts with an error rather than running away
with cost. Non-positive, non-finite, or non-numeric values are silently
treated as no cap. The cap is ignored on backends other than `claude-cli`.

Regardless of whether a cap is set, every invocation's `total_cost_usd` is
logged at `INFO` level — run with `RUST_LOG=omni_dev=info` to see it:

```
claude -p invocation cost total_cost_usd=0.0341 max_budget_usd=Some(0.5) model="claude-sonnet-4-6"
```

If the reported cost ever exceeds the configured cap, an additional `WARN`
is emitted.

### When to choose the CLI backend

Use `claude-cli` when:

- You're running inside an existing Claude Code session that already holds
  Anthropic credentials, and you don't want to manage a second API key.
- You want all Anthropic spend to flow through one billing source.
- You explicitly want the sandbox semantics described above.

Prefer the direct [Claude API](#claude-api-default) when:

- You're running in CI or another non-interactive environment where the
  `claude` CLI isn't installed.
- You care about the per-invocation cost floor — the `claude -p` system
  prompt has a small fixed cost (~$0.007 Haiku, ~$0.03 Sonnet, ~$0.15 Opus)
  on each call that the direct API doesn't have.

## Model Registry

omni-dev ships with a built-in catalogue of model identifiers and their
token limits. Inspect it with:

```bash
omni-dev config models show              # merged catalogue with source annotations
omni-dev config models show --embedded-only   # just the built-in entries
```

**Catalogue precedence** — entries from later files override earlier ones:

1. Built-in [src/templates/models.yaml]../src/templates/models.yaml
2. `~/.omni-dev/models.yaml` (user-level)
3. `./.omni-dev/models.yaml` (project-local)
4. The path in `OMNI_DEV_MODELS_YAML` (if set — short-circuits user/project)

**Bedrock identifiers** are normalised before lookup: regional prefixes
(`us.anthropic.…`), provider prefixes (`anthropic.…`), and version suffixes
(`…-v1:0`) are stripped so the same registry entry serves every form your
Bedrock deployment might emit.

**Architectural background:**
[ADR-0011](adrs/adr-0011.md) (superseded) and
[ADR-0022](adrs/adr-0022.md) (current) — the layered catalogue with user and
project overrides.

## Choosing a Backend

| Criterion           | Claude CLI                    | Claude API                | OpenAI                | Ollama                  | Bedrock                |
|---------------------|-------------------------------|---------------------------|-----------------------|-------------------------|------------------------|
| Setup effort        | Already have Claude Code? Zero | Get an API key           | Get an API key       | Install Ollama + pull model | Configure AWS / endpoint |
| Latency             | High (subprocess spawn)       | Low                       | Low                   | Depends on hardware     | Low                    |
| Per-call floor cost | ~$0.007–$0.15 system prompt   | None                      | None                  | Free (local)            | None                   |
| Sandboxed           | Yes (configurable)            | n/a                       | n/a                   | n/a                     | n/a                    |
| Offline support     | No                            | No                        | No                    | **Yes**                 | No                     |
| Best model quality  | Claude flagship               | Claude flagship           | GPT flagship          | Variable                | Claude flagship        |
| Choose when…        | You already use Claude Code   | Default, simplest path    | OpenAI customer       | Local-only / offline    | AWS shop, Bedrock-only |

Most users should start with the default [Claude API](#claude-api-default)
backend. Move to `claude-cli` once you have Claude Code installed; move to
Bedrock or OpenAI when your organisation requires it; reach for Ollama when
you need offline / local inference.

## Troubleshooting

See the [Troubleshooting Guide](troubleshooting.md) for backend-specific
errors. The most common cases:

| Error                                           | Likely backend     | See                                                                 |
|-------------------------------------------------|--------------------|---------------------------------------------------------------------|
| `CLAUDE_API_KEY not found`                      | Claude API         | [troubleshooting.md]troubleshooting.md#error-claude_api_key-not-found |
| `the assistant tried to use a tool …`           | Claude CLI         | [troubleshooting.md]troubleshooting.md#claude-cli-backend-issues  |
| `MCP server X not loaded`                       | Claude CLI         | [troubleshooting.md]troubleshooting.md#claude-cli-backend-issues  |
| `claude -p exited with cost cap exceeded`       | Claude CLI         | [troubleshooting.md]troubleshooting.md#claude-cli-backend-issues  |
| Connection refused on `localhost:11434`         | Ollama             | Start `ollama serve` or set `OLLAMA_BASE_URL`.                      |
| `401 Unauthorized` from OpenAI                  | OpenAI             | Check `OPENAI_API_KEY` / `OPENAI_AUTH_TOKEN`.                       |
| `AccessDeniedException` on a model ID           | Bedrock            | Region doesn't have the model, or your IAM policy blocks it.        |

Enable verbose logging when reporting issues:

```bash
RUST_LOG=omni_dev=debug omni-dev git commit message twiddle 'HEAD~1..HEAD' --use-context
```