saving-token 1.0.0 → 1.2.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/README.md +15 -1
- package/bin/saving-token.cjs +8 -3
- package/package.json +1 -1
- package/skills/saving-token/SKILL.md +10 -3
- package/skills/saving-token/assets/claude/saving-token-writer.md.template +2 -1
- package/skills/saving-token/assets/codex/saving-token-writer.toml.template +2 -1
- package/skills/saving-token/assets/cursor/saving-token-writer.md.template +2 -1
- package/skills/saving-token/scripts/setup.sh +118 -7
package/README.md
CHANGED
|
@@ -6,6 +6,9 @@ unchanged.
|
|
|
6
6
|
|
|
7
7
|
Inspired by [karpathy-guidelines](https://github.com/multica-ai/andrej-karpathy-skills).
|
|
8
8
|
|
|
9
|
+
The writer is used only when the host model is stronger; otherwise the host
|
|
10
|
+
works directly.
|
|
11
|
+
|
|
9
12
|
## Install
|
|
10
13
|
|
|
11
14
|
### Interactive setup
|
|
@@ -42,10 +45,21 @@ After publication, run:
|
|
|
42
45
|
npx saving-token@latest install --agent codex
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
The wrapper supports `install --agent codex` and
|
|
48
|
+
The wrapper supports `install --agent codex` and `update-models --agent codex`.
|
|
46
49
|
Use the Bash script directly for `--target`, `--model`, `--reasoning-effort`,
|
|
47
50
|
or `--yes`.
|
|
48
51
|
|
|
52
|
+
To choose a new writer model in an existing Codex installation, run:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx saving-token@latest update-models --agent codex
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Use **Up/Down** and **Enter** to choose the model. It updates the model list
|
|
59
|
+
and only the writer's model field; it preserves the reasoning effort and shows
|
|
60
|
+
no platform, effort, or confirmation menus. Use the Bash script with
|
|
61
|
+
`--update-models --target claude` or `cursor` for those platforms.
|
|
62
|
+
|
|
49
63
|
### Installed paths
|
|
50
64
|
|
|
51
65
|
| Platform | Skill | Writer configuration |
|
package/bin/saving-token.cjs
CHANGED
|
@@ -8,11 +8,11 @@ const args = process.argv.slice(2);
|
|
|
8
8
|
|
|
9
9
|
if (
|
|
10
10
|
args.length !== 3 ||
|
|
11
|
-
args[0]
|
|
11
|
+
!['install', 'update-models'].includes(args[0]) ||
|
|
12
12
|
args[1] !== '--agent' ||
|
|
13
13
|
args[2] !== 'codex'
|
|
14
14
|
) {
|
|
15
|
-
console.error('Usage: saving-token install --agent codex');
|
|
15
|
+
console.error('Usage: saving-token <install|update-models> --agent codex');
|
|
16
16
|
process.exit(1);
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -24,7 +24,12 @@ const setupPath = path.join(
|
|
|
24
24
|
'scripts',
|
|
25
25
|
'setup.sh'
|
|
26
26
|
);
|
|
27
|
-
const
|
|
27
|
+
const setupArgs = [setupPath, '--target', 'codex'];
|
|
28
|
+
if (args[0] === 'update-models') {
|
|
29
|
+
setupArgs.push('--update-models');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const result = spawnSync('bash', setupArgs, {
|
|
28
33
|
stdio: 'inherit'
|
|
29
34
|
});
|
|
30
35
|
|
package/package.json
CHANGED
|
@@ -18,18 +18,25 @@ If your identity is `saving-token-writer` or `saving-token:saving-token-writer`,
|
|
|
18
18
|
- If a writable native writer or independent model configuration is unavailable, report instruction-only compatibility and ask before implementing directly.
|
|
19
19
|
- Configuration is not runtime proof. Check exposed model metadata and disclose mismatches; never silently substitute a model yourself. Claude Code and Cursor may apply host-level fallback.
|
|
20
20
|
|
|
21
|
+
## Model gate
|
|
22
|
+
|
|
23
|
+
- Delegate only when the current host model is stronger than the configured writer model.
|
|
24
|
+
- If the comparison is unknown, do not delegate; the parent completes the task directly under normal authorization.
|
|
25
|
+
|
|
21
26
|
## Delegate
|
|
22
27
|
|
|
23
28
|
- Delegate every file write, including edits, deletions, documents, temporary scripts, and formatting.
|
|
24
29
|
- Give goals and acceptance criteria, not implementation text to paste. Prefer file paths and issue locations over copied source or conversation history.
|
|
25
30
|
- Batch related changes into one scoped task and reuse the writer for revisions.
|
|
26
31
|
- The writer follows project rules and authorization boundaries, preserves user edits, implements directly, and runs relevant checks.
|
|
32
|
+
- Put exact focused commands in `Verify`; the writer runs them with the change.
|
|
33
|
+
- For slow E2E or independent confirmation, use a verification-only native subagent. It must not modify files and returns commands, exit codes, result counts when available, and code failures or environmental blockers.
|
|
27
34
|
|
|
28
35
|
```text
|
|
29
36
|
Goal: <expected behavior>
|
|
30
|
-
Scope: <paths; prohibited changes>
|
|
31
|
-
Verify: <
|
|
32
|
-
Return: changed paths;
|
|
37
|
+
Scope: <paths; prohibited changes; or verification-only, no file changes>
|
|
38
|
+
Verify: <exact commands>
|
|
39
|
+
Return: changed paths; commands, exit codes, result counts when available; code failures or environmental blockers.
|
|
33
40
|
```
|
|
34
41
|
|
|
35
42
|
## Accept
|
|
@@ -12,4 +12,5 @@ disallowedTools:
|
|
|
12
12
|
Implement directly. Never delegate or invoke another subagent.
|
|
13
13
|
Follow project rules and authorization boundaries, and preserve existing user edits.
|
|
14
14
|
Make only the requested changes and run the requested checks.
|
|
15
|
-
|
|
15
|
+
For verification-only work, do not modify files.
|
|
16
|
+
Return changed paths; commands, exit codes, result counts when available; and code failures or environmental blockers only.
|
|
@@ -7,5 +7,6 @@ developer_instructions = """
|
|
|
7
7
|
Implement directly. Do not delegate further.
|
|
8
8
|
Follow project rules and preserve existing user edits.
|
|
9
9
|
Run the requested checks.
|
|
10
|
-
|
|
10
|
+
For verification-only work, do not modify files.
|
|
11
|
+
Return changed paths; commands, exit codes, result counts when available; and code failures or environmental blockers only.
|
|
11
12
|
"""
|
|
@@ -11,4 +11,5 @@ is_background: false
|
|
|
11
11
|
Implement directly. Never delegate or invoke another subagent.
|
|
12
12
|
Follow project rules and authorization boundaries, and preserve existing user edits.
|
|
13
13
|
Make only the requested changes and run the requested checks.
|
|
14
|
-
|
|
14
|
+
For verification-only work, do not modify files.
|
|
15
|
+
Return changed paths; commands, exit codes, result counts when available; and code failures or environmental blockers only.
|
|
@@ -90,6 +90,7 @@ usage() {
|
|
|
90
90
|
cat <<'HELP'
|
|
91
91
|
Usage: setup.sh [--target codex|claude|cursor] [--model ID]
|
|
92
92
|
[--reasoning-effort EFFORT] [--yes]
|
|
93
|
+
setup.sh --update-models --target codex|claude|cursor
|
|
93
94
|
|
|
94
95
|
Use Up/Down and Enter to choose a platform, model, effort, and confirmation.
|
|
95
96
|
Esc cancels before any files are changed.
|
|
@@ -97,6 +98,7 @@ Esc cancels before any files are changed.
|
|
|
97
98
|
--model ID Skip the model menu; required without a terminal.
|
|
98
99
|
--reasoning-effort EFFORT Optional. Omit to use the host's default behavior.
|
|
99
100
|
--yes Approve installation and displayed replacements.
|
|
101
|
+
--update-models Choose and update the writer model in an installed Skill.
|
|
100
102
|
-h, --help Show this help.
|
|
101
103
|
|
|
102
104
|
Model suggestions are not an account availability check. Use only models and
|
|
@@ -112,6 +114,7 @@ reasoning_effort=''
|
|
|
112
114
|
model_was_set=false
|
|
113
115
|
effort_was_set=false
|
|
114
116
|
assume_yes=false
|
|
117
|
+
update_models=false
|
|
115
118
|
|
|
116
119
|
while [[ $# -gt 0 ]]; do
|
|
117
120
|
case "$1" in
|
|
@@ -124,12 +127,17 @@ while [[ $# -gt 0 ]]; do
|
|
|
124
127
|
esac
|
|
125
128
|
shift 2 ;;
|
|
126
129
|
--yes) assume_yes=true; shift ;;
|
|
130
|
+
--update-models) update_models=true; shift ;;
|
|
127
131
|
-h|--help) usage; exit 0 ;;
|
|
128
132
|
*) fail "Unknown option: $1" ;;
|
|
129
133
|
esac
|
|
130
134
|
done
|
|
131
135
|
|
|
132
136
|
[[ -n "${HOME:-}" ]] || fail 'HOME is not set.'
|
|
137
|
+
if [[ "$update_models" == true ]]; then
|
|
138
|
+
[[ -n "$target" ]] || fail 'Pass --target with --update-models.'
|
|
139
|
+
[[ "$model_was_set" == false && "$effort_was_set" == false && "$assume_yes" == false ]] || fail '--update-models cannot be combined with --model, --reasoning-effort, or --yes.'
|
|
140
|
+
fi
|
|
133
141
|
if [[ -z "$target" ]]; then
|
|
134
142
|
[[ -t 0 ]] || fail 'Pass --target in non-interactive use.'
|
|
135
143
|
if choose_menu 'Choose a platform:' 'Codex|codex' 'Claude Code|claude' 'Cursor|cursor'; then
|
|
@@ -145,30 +153,134 @@ case "$target" in
|
|
|
145
153
|
skill_target="$codex_home/skills/saving-token"
|
|
146
154
|
agent_dir="$codex_home/agents"
|
|
147
155
|
agent_file='saving-token-writer.toml'
|
|
148
|
-
models=(gpt-
|
|
156
|
+
models=(gpt-6-luna gpt-6-sol gpt-6-astra)
|
|
149
157
|
;;
|
|
150
158
|
claude)
|
|
151
159
|
skill_target="$HOME/.claude/skills/saving-token"
|
|
152
160
|
agent_dir="$HOME/.claude/agents"
|
|
153
161
|
agent_file='saving-token-writer.md'
|
|
154
|
-
models=(haiku sonnet opus)
|
|
162
|
+
models=(claude-haiku-4-5-20251001 claude-sonnet-5 claude-opus-5-5 claude-fable-5-1)
|
|
155
163
|
;;
|
|
156
164
|
cursor)
|
|
157
165
|
skill_target="$HOME/.cursor/skills/saving-token"
|
|
158
166
|
agent_dir="$HOME/.cursor/agents"
|
|
159
167
|
agent_file='saving-token-writer.md'
|
|
160
|
-
models=(composer-2.5 gpt-5.6-sol)
|
|
168
|
+
models=(composer-2.5 gpt-5.6-luna gpt-5.6-terra gpt-5.6-sol claude-sonnet-5 claude-opus-5-5 claude-fable-5-1)
|
|
161
169
|
;;
|
|
162
170
|
*) fail "Unsupported target '$target'. Expected codex, claude, or cursor." ;;
|
|
163
171
|
esac
|
|
164
172
|
|
|
165
|
-
|
|
166
|
-
|
|
173
|
+
agent_target="$agent_dir/$agent_file"
|
|
174
|
+
|
|
175
|
+
choose_writer_model() {
|
|
176
|
+
local prompt=$1
|
|
177
|
+
local -a model_options
|
|
178
|
+
local model
|
|
179
|
+
|
|
167
180
|
model_options=()
|
|
168
181
|
for model in "${models[@]}"; do model_options[${#model_options[@]}]="$model|$model"; done
|
|
169
|
-
if choose_menu
|
|
182
|
+
if choose_menu "$prompt" "${model_options[@]}"; then
|
|
170
183
|
writer_model=$MENU_RESULT
|
|
184
|
+
return 0
|
|
185
|
+
fi
|
|
186
|
+
return 1
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
update_installed_model_suggestions() {
|
|
190
|
+
local installed_setup temporary_setup model_line
|
|
191
|
+
|
|
192
|
+
installed_setup="$skill_target/scripts/setup.sh"
|
|
193
|
+
[[ -f "$installed_setup" ]] || fail "No installed Skill script found at $installed_setup. Run install first."
|
|
194
|
+
|
|
195
|
+
model_line=" models=(${models[*]})"
|
|
196
|
+
|
|
197
|
+
temporary_setup="$(mktemp "$(dirname -- "$installed_setup")/.saving-token-setup.XXXXXX")"
|
|
198
|
+
cp -p "$installed_setup" "$temporary_setup"
|
|
199
|
+
if ! awk -v target="$target" -v model_line="$model_line" '
|
|
200
|
+
$0 == " " target ")" { in_target = 1; print; next }
|
|
201
|
+
in_target && $0 == " ;;" { in_target = 0; print; next }
|
|
202
|
+
in_target && $0 ~ /^ models=\([^)]*\)$/ {
|
|
203
|
+
replacements++
|
|
204
|
+
print model_line
|
|
205
|
+
next
|
|
206
|
+
}
|
|
207
|
+
{ print }
|
|
208
|
+
END { exit replacements == 1 ? 0 : 1 }
|
|
209
|
+
' "$installed_setup" > "$temporary_setup"; then
|
|
210
|
+
rm -f "$temporary_setup"
|
|
211
|
+
fail "Could not find one model list for $target in $installed_setup. Run install to refresh the Skill."
|
|
212
|
+
fi
|
|
213
|
+
if ! bash -n "$temporary_setup"; then
|
|
214
|
+
rm -f "$temporary_setup"
|
|
215
|
+
fail 'Updated Skill script failed syntax validation.'
|
|
216
|
+
fi
|
|
217
|
+
if cmp -s "$installed_setup" "$temporary_setup"; then
|
|
218
|
+
rm -f "$temporary_setup"
|
|
219
|
+
printf 'Model suggestions for %s are already current.\n' "$target"
|
|
220
|
+
return
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
mv -f "$temporary_setup" "$installed_setup"
|
|
224
|
+
printf 'Updated model suggestions for %s in %s.\n' "$target" "$installed_setup"
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
update_writer_model() {
|
|
228
|
+
local temporary_agent model_line cursor_effort line
|
|
229
|
+
|
|
230
|
+
[[ -f "$agent_target" ]] || fail "No writer configuration found at $agent_target. Run install first."
|
|
231
|
+
if [[ "$target" == codex ]]; then
|
|
232
|
+
model_line="model = \"$writer_model\""
|
|
171
233
|
else
|
|
234
|
+
cursor_effort=''
|
|
235
|
+
if [[ "$target" == cursor ]]; then
|
|
236
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
237
|
+
if [[ "$line" =~ ^model:\ \"[^\"]*(\[effort=[^]]+\])\"$ ]]; then
|
|
238
|
+
cursor_effort=${BASH_REMATCH[1]}
|
|
239
|
+
break
|
|
240
|
+
fi
|
|
241
|
+
done < "$agent_target"
|
|
242
|
+
fi
|
|
243
|
+
model_line="model: \"$writer_model$cursor_effort\""
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
temporary_agent="$(mktemp "$(dirname -- "$agent_target")/.${agent_file}.XXXXXX")"
|
|
247
|
+
cp -p "$agent_target" "$temporary_agent"
|
|
248
|
+
if ! awk -v target="$target" -v model_line="$model_line" '
|
|
249
|
+
(target == "codex" && $0 ~ /^model = "[^"]*"$/) ||
|
|
250
|
+
(target != "codex" && $0 ~ /^model: "[^"]*"$/) {
|
|
251
|
+
replacements++
|
|
252
|
+
print model_line
|
|
253
|
+
next
|
|
254
|
+
}
|
|
255
|
+
{ print }
|
|
256
|
+
END { exit replacements == 1 ? 0 : 1 }
|
|
257
|
+
' "$agent_target" > "$temporary_agent"; then
|
|
258
|
+
rm -f "$temporary_agent"
|
|
259
|
+
fail "Could not find one model field in $agent_target. Run install to refresh the writer configuration."
|
|
260
|
+
fi
|
|
261
|
+
if cmp -s "$agent_target" "$temporary_agent"; then
|
|
262
|
+
rm -f "$temporary_agent"
|
|
263
|
+
printf 'Writer model for %s is already %s.\n' "$target" "$writer_model"
|
|
264
|
+
return
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
mv -f "$temporary_agent" "$agent_target"
|
|
268
|
+
printf 'Updated writer model for %s to %s.\n' "$target" "$writer_model"
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if [[ "$update_models" == true ]]; then
|
|
272
|
+
[[ -t 0 ]] || fail '--update-models requires a terminal to choose a writer model.'
|
|
273
|
+
if ! choose_writer_model 'Choose a writer model to update:'; then
|
|
274
|
+
cancel_install
|
|
275
|
+
fi
|
|
276
|
+
update_installed_model_suggestions
|
|
277
|
+
update_writer_model
|
|
278
|
+
exit 0
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
if [[ "$model_was_set" != true ]]; then
|
|
282
|
+
[[ -t 0 ]] || fail 'Pass --model in non-interactive use.'
|
|
283
|
+
if ! choose_writer_model 'Choose a writer model:'; then
|
|
172
284
|
cancel_install
|
|
173
285
|
fi
|
|
174
286
|
fi
|
|
@@ -210,7 +322,6 @@ if [[ "$target" == claude ]]; then
|
|
|
210
322
|
fi
|
|
211
323
|
|
|
212
324
|
template_path="$SKILL_SOURCE/assets/$target/$agent_file.template"
|
|
213
|
-
agent_target="$agent_dir/$agent_file"
|
|
214
325
|
distributed_files=(SKILL.md scripts/setup.sh assets/codex/saving-token-writer.toml.template assets/claude/saving-token-writer.md.template assets/cursor/saving-token-writer.md.template)
|
|
215
326
|
for file in "${distributed_files[@]}"; do
|
|
216
327
|
[[ -f "$SKILL_SOURCE/$file" ]] || fail "Missing required Skill file: $SKILL_SOURCE/$file"
|