rafcode 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +4 -1
- package/CLAUDE.md +59 -11
- package/RAF/ahslfe-config-wizard/decisions.md +34 -0
- package/RAF/ahslfe-config-wizard/input.md +1 -0
- package/RAF/ahslfe-config-wizard/outcomes/01-define-config-schema.md +38 -0
- package/RAF/ahslfe-config-wizard/outcomes/02-refactor-codebase-to-use-config.md +67 -0
- package/RAF/ahslfe-config-wizard/outcomes/03-create-config-documentation.md +37 -0
- package/RAF/ahslfe-config-wizard/outcomes/04-implement-raf-config-command.md +47 -0
- package/RAF/ahslfe-config-wizard/outcomes/05-update-claude-md.md +26 -0
- package/RAF/ahslfe-config-wizard/plans/01-define-config-schema.md +73 -0
- package/RAF/ahslfe-config-wizard/plans/02-refactor-codebase-to-use-config.md +74 -0
- package/RAF/ahslfe-config-wizard/plans/03-create-config-documentation.md +57 -0
- package/RAF/ahslfe-config-wizard/plans/04-implement-raf-config-command.md +66 -0
- package/RAF/ahslfe-config-wizard/plans/05-update-claude-md.md +60 -0
- package/RAF/ahstvo-token-tracker/decisions.md +44 -0
- package/RAF/ahstvo-token-tracker/input.md +3 -0
- package/RAF/ahstvo-token-tracker/outcomes/01-full-model-id-support.md +43 -0
- package/RAF/ahstvo-token-tracker/outcomes/02-name-generation-no-session.md +33 -0
- package/RAF/ahstvo-token-tracker/outcomes/03-unify-stream-json-execution.md +48 -0
- package/RAF/ahstvo-token-tracker/outcomes/04-token-tracking-cost-calculation.md +53 -0
- package/RAF/ahstvo-token-tracker/outcomes/05-token-cost-console-reporting.md +57 -0
- package/RAF/ahstvo-token-tracker/outcomes/06-runtime-verbose-toggle.md +53 -0
- package/RAF/ahstvo-token-tracker/outcomes/07-readme-config-docs.md +36 -0
- package/RAF/ahstvo-token-tracker/plans/01-full-model-id-support.md +35 -0
- package/RAF/ahstvo-token-tracker/plans/02-name-generation-no-session.md +36 -0
- package/RAF/ahstvo-token-tracker/plans/03-unify-stream-json-execution.md +44 -0
- package/RAF/ahstvo-token-tracker/plans/04-token-tracking-cost-calculation.md +56 -0
- package/RAF/ahstvo-token-tracker/plans/05-token-cost-console-reporting.md +55 -0
- package/RAF/ahstvo-token-tracker/plans/06-runtime-verbose-toggle.md +48 -0
- package/RAF/ahstvo-token-tracker/plans/07-readme-config-docs.md +44 -0
- package/RAF/ahtahs-token-reaper/decisions.md +37 -0
- package/RAF/ahtahs-token-reaper/input.md +20 -0
- package/RAF/ahtahs-token-reaper/outcomes/01-extend-token-tracker-data-model.md +42 -0
- package/RAF/ahtahs-token-reaper/outcomes/02-accumulate-usage-in-retry-loop.md +31 -0
- package/RAF/ahtahs-token-reaper/outcomes/03-per-attempt-display-formatting.md +60 -0
- package/RAF/ahtahs-token-reaper/outcomes/04-add-model-name-to-claude-call-logs.md +57 -0
- package/RAF/ahtahs-token-reaper/outcomes/05-handle-invalid-config-in-raf-config.md +46 -0
- package/RAF/ahtahs-token-reaper/outcomes/06-fix-verbose-toggle-timer-display.md +38 -0
- package/RAF/ahtahs-token-reaper/plans/01-extend-token-tracker-data-model.md +36 -0
- package/RAF/ahtahs-token-reaper/plans/02-accumulate-usage-in-retry-loop.md +36 -0
- package/RAF/ahtahs-token-reaper/plans/03-per-attempt-display-formatting.md +43 -0
- package/RAF/ahtahs-token-reaper/plans/04-add-model-name-to-claude-call-logs.md +38 -0
- package/RAF/ahtahs-token-reaper/plans/05-handle-invalid-config-in-raf-config.md +36 -0
- package/RAF/ahtahs-token-reaper/plans/06-fix-verbose-toggle-timer-display.md +40 -0
- package/README.md +34 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +195 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/do.d.ts.map +1 -1
- package/dist/commands/do.js +55 -7
- package/dist/commands/do.js.map +1 -1
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +5 -3
- package/dist/commands/plan.js.map +1 -1
- package/dist/core/claude-runner.d.ts +19 -2
- package/dist/core/claude-runner.d.ts.map +1 -1
- package/dist/core/claude-runner.js +43 -96
- package/dist/core/claude-runner.js.map +1 -1
- package/dist/core/failure-analyzer.d.ts.map +1 -1
- package/dist/core/failure-analyzer.js +6 -3
- package/dist/core/failure-analyzer.js.map +1 -1
- package/dist/core/git.d.ts.map +1 -1
- package/dist/core/git.js +10 -3
- package/dist/core/git.js.map +1 -1
- package/dist/core/pull-request.d.ts +1 -1
- package/dist/core/pull-request.d.ts.map +1 -1
- package/dist/core/pull-request.js +9 -4
- package/dist/core/pull-request.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/parsers/stream-renderer.d.ts +16 -1
- package/dist/parsers/stream-renderer.d.ts.map +1 -1
- package/dist/parsers/stream-renderer.js +34 -4
- package/dist/parsers/stream-renderer.js.map +1 -1
- package/dist/prompts/execution.d.ts.map +1 -1
- package/dist/prompts/execution.js +11 -1
- package/dist/prompts/execution.js.map +1 -1
- package/dist/types/config.d.ts +95 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +63 -3
- package/dist/types/config.js.map +1 -1
- package/dist/utils/config.d.ts +65 -7
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +297 -21
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/name-generator.d.ts +3 -7
- package/dist/utils/name-generator.d.ts.map +1 -1
- package/dist/utils/name-generator.js +75 -61
- package/dist/utils/name-generator.js.map +1 -1
- package/dist/utils/terminal-symbols.d.ts +25 -0
- package/dist/utils/terminal-symbols.d.ts.map +1 -1
- package/dist/utils/terminal-symbols.js +87 -0
- package/dist/utils/terminal-symbols.js.map +1 -1
- package/dist/utils/token-tracker.d.ts +55 -0
- package/dist/utils/token-tracker.d.ts.map +1 -0
- package/dist/utils/token-tracker.js +142 -0
- package/dist/utils/token-tracker.js.map +1 -0
- package/dist/utils/validation.d.ts +5 -5
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +10 -6
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/verbose-toggle.d.ts +33 -0
- package/dist/utils/verbose-toggle.d.ts.map +1 -0
- package/dist/utils/verbose-toggle.js +94 -0
- package/dist/utils/verbose-toggle.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/config.ts +230 -0
- package/src/commands/do.ts +64 -6
- package/src/commands/plan.ts +5 -3
- package/src/core/claude-runner.ts +59 -115
- package/src/core/failure-analyzer.ts +6 -3
- package/src/core/git.ts +10 -3
- package/src/core/pull-request.ts +9 -4
- package/src/index.ts +2 -0
- package/src/parsers/stream-renderer.ts +54 -4
- package/src/prompts/config-docs.md +331 -0
- package/src/prompts/execution.ts +13 -1
- package/src/types/config.ts +156 -7
- package/src/utils/config.ts +357 -21
- package/src/utils/name-generator.ts +84 -71
- package/src/utils/terminal-symbols.ts +103 -0
- package/src/utils/token-tracker.ts +177 -0
- package/src/utils/validation.ts +15 -10
- package/src/utils/verbose-toggle.ts +103 -0
- package/tests/unit/claude-runner.test.ts +171 -7
- package/tests/unit/config-command.test.ts +242 -0
- package/tests/unit/config.test.ts +632 -30
- package/tests/unit/name-generator.test.ts +99 -75
- package/tests/unit/pull-request.test.ts +2 -0
- package/tests/unit/stream-renderer.test.ts +83 -0
- package/tests/unit/terminal-symbols.test.ts +245 -0
- package/tests/unit/timer-verbose-integration.test.ts +170 -0
- package/tests/unit/token-tracker.test.ts +685 -0
- package/tests/unit/verbose-toggle.test.ts +204 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# RAF Configuration Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
RAF uses a JSON configuration file at `~/.raf/raf.config.json` to control its behavior. All keys are optional — only set what you want to change. Unset keys use sensible defaults.
|
|
6
|
+
|
|
7
|
+
The config is loaded once per process and cached. Changes take effect on the next RAF command invocation.
|
|
8
|
+
|
|
9
|
+
## File Format
|
|
10
|
+
|
|
11
|
+
The config file is a JSON object. All keys are optional at every level. User values are deep-merged with defaults: you can override a single nested key without specifying the entire object.
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"models": {
|
|
16
|
+
"plan": "opus"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The above only changes `models.plan` — all other model settings keep their defaults.
|
|
22
|
+
|
|
23
|
+
## Config Reference
|
|
24
|
+
|
|
25
|
+
### `models` — Claude Model Selection
|
|
26
|
+
|
|
27
|
+
Controls which Claude model is used for each scenario. Values can be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID.
|
|
28
|
+
|
|
29
|
+
**Model ID format**: Full model IDs follow the pattern `claude-{family}-{version}`, for example:
|
|
30
|
+
- `"claude-opus-4-5-20251101"` — Opus 4.5 from November 2025
|
|
31
|
+
- `"claude-opus-4-6"` — Opus 4.6 (latest)
|
|
32
|
+
- `"claude-sonnet-4-5-20250929"` — Sonnet 4.5 from September 2025
|
|
33
|
+
- `"claude-haiku-4-5-20251001"` — Haiku 4.5 from October 2025
|
|
34
|
+
|
|
35
|
+
**Short aliases**: Using aliases (`"opus"`, `"sonnet"`, `"haiku"`) automatically selects the latest version of that model family.
|
|
36
|
+
|
|
37
|
+
| Key | Default | Description |
|
|
38
|
+
|-----|---------|-------------|
|
|
39
|
+
| `models.plan` | `"opus"` | Model used for planning sessions (`raf plan`) |
|
|
40
|
+
| `models.execute` | `"opus"` | Model used for task execution (`raf do`) |
|
|
41
|
+
| `models.nameGeneration` | `"sonnet"` | Model used for generating project names |
|
|
42
|
+
| `models.failureAnalysis` | `"haiku"` | Model used for analyzing task failures |
|
|
43
|
+
| `models.prGeneration` | `"sonnet"` | Model used for generating PR titles and descriptions |
|
|
44
|
+
| `models.config` | `"sonnet"` | Model used for the interactive config editor (`raf config`) |
|
|
45
|
+
|
|
46
|
+
### `effort` — Claude Effort Level
|
|
47
|
+
|
|
48
|
+
Controls the effort level passed to Claude for each scenario. All values must be one of: `"low"`, `"medium"`, `"high"`.
|
|
49
|
+
|
|
50
|
+
| Key | Default | Description |
|
|
51
|
+
|-----|---------|-------------|
|
|
52
|
+
| `effort.plan` | `"high"` | Effort level for planning sessions |
|
|
53
|
+
| `effort.execute` | `"medium"` | Effort level for task execution |
|
|
54
|
+
| `effort.nameGeneration` | `"low"` | Effort level for project name generation |
|
|
55
|
+
| `effort.failureAnalysis` | `"low"` | Effort level for failure analysis |
|
|
56
|
+
| `effort.prGeneration` | `"medium"` | Effort level for PR generation |
|
|
57
|
+
| `effort.config` | `"medium"` | Effort level for config editing sessions |
|
|
58
|
+
|
|
59
|
+
### `timeout` — Task Timeout
|
|
60
|
+
|
|
61
|
+
- **Type**: number (positive)
|
|
62
|
+
- **Default**: `60`
|
|
63
|
+
- **Description**: Timeout in minutes for each task execution. Must be a positive number.
|
|
64
|
+
|
|
65
|
+
### `maxRetries` — Maximum Retry Attempts
|
|
66
|
+
|
|
67
|
+
- **Type**: number (non-negative integer)
|
|
68
|
+
- **Default**: `3`
|
|
69
|
+
- **Description**: How many times RAF retries a failed task before giving up. Must be a non-negative integer (0 disables retries).
|
|
70
|
+
|
|
71
|
+
### `autoCommit` — Automatic Git Commits
|
|
72
|
+
|
|
73
|
+
- **Type**: boolean
|
|
74
|
+
- **Default**: `true`
|
|
75
|
+
- **Description**: When `true`, Claude automatically commits changes after completing each task. When `false`, changes are left uncommitted.
|
|
76
|
+
|
|
77
|
+
### `worktree` — Default Worktree Mode
|
|
78
|
+
|
|
79
|
+
- **Type**: boolean
|
|
80
|
+
- **Default**: `false`
|
|
81
|
+
- **Description**: When `true`, `raf plan` and `raf do` default to worktree mode (isolated git worktree). Can be overridden per-command with `--worktree` flag.
|
|
82
|
+
|
|
83
|
+
### `commitFormat` — Commit Message Templates
|
|
84
|
+
|
|
85
|
+
Controls the format of git commit messages. Templates use `{placeholder}` syntax for variable substitution.
|
|
86
|
+
|
|
87
|
+
| Key | Default | Description |
|
|
88
|
+
|-----|---------|-------------|
|
|
89
|
+
| `commitFormat.task` | `"{prefix}[{projectId}:{taskId}] {description}"` | Format for task completion commits |
|
|
90
|
+
| `commitFormat.plan` | `"{prefix}[{projectId}] Plan: {projectName}"` | Format for plan creation commits |
|
|
91
|
+
| `commitFormat.amend` | `"{prefix}[{projectId}] Amend: {projectName}"` | Format for plan amendment commits |
|
|
92
|
+
| `commitFormat.prefix` | `"RAF"` | Prefix string substituted into `{prefix}` placeholder |
|
|
93
|
+
|
|
94
|
+
#### Template Variables
|
|
95
|
+
|
|
96
|
+
**Task commits** (`commitFormat.task`):
|
|
97
|
+
- `{prefix}` — The value of `commitFormat.prefix`
|
|
98
|
+
- `{projectId}` — The 6-character project identifier (e.g., `abcdef`)
|
|
99
|
+
- `{taskId}` — The 2-character task identifier (e.g., `01`, `0a`)
|
|
100
|
+
- `{description}` — A concise description of what was accomplished
|
|
101
|
+
|
|
102
|
+
**Plan commits** (`commitFormat.plan`):
|
|
103
|
+
- `{prefix}` — The value of `commitFormat.prefix`
|
|
104
|
+
- `{projectId}` — The 6-character project identifier
|
|
105
|
+
- `{projectName}` — The human-readable project name (e.g., `fix-auth-bug`)
|
|
106
|
+
|
|
107
|
+
**Amend commits** (`commitFormat.amend`):
|
|
108
|
+
- `{prefix}` — The value of `commitFormat.prefix`
|
|
109
|
+
- `{projectId}` — The 6-character project identifier
|
|
110
|
+
- `{projectName}` — The human-readable project name
|
|
111
|
+
|
|
112
|
+
Unknown placeholders are left as-is in the output.
|
|
113
|
+
|
|
114
|
+
### `pricing` — Token Cost Pricing
|
|
115
|
+
|
|
116
|
+
Controls per-model token pricing used for cost estimation. Prices are in dollars per million tokens. Each model category (`opus`, `sonnet`, `haiku`) has four pricing fields:
|
|
117
|
+
|
|
118
|
+
| Field | Description |
|
|
119
|
+
|-------|-------------|
|
|
120
|
+
| `inputPerMTok` | Cost per million input tokens |
|
|
121
|
+
| `outputPerMTok` | Cost per million output tokens |
|
|
122
|
+
| `cacheReadPerMTok` | Cost per million cache read tokens (discounted) |
|
|
123
|
+
| `cacheCreatePerMTok` | Cost per million cache creation tokens |
|
|
124
|
+
|
|
125
|
+
**Default values:**
|
|
126
|
+
|
|
127
|
+
| Category | Input | Output | Cache Read | Cache Create |
|
|
128
|
+
|----------|-------|--------|------------|--------------|
|
|
129
|
+
| `opus` | $15 | $75 | $1.50 | $18.75 |
|
|
130
|
+
| `sonnet` | $3 | $15 | $0.30 | $3.75 |
|
|
131
|
+
| `haiku` | $1 | $5 | $0.10 | $1.25 |
|
|
132
|
+
|
|
133
|
+
Full model IDs from CLI output (e.g., `claude-opus-4-6`) are automatically mapped to the corresponding pricing category based on the model family name.
|
|
134
|
+
|
|
135
|
+
Example override:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"pricing": {
|
|
140
|
+
"opus": {
|
|
141
|
+
"inputPerMTok": 10,
|
|
142
|
+
"outputPerMTok": 50
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Only specify the fields you want to change — unset fields keep their defaults.
|
|
149
|
+
|
|
150
|
+
### `claudeCommand` — Claude CLI Path
|
|
151
|
+
|
|
152
|
+
- **Type**: string (non-empty)
|
|
153
|
+
- **Default**: `"claude"`
|
|
154
|
+
- **Description**: The command or path used to invoke the Claude CLI. Change this if `claude` is not on your PATH or you want to use a wrapper script.
|
|
155
|
+
|
|
156
|
+
## Validation Rules
|
|
157
|
+
|
|
158
|
+
The config is validated when loaded. Invalid configs cause an error with a descriptive message. The following rules are enforced:
|
|
159
|
+
|
|
160
|
+
- **Unknown keys are rejected** at every nesting level. Typos like `"model"` instead of `"models"` will be caught.
|
|
161
|
+
- **Model values** must be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID matching the pattern `claude-{family}-{version}` (e.g., `"claude-sonnet-4-5-20250929"`).
|
|
162
|
+
- **Effort values** must be exactly `"low"`, `"medium"`, or `"high"` (case-sensitive).
|
|
163
|
+
- **`timeout`** must be a positive finite number.
|
|
164
|
+
- **`maxRetries`** must be a non-negative integer.
|
|
165
|
+
- **`autoCommit`** and **`worktree`** must be booleans.
|
|
166
|
+
- **`commitFormat` values** must be strings.
|
|
167
|
+
- **`claudeCommand`** must be a non-empty string.
|
|
168
|
+
- **`pricing`** categories must be `"opus"`, `"sonnet"`, or `"haiku"`. Each field must be a non-negative number.
|
|
169
|
+
- The config file must be valid JSON containing an object (not an array or primitive).
|
|
170
|
+
|
|
171
|
+
## CLI Precedence
|
|
172
|
+
|
|
173
|
+
CLI flags always override config values. For example:
|
|
174
|
+
|
|
175
|
+
- `raf do --model haiku` uses Haiku regardless of `models.execute` in config
|
|
176
|
+
- `raf plan --worktree` enables worktree mode regardless of the `worktree` config value
|
|
177
|
+
|
|
178
|
+
The precedence order is: **CLI flag > config file > default value**.
|
|
179
|
+
|
|
180
|
+
## Example Configs
|
|
181
|
+
|
|
182
|
+
### Minimal — Just Change the Default Model
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"models": {
|
|
187
|
+
"execute": "sonnet"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Uses Sonnet instead of Opus for task execution. Everything else stays at defaults.
|
|
193
|
+
|
|
194
|
+
### Common — Cost-Conscious Setup
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"models": {
|
|
199
|
+
"plan": "sonnet",
|
|
200
|
+
"execute": "sonnet"
|
|
201
|
+
},
|
|
202
|
+
"effort": {
|
|
203
|
+
"plan": "medium"
|
|
204
|
+
},
|
|
205
|
+
"worktree": true
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Uses Sonnet for both planning and execution, reduces planning effort, and defaults to worktree mode.
|
|
210
|
+
|
|
211
|
+
### Full — All Settings Explicit
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"models": {
|
|
216
|
+
"plan": "opus",
|
|
217
|
+
"execute": "opus",
|
|
218
|
+
"nameGeneration": "sonnet",
|
|
219
|
+
"failureAnalysis": "haiku",
|
|
220
|
+
"prGeneration": "sonnet",
|
|
221
|
+
"config": "sonnet"
|
|
222
|
+
},
|
|
223
|
+
"effort": {
|
|
224
|
+
"plan": "high",
|
|
225
|
+
"execute": "medium",
|
|
226
|
+
"nameGeneration": "low",
|
|
227
|
+
"failureAnalysis": "low",
|
|
228
|
+
"prGeneration": "medium",
|
|
229
|
+
"config": "medium"
|
|
230
|
+
},
|
|
231
|
+
"timeout": 60,
|
|
232
|
+
"maxRetries": 3,
|
|
233
|
+
"autoCommit": true,
|
|
234
|
+
"worktree": false,
|
|
235
|
+
"commitFormat": {
|
|
236
|
+
"task": "{prefix}[{projectId}:{taskId}] {description}",
|
|
237
|
+
"plan": "{prefix}[{projectId}] Plan: {projectName}",
|
|
238
|
+
"amend": "{prefix}[{projectId}] Amend: {projectName}",
|
|
239
|
+
"prefix": "RAF"
|
|
240
|
+
},
|
|
241
|
+
"claudeCommand": "claude",
|
|
242
|
+
"pricing": {
|
|
243
|
+
"opus": { "inputPerMTok": 15, "outputPerMTok": 75, "cacheReadPerMTok": 1.5, "cacheCreatePerMTok": 18.75 },
|
|
244
|
+
"sonnet": { "inputPerMTok": 3, "outputPerMTok": 15, "cacheReadPerMTok": 0.3, "cacheCreatePerMTok": 3.75 },
|
|
245
|
+
"haiku": { "inputPerMTok": 1, "outputPerMTok": 5, "cacheReadPerMTok": 0.1, "cacheCreatePerMTok": 1.25 }
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
This is equivalent to having no config file at all — all values match the defaults.
|
|
251
|
+
|
|
252
|
+
### Pinned Model Versions
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"models": {
|
|
257
|
+
"plan": "claude-opus-4-5-20251101",
|
|
258
|
+
"execute": "claude-sonnet-4-5-20250929"
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Uses specific model versions for planning and execution. Useful for pinning to a known-good model version.
|
|
264
|
+
|
|
265
|
+
### Team Branding — Custom Commit Prefix
|
|
266
|
+
|
|
267
|
+
```json
|
|
268
|
+
{
|
|
269
|
+
"commitFormat": {
|
|
270
|
+
"prefix": "ACME"
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Commits will read `ACME[abcdef:01] Add login page` instead of `RAF[abcdef:01] Add login page`.
|
|
276
|
+
|
|
277
|
+
## Resetting to Defaults
|
|
278
|
+
|
|
279
|
+
To reset all settings to defaults, delete the config file:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
rm ~/.raf/raf.config.json
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
To reset a single setting, remove its key from the config file. Any key not present in the file will use its default value.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## For Claude — Config Editing Session Instructions
|
|
290
|
+
|
|
291
|
+
This section contains instructions for Claude when operating as the interactive config editor during `raf config` sessions.
|
|
292
|
+
|
|
293
|
+
### Your Role
|
|
294
|
+
|
|
295
|
+
You are helping the user view and edit their RAF configuration. Be helpful, explain what each setting does when asked, and make changes accurately.
|
|
296
|
+
|
|
297
|
+
### Reading the Config
|
|
298
|
+
|
|
299
|
+
1. Read the current config file at `~/.raf/raf.config.json`
|
|
300
|
+
2. If the file does not exist, tell the user they have no custom config and all defaults are active
|
|
301
|
+
3. Show the user their current settings when asked, noting which are custom vs. default
|
|
302
|
+
|
|
303
|
+
### Making Changes
|
|
304
|
+
|
|
305
|
+
1. **Only change what the user asks for.** Never modify keys the user didn't mention.
|
|
306
|
+
2. **Write partial configs.** Only include keys that differ from defaults. If the user sets a value back to its default, remove that key.
|
|
307
|
+
3. **Validate before saving.** Ensure all values conform to the validation rules above before writing the file.
|
|
308
|
+
4. **Create the directory if needed.** If `~/.raf/` doesn't exist, create it before writing the file.
|
|
309
|
+
5. **Preserve existing keys.** Read the current file first, merge the user's changes, then write the result.
|
|
310
|
+
|
|
311
|
+
### Explaining Changes
|
|
312
|
+
|
|
313
|
+
After making a change, briefly confirm what was changed and what the effective value is. For example:
|
|
314
|
+
|
|
315
|
+
> Set `models.execute` to `"sonnet"`. Task execution will now use the Sonnet model instead of Opus.
|
|
316
|
+
|
|
317
|
+
### Showing Current Config
|
|
318
|
+
|
|
319
|
+
When the user asks to see their config, show:
|
|
320
|
+
1. Their custom settings (from the config file)
|
|
321
|
+
2. The effective resolved config (custom + defaults merged)
|
|
322
|
+
|
|
323
|
+
Distinguish between user-set values and defaults so the user knows what they've customized.
|
|
324
|
+
|
|
325
|
+
### Common User Requests
|
|
326
|
+
|
|
327
|
+
- **"Show my config"** — Read and display the config file, noting defaults
|
|
328
|
+
- **"Use sonnet for everything"** — Set all `models.*` keys to `"sonnet"`
|
|
329
|
+
- **"Reset to defaults"** — Delete the config file (confirm with user first)
|
|
330
|
+
- **"What does X do?"** — Explain the setting using the reference above
|
|
331
|
+
- **"Set timeout to 90"** — Update `timeout` to `90` in the config file
|
package/src/prompts/execution.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getCommitFormat, getCommitPrefix, renderCommitMessage } from '../utils/config.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Maximum characters for a dependency outcome summary.
|
|
3
5
|
* Outcomes larger than this will be truncated to avoid context bloat.
|
|
@@ -86,6 +88,16 @@ ${previousOutcomes.map((o) => `### Task ${o.taskId}\n${o.content}`).join('\n\n')
|
|
|
86
88
|
// Encode task number to 2-char base36
|
|
87
89
|
const paddedTaskNumber = taskNumber.toString(36).padStart(2, '0');
|
|
88
90
|
|
|
91
|
+
// Build example commit message from config template
|
|
92
|
+
const commitTemplate = getCommitFormat('task');
|
|
93
|
+
const commitPrefix = getCommitPrefix();
|
|
94
|
+
const exampleCommit = renderCommitMessage(commitTemplate, {
|
|
95
|
+
prefix: commitPrefix,
|
|
96
|
+
projectId: projectNumber,
|
|
97
|
+
taskId: paddedTaskNumber,
|
|
98
|
+
description: '<description>',
|
|
99
|
+
});
|
|
100
|
+
|
|
89
101
|
const commitInstructions = autoCommit
|
|
90
102
|
? `
|
|
91
103
|
## Git Instructions
|
|
@@ -95,7 +107,7 @@ After successfully completing the task:
|
|
|
95
107
|
- Add each code file you changed: \`git add <file1> <file2> ...\`
|
|
96
108
|
- Add the outcome file: \`git add ${outcomeFilePath}\`
|
|
97
109
|
- Add this task's plan file: \`git add ${planPath}\`
|
|
98
|
-
2. Commit with message: "
|
|
110
|
+
2. Commit with message: "${exampleCommit}"
|
|
99
111
|
- Write a concise description of what was accomplished
|
|
100
112
|
- Focus on the actual change, not the task name
|
|
101
113
|
- The commit message must be a SINGLE LINE — no body, no trailers
|
package/src/types/config.ts
CHANGED
|
@@ -1,19 +1,149 @@
|
|
|
1
|
+
/** Short alias for a Claude model family */
|
|
2
|
+
export type ClaudeModelAlias = 'sonnet' | 'haiku' | 'opus';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Accepts short aliases (`sonnet`, `haiku`, `opus`) or full model IDs
|
|
6
|
+
* matching the pattern `claude-{family}-{version}` (e.g., `claude-opus-4-5-20251101`).
|
|
7
|
+
*/
|
|
8
|
+
export type ClaudeModelName = ClaudeModelAlias | (string & { __brand?: 'FullModelId' });
|
|
9
|
+
export type EffortLevel = 'low' | 'medium' | 'high';
|
|
10
|
+
|
|
11
|
+
export type ModelScenario = 'plan' | 'execute' | 'nameGeneration' | 'failureAnalysis' | 'prGeneration' | 'config';
|
|
12
|
+
export type EffortScenario = ModelScenario;
|
|
13
|
+
export type CommitFormatType = 'task' | 'plan' | 'amend';
|
|
14
|
+
|
|
15
|
+
export interface ModelsConfig {
|
|
16
|
+
plan: ClaudeModelName;
|
|
17
|
+
execute: ClaudeModelName;
|
|
18
|
+
nameGeneration: ClaudeModelName;
|
|
19
|
+
failureAnalysis: ClaudeModelName;
|
|
20
|
+
prGeneration: ClaudeModelName;
|
|
21
|
+
config: ClaudeModelName;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface EffortConfig {
|
|
25
|
+
plan: EffortLevel;
|
|
26
|
+
execute: EffortLevel;
|
|
27
|
+
nameGeneration: EffortLevel;
|
|
28
|
+
failureAnalysis: EffortLevel;
|
|
29
|
+
prGeneration: EffortLevel;
|
|
30
|
+
config: EffortLevel;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface CommitFormatConfig {
|
|
34
|
+
task: string;
|
|
35
|
+
plan: string;
|
|
36
|
+
amend: string;
|
|
37
|
+
prefix: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Pricing category derived from model family name. */
|
|
41
|
+
export type PricingCategory = 'opus' | 'sonnet' | 'haiku';
|
|
42
|
+
|
|
43
|
+
/** Per-direction pricing for a single model category, in dollars per million tokens. */
|
|
44
|
+
export interface ModelPricing {
|
|
45
|
+
inputPerMTok: number;
|
|
46
|
+
outputPerMTok: number;
|
|
47
|
+
cacheReadPerMTok: number;
|
|
48
|
+
cacheCreatePerMTok: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Pricing config: per-category pricing in dollars per million tokens. */
|
|
52
|
+
export interface PricingConfig {
|
|
53
|
+
opus: ModelPricing;
|
|
54
|
+
sonnet: ModelPricing;
|
|
55
|
+
haiku: ModelPricing;
|
|
56
|
+
}
|
|
57
|
+
|
|
1
58
|
export interface RafConfig {
|
|
2
|
-
|
|
3
|
-
|
|
59
|
+
models: ModelsConfig;
|
|
60
|
+
effort: EffortConfig;
|
|
61
|
+
timeout: number;
|
|
62
|
+
maxRetries: number;
|
|
4
63
|
autoCommit: boolean;
|
|
64
|
+
worktree: boolean;
|
|
65
|
+
commitFormat: CommitFormatConfig;
|
|
5
66
|
claudeCommand: string;
|
|
6
|
-
|
|
67
|
+
pricing: PricingConfig;
|
|
7
68
|
}
|
|
8
69
|
|
|
9
|
-
export const
|
|
10
|
-
|
|
11
|
-
|
|
70
|
+
export const DEFAULT_CONFIG: RafConfig = {
|
|
71
|
+
models: {
|
|
72
|
+
plan: 'opus',
|
|
73
|
+
execute: 'opus',
|
|
74
|
+
nameGeneration: 'sonnet',
|
|
75
|
+
failureAnalysis: 'haiku',
|
|
76
|
+
prGeneration: 'sonnet',
|
|
77
|
+
config: 'sonnet',
|
|
78
|
+
},
|
|
79
|
+
effort: {
|
|
80
|
+
plan: 'high',
|
|
81
|
+
execute: 'medium',
|
|
82
|
+
nameGeneration: 'low',
|
|
83
|
+
failureAnalysis: 'low',
|
|
84
|
+
prGeneration: 'medium',
|
|
85
|
+
config: 'medium',
|
|
86
|
+
},
|
|
87
|
+
timeout: 60,
|
|
88
|
+
maxRetries: 3,
|
|
12
89
|
autoCommit: true,
|
|
90
|
+
worktree: false,
|
|
91
|
+
commitFormat: {
|
|
92
|
+
task: '{prefix}[{projectId}:{taskId}] {description}',
|
|
93
|
+
plan: '{prefix}[{projectId}] Plan: {projectName}',
|
|
94
|
+
amend: '{prefix}[{projectId}] Amend: {projectName}',
|
|
95
|
+
prefix: 'RAF',
|
|
96
|
+
},
|
|
13
97
|
claudeCommand: 'claude',
|
|
98
|
+
pricing: {
|
|
99
|
+
opus: {
|
|
100
|
+
inputPerMTok: 15,
|
|
101
|
+
outputPerMTok: 75,
|
|
102
|
+
cacheReadPerMTok: 1.5,
|
|
103
|
+
cacheCreatePerMTok: 18.75,
|
|
104
|
+
},
|
|
105
|
+
sonnet: {
|
|
106
|
+
inputPerMTok: 3,
|
|
107
|
+
outputPerMTok: 15,
|
|
108
|
+
cacheReadPerMTok: 0.3,
|
|
109
|
+
cacheCreatePerMTok: 3.75,
|
|
110
|
+
},
|
|
111
|
+
haiku: {
|
|
112
|
+
inputPerMTok: 1,
|
|
113
|
+
outputPerMTok: 5,
|
|
114
|
+
cacheReadPerMTok: 0.1,
|
|
115
|
+
cacheCreatePerMTok: 1.25,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/** Deep partial type for user config files — all fields optional at every level */
|
|
121
|
+
export type DeepPartial<T> = {
|
|
122
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
14
123
|
};
|
|
15
124
|
|
|
16
|
-
export type
|
|
125
|
+
export type UserConfig = DeepPartial<RafConfig>;
|
|
126
|
+
|
|
127
|
+
export const VALID_MODEL_ALIASES: readonly ClaudeModelAlias[] = ['sonnet', 'haiku', 'opus'];
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Regex for full Claude model IDs (e.g., `claude-sonnet-4-5-20250929`, `claude-opus-4-5-20251101`).
|
|
131
|
+
* Pattern: claude-{family}-{major}(-{minor})?(-{date})?
|
|
132
|
+
*/
|
|
133
|
+
export const FULL_MODEL_ID_PATTERN = /^claude-[a-z]+-\d+(-\d+)*$/;
|
|
134
|
+
|
|
135
|
+
/** @deprecated Use VALID_MODEL_ALIASES instead */
|
|
136
|
+
export const VALID_MODELS = VALID_MODEL_ALIASES;
|
|
137
|
+
export const VALID_EFFORTS: readonly EffortLevel[] = ['low', 'medium', 'high'];
|
|
138
|
+
|
|
139
|
+
// Keep backward-compat exports used by other modules
|
|
140
|
+
/** @deprecated Use DEFAULT_CONFIG instead */
|
|
141
|
+
export const DEFAULT_RAF_CONFIG = {
|
|
142
|
+
defaultTimeout: DEFAULT_CONFIG.timeout,
|
|
143
|
+
defaultMaxRetries: DEFAULT_CONFIG.maxRetries,
|
|
144
|
+
autoCommit: DEFAULT_CONFIG.autoCommit,
|
|
145
|
+
claudeCommand: DEFAULT_CONFIG.claudeCommand,
|
|
146
|
+
};
|
|
17
147
|
|
|
18
148
|
export interface PlanCommandOptions {
|
|
19
149
|
projectName?: string;
|
|
@@ -39,3 +169,22 @@ export interface MigrateCommandOptions {
|
|
|
39
169
|
dryRun?: boolean;
|
|
40
170
|
worktree?: boolean;
|
|
41
171
|
}
|
|
172
|
+
|
|
173
|
+
/** Per-model token usage breakdown from stream-json result event. */
|
|
174
|
+
export interface ModelTokenUsage {
|
|
175
|
+
inputTokens: number;
|
|
176
|
+
outputTokens: number;
|
|
177
|
+
cacheReadInputTokens: number;
|
|
178
|
+
cacheCreationInputTokens: number;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Token usage data extracted from Claude CLI stream-json result event. */
|
|
182
|
+
export interface UsageData {
|
|
183
|
+
/** Aggregate token counts across all models. */
|
|
184
|
+
inputTokens: number;
|
|
185
|
+
outputTokens: number;
|
|
186
|
+
cacheReadInputTokens: number;
|
|
187
|
+
cacheCreationInputTokens: number;
|
|
188
|
+
/** Per-model breakdown (e.g., { "claude-opus-4-6": { ... } }). */
|
|
189
|
+
modelUsage: Record<string, ModelTokenUsage>;
|
|
190
|
+
}
|