oh-my-customcodex 0.4.13 → 0.4.17
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 +4 -3
- package/dist/cli/index.js +65 -20
- package/dist/index.js +40 -4
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +3 -0
- package/templates/.claude/hooks/scripts/context-budget-advisor.sh +40 -2
- package/templates/.claude/hooks/scripts/cost-cap-advisor.sh +8 -3
- package/templates/.claude/hooks/scripts/omcustom-auto-update.sh +5 -5
- package/templates/.claude/hooks/scripts/session-env-check.sh +8 -6
- package/templates/.claude/hooks/scripts/stuck-detector.sh +2 -2
- package/templates/.claude/ontology/skills.yaml +14 -0
- package/templates/.claude/rules/MUST-agent-design.md +1 -0
- package/templates/.claude/rules/MUST-orchestrator-coordination.md +6 -0
- package/templates/.claude/rules/SHOULD-hud-statusline.md +2 -0
- package/templates/.claude/skills/goal/SKILL.md +88 -0
- package/templates/.claude/skills/harness-synthesizer/SKILL.md +32 -0
- package/templates/.claude/skills/help/SKILL.md +2 -0
- package/templates/.claude/skills/lists/SKILL.md +3 -1
- package/templates/.claude/skills/omcodex-release-notes/SKILL.md +13 -2
- package/templates/.claude/skills/post-release-followup/SKILL.md +1 -1
- package/templates/.claude/skills/status/SKILL.md +2 -2
- package/templates/.claude/statusline.sh +24 -3
- package/templates/AGENTS.md.en +4 -1
- package/templates/AGENTS.md.ko +4 -1
- package/templates/CLAUDE.md +11 -2
- package/templates/CLAUDE.md.en +11 -1
- package/templates/CLAUDE.md.ko +11 -1
- package/templates/guides/claude-code/04-agent-skills.md +16 -0
- package/templates/guides/claude-code/06-mcp.md +6 -0
- package/templates/guides/claude-code/13-cli-flags.md +13 -1
- package/templates/guides/claude-code/15-version-compatibility.md +59 -0
- package/templates/guides/claude-code/index.yaml +5 -0
- package/templates/guides/hook-data-flow/README.md +16 -16
- package/templates/guides/professor-triage/phases.md +324 -0
- package/templates/manifest.json +2 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
**[한국어 문서 (Korean)](./README_ko.md)**
|
|
15
15
|
|
|
16
|
-
49 agents.
|
|
16
|
+
49 agents. 118 skills. 22 rules. One command.
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
npm install -g oh-my-customcodex && cd your-project && omcustomcodex init
|
|
@@ -134,7 +134,7 @@ Each agent declares its tools, model, memory scope, and limitations in YAML fron
|
|
|
134
134
|
|
|
135
135
|
---
|
|
136
136
|
|
|
137
|
-
### Skills (
|
|
137
|
+
### Skills (118)
|
|
138
138
|
|
|
139
139
|
| Category | Count | Includes |
|
|
140
140
|
|----------|-------|----------|
|
|
@@ -170,6 +170,7 @@ All commands are invoked inside the oh-my-customcodex GPT Codex + OMX session.
|
|
|
170
170
|
| `/ambiguity-gate` | Pre-routing ambiguity analysis |
|
|
171
171
|
| `/pre-generation-arch-check` | Check architecture risks before implementation |
|
|
172
172
|
| `/adversarial-review` | Attacker-mindset security code review |
|
|
173
|
+
| `/omcustomcodex:goal` | Keep a concrete objective in view through planning, execution, and verification |
|
|
173
174
|
| `/pipeline` | Execute YAML-defined pipelines |
|
|
174
175
|
| `/pipeline resume` | Resume a halted pipeline from last failure point |
|
|
175
176
|
|
|
@@ -286,7 +287,7 @@ your-project/
|
|
|
286
287
|
│ ├── contexts/ # 4 shared context files
|
|
287
288
|
│ └── ontology/ # Knowledge graph for RAG
|
|
288
289
|
├── .agents/
|
|
289
|
-
│ └── skills/ #
|
|
290
|
+
│ └── skills/ # 118 installed skill modules
|
|
290
291
|
└── guides/ # 47 reference documents
|
|
291
292
|
```
|
|
292
293
|
|
package/dist/cli/index.js
CHANGED
|
@@ -1019,7 +1019,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1019
1019
|
this._exitCallback = (err) => {
|
|
1020
1020
|
if (err.code !== "commander.executeSubCommandAsync") {
|
|
1021
1021
|
throw err;
|
|
1022
|
-
}
|
|
1022
|
+
}
|
|
1023
1023
|
};
|
|
1024
1024
|
}
|
|
1025
1025
|
return this;
|
|
@@ -3091,7 +3091,7 @@ var init_package = __esm(() => {
|
|
|
3091
3091
|
workspaces: [
|
|
3092
3092
|
"packages/*"
|
|
3093
3093
|
],
|
|
3094
|
-
version: "0.4.
|
|
3094
|
+
version: "0.4.17",
|
|
3095
3095
|
requiresCC: ">=2.1.121",
|
|
3096
3096
|
claudeCode: {
|
|
3097
3097
|
minimumVersion: "2.1.121",
|
|
@@ -10179,6 +10179,23 @@ function sortProjects(projects) {
|
|
|
10179
10179
|
return a.name.localeCompare(b.name);
|
|
10180
10180
|
});
|
|
10181
10181
|
}
|
|
10182
|
+
async function buildRegistryProjectInfo(projectPath, entry, options, home, currentVersion) {
|
|
10183
|
+
if (!matchesSearchPaths(projectPath, options.paths))
|
|
10184
|
+
return null;
|
|
10185
|
+
if (!isUnderHome(projectPath, home))
|
|
10186
|
+
return null;
|
|
10187
|
+
if (!await fileExists(projectPath))
|
|
10188
|
+
return null;
|
|
10189
|
+
return {
|
|
10190
|
+
name: basename5(projectPath),
|
|
10191
|
+
path: projectPath,
|
|
10192
|
+
version: entry.version || null,
|
|
10193
|
+
installedAt: entry.installedAt || null,
|
|
10194
|
+
updatedAt: entry.updatedAt || null,
|
|
10195
|
+
status: computeStatus(entry.version || null, currentVersion),
|
|
10196
|
+
detectionMethod: "registry"
|
|
10197
|
+
};
|
|
10198
|
+
}
|
|
10182
10199
|
async function findProjects(options = {}) {
|
|
10183
10200
|
const currentVersion = await getTemplateVersion();
|
|
10184
10201
|
const registry = await readRegistry();
|
|
@@ -10192,19 +10209,9 @@ async function findProjects(options = {}) {
|
|
|
10192
10209
|
const results = [];
|
|
10193
10210
|
const home = process.env.HOME ?? homedir3();
|
|
10194
10211
|
for (const [projectPath, entry] of Object.entries(registry.projects)) {
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
continue;
|
|
10199
|
-
results.push({
|
|
10200
|
-
name: basename5(projectPath),
|
|
10201
|
-
path: projectPath,
|
|
10202
|
-
version: entry.version || null,
|
|
10203
|
-
installedAt: entry.installedAt || null,
|
|
10204
|
-
updatedAt: entry.updatedAt || null,
|
|
10205
|
-
status: computeStatus(entry.version || null, currentVersion),
|
|
10206
|
-
detectionMethod: "registry"
|
|
10207
|
-
});
|
|
10212
|
+
const project = await buildRegistryProjectInfo(projectPath, entry, options, home, currentVersion);
|
|
10213
|
+
if (project)
|
|
10214
|
+
results.push(project);
|
|
10208
10215
|
}
|
|
10209
10216
|
return sortProjects(results);
|
|
10210
10217
|
}
|
|
@@ -19772,7 +19779,7 @@ var require_dbcs_codec = __commonJS((exports) => {
|
|
|
19772
19779
|
if (resCode !== undefined) {
|
|
19773
19780
|
dbcsCode = resCode;
|
|
19774
19781
|
nextChar = uCode;
|
|
19775
|
-
}
|
|
19782
|
+
}
|
|
19776
19783
|
}
|
|
19777
19784
|
seqObj = undefined;
|
|
19778
19785
|
} else if (uCode >= 0) {
|
|
@@ -19837,7 +19844,7 @@ var require_dbcs_codec = __commonJS((exports) => {
|
|
|
19837
19844
|
newBuf[j2++] = dbcsCode >> 8;
|
|
19838
19845
|
newBuf[j2++] = dbcsCode & 255;
|
|
19839
19846
|
}
|
|
19840
|
-
}
|
|
19847
|
+
}
|
|
19841
19848
|
this.seqObj = undefined;
|
|
19842
19849
|
}
|
|
19843
19850
|
if (this.leadSurrogate !== -1) {
|
|
@@ -31413,6 +31420,7 @@ async function runFullUpdatePostProcessing(options, result, config) {
|
|
|
31413
31420
|
const removed = await removeDeprecatedFiles(options.targetDir, options);
|
|
31414
31421
|
result.removedDeprecatedFiles = removed;
|
|
31415
31422
|
if (!options.dryRun) {
|
|
31423
|
+
await ensureStatusLineConfig(options.targetDir);
|
|
31416
31424
|
await updateEntryDoc(options.targetDir, config, options);
|
|
31417
31425
|
}
|
|
31418
31426
|
}
|
|
@@ -31431,6 +31439,34 @@ async function runFullUpdatePostProcessing(options, result, config) {
|
|
|
31431
31439
|
});
|
|
31432
31440
|
}
|
|
31433
31441
|
}
|
|
31442
|
+
async function ensureStatusLineConfig(targetDir) {
|
|
31443
|
+
const layout = getProviderLayout();
|
|
31444
|
+
const settingsPath = join17(targetDir, layout.rootDir, "settings.local.json");
|
|
31445
|
+
const statusLineConfig = {
|
|
31446
|
+
type: "command",
|
|
31447
|
+
command: `${layout.rootDir}/statusline.sh`,
|
|
31448
|
+
padding: 0,
|
|
31449
|
+
refreshInterval: 10
|
|
31450
|
+
};
|
|
31451
|
+
if (!await fileExists(settingsPath)) {
|
|
31452
|
+
await ensureDirectory(join17(settingsPath, ".."));
|
|
31453
|
+
await writeJsonFile(settingsPath, { statusLine: statusLineConfig });
|
|
31454
|
+
return;
|
|
31455
|
+
}
|
|
31456
|
+
const settings = await readJsonFile(settingsPath);
|
|
31457
|
+
const statusLine = settings.statusLine;
|
|
31458
|
+
if (!statusLine || typeof statusLine !== "object" || Array.isArray(statusLine)) {
|
|
31459
|
+
settings.statusLine = statusLineConfig;
|
|
31460
|
+
await writeJsonFile(settingsPath, settings);
|
|
31461
|
+
return;
|
|
31462
|
+
}
|
|
31463
|
+
const mergedStatusLine = statusLine;
|
|
31464
|
+
if (mergedStatusLine.refreshInterval === undefined) {
|
|
31465
|
+
mergedStatusLine.refreshInterval = statusLineConfig.refreshInterval;
|
|
31466
|
+
settings.statusLine = mergedStatusLine;
|
|
31467
|
+
await writeJsonFile(settingsPath, settings);
|
|
31468
|
+
}
|
|
31469
|
+
}
|
|
31434
31470
|
function compareSemver2(a, b) {
|
|
31435
31471
|
const pa = a.split(".").map(Number);
|
|
31436
31472
|
const pb = b.split(".").map(Number);
|
|
@@ -31502,6 +31538,15 @@ function checkAndInstallOmxAfterUpdate() {
|
|
|
31502
31538
|
}
|
|
31503
31539
|
}
|
|
31504
31540
|
}
|
|
31541
|
+
async function handleNoUpdateResult(options, result) {
|
|
31542
|
+
const isFullUpdate = !options.components || options.components.length === 0;
|
|
31543
|
+
if (isFullUpdate && !options.dryRun) {
|
|
31544
|
+
await ensureStatusLineConfig(options.targetDir);
|
|
31545
|
+
}
|
|
31546
|
+
info("update.no_updates");
|
|
31547
|
+
result.success = true;
|
|
31548
|
+
result.skippedComponents = options.components || getAllUpdateComponents();
|
|
31549
|
+
}
|
|
31505
31550
|
async function update(options) {
|
|
31506
31551
|
const result = createUpdateResult();
|
|
31507
31552
|
try {
|
|
@@ -31520,9 +31565,7 @@ async function update(options) {
|
|
|
31520
31565
|
const updateCheck = await checkForUpdates(options.targetDir);
|
|
31521
31566
|
result.newVersion = updateCheck.latestVersion;
|
|
31522
31567
|
if (!updateCheck.hasUpdates && !options.force) {
|
|
31523
|
-
|
|
31524
|
-
result.success = true;
|
|
31525
|
-
result.skippedComponents = options.components || getAllUpdateComponents();
|
|
31568
|
+
await handleNoUpdateResult(options, result);
|
|
31526
31569
|
return result;
|
|
31527
31570
|
}
|
|
31528
31571
|
await handleBackupIfRequested(options.targetDir, !!options.backup, result);
|
|
@@ -32022,8 +32065,10 @@ function reportProjectUpdateResult(project, result, currentVersion) {
|
|
|
32022
32065
|
}
|
|
32023
32066
|
async function updateAllProjects(options) {
|
|
32024
32067
|
const { findProjects: findProjects2 } = await Promise.resolve().then(() => (init_projects(), exports_projects));
|
|
32068
|
+
const { cleanRegistry: cleanRegistry2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
32025
32069
|
const currentVersion = package_default.version;
|
|
32026
32070
|
console.log(i18n.t("cli.update.allScanning"));
|
|
32071
|
+
await cleanRegistry2();
|
|
32027
32072
|
const projects = await findProjects2();
|
|
32028
32073
|
if (projects.length === 0) {
|
|
32029
32074
|
console.log(i18n.t("cli.update.allNoneFound"));
|
package/dist/index.js
CHANGED
|
@@ -2180,7 +2180,7 @@ var package_default = {
|
|
|
2180
2180
|
workspaces: [
|
|
2181
2181
|
"packages/*"
|
|
2182
2182
|
],
|
|
2183
|
-
version: "0.4.
|
|
2183
|
+
version: "0.4.17",
|
|
2184
2184
|
requiresCC: ">=2.1.121",
|
|
2185
2185
|
claudeCode: {
|
|
2186
2186
|
minimumVersion: "2.1.121",
|
|
@@ -5015,6 +5015,7 @@ async function runFullUpdatePostProcessing(options, result, config) {
|
|
|
5015
5015
|
const removed = await removeDeprecatedFiles(options.targetDir, options);
|
|
5016
5016
|
result.removedDeprecatedFiles = removed;
|
|
5017
5017
|
if (!options.dryRun) {
|
|
5018
|
+
await ensureStatusLineConfig(options.targetDir);
|
|
5018
5019
|
await updateEntryDoc(options.targetDir, config, options);
|
|
5019
5020
|
}
|
|
5020
5021
|
}
|
|
@@ -5033,6 +5034,34 @@ async function runFullUpdatePostProcessing(options, result, config) {
|
|
|
5033
5034
|
});
|
|
5034
5035
|
}
|
|
5035
5036
|
}
|
|
5037
|
+
async function ensureStatusLineConfig(targetDir) {
|
|
5038
|
+
const layout = getProviderLayout();
|
|
5039
|
+
const settingsPath = join8(targetDir, layout.rootDir, "settings.local.json");
|
|
5040
|
+
const statusLineConfig = {
|
|
5041
|
+
type: "command",
|
|
5042
|
+
command: `${layout.rootDir}/statusline.sh`,
|
|
5043
|
+
padding: 0,
|
|
5044
|
+
refreshInterval: 10
|
|
5045
|
+
};
|
|
5046
|
+
if (!await fileExists(settingsPath)) {
|
|
5047
|
+
await ensureDirectory(join8(settingsPath, ".."));
|
|
5048
|
+
await writeJsonFile(settingsPath, { statusLine: statusLineConfig });
|
|
5049
|
+
return;
|
|
5050
|
+
}
|
|
5051
|
+
const settings = await readJsonFile(settingsPath);
|
|
5052
|
+
const statusLine = settings.statusLine;
|
|
5053
|
+
if (!statusLine || typeof statusLine !== "object" || Array.isArray(statusLine)) {
|
|
5054
|
+
settings.statusLine = statusLineConfig;
|
|
5055
|
+
await writeJsonFile(settingsPath, settings);
|
|
5056
|
+
return;
|
|
5057
|
+
}
|
|
5058
|
+
const mergedStatusLine = statusLine;
|
|
5059
|
+
if (mergedStatusLine.refreshInterval === undefined) {
|
|
5060
|
+
mergedStatusLine.refreshInterval = statusLineConfig.refreshInterval;
|
|
5061
|
+
settings.statusLine = mergedStatusLine;
|
|
5062
|
+
await writeJsonFile(settingsPath, settings);
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
5036
5065
|
function compareSemver(a, b) {
|
|
5037
5066
|
const pa = a.split(".").map(Number);
|
|
5038
5067
|
const pb = b.split(".").map(Number);
|
|
@@ -5104,6 +5133,15 @@ function checkAndInstallOmxAfterUpdate() {
|
|
|
5104
5133
|
}
|
|
5105
5134
|
}
|
|
5106
5135
|
}
|
|
5136
|
+
async function handleNoUpdateResult(options, result) {
|
|
5137
|
+
const isFullUpdate = !options.components || options.components.length === 0;
|
|
5138
|
+
if (isFullUpdate && !options.dryRun) {
|
|
5139
|
+
await ensureStatusLineConfig(options.targetDir);
|
|
5140
|
+
}
|
|
5141
|
+
info("update.no_updates");
|
|
5142
|
+
result.success = true;
|
|
5143
|
+
result.skippedComponents = options.components || getAllUpdateComponents();
|
|
5144
|
+
}
|
|
5107
5145
|
async function update(options) {
|
|
5108
5146
|
const result = createUpdateResult();
|
|
5109
5147
|
try {
|
|
@@ -5122,9 +5160,7 @@ async function update(options) {
|
|
|
5122
5160
|
const updateCheck = await checkForUpdates(options.targetDir);
|
|
5123
5161
|
result.newVersion = updateCheck.latestVersion;
|
|
5124
5162
|
if (!updateCheck.hasUpdates && !options.force) {
|
|
5125
|
-
|
|
5126
|
-
result.success = true;
|
|
5127
|
-
result.skippedComponents = options.components || getAllUpdateComponents();
|
|
5163
|
+
await handleNoUpdateResult(options, result);
|
|
5128
5164
|
return result;
|
|
5129
5165
|
}
|
|
5130
5166
|
await handleBackupIfRequested(options.targetDir, !!options.backup, result);
|
package/package.json
CHANGED
|
@@ -438,6 +438,7 @@
|
|
|
438
438
|
"command": "bash .codex/hooks/scripts/context-budget-advisor.sh"
|
|
439
439
|
}
|
|
440
440
|
],
|
|
441
|
+
"continueOnBlock": true,
|
|
441
442
|
"description": "Context budget advisor — track tool usage patterns and advise ecomode activation"
|
|
442
443
|
},
|
|
443
444
|
{
|
|
@@ -448,6 +449,7 @@
|
|
|
448
449
|
"command": "bash .codex/hooks/scripts/stuck-detector.sh"
|
|
449
450
|
}
|
|
450
451
|
],
|
|
452
|
+
"continueOnBlock": true,
|
|
451
453
|
"description": "Detect repetitive failure loops and advise recovery strategies"
|
|
452
454
|
},
|
|
453
455
|
{
|
|
@@ -458,6 +460,7 @@
|
|
|
458
460
|
"command": "bash .codex/hooks/scripts/cost-cap-advisor.sh"
|
|
459
461
|
}
|
|
460
462
|
],
|
|
463
|
+
"continueOnBlock": true,
|
|
461
464
|
"description": "Advisory cost cap monitoring — warn when session cost approaches configurable limit"
|
|
462
465
|
},
|
|
463
466
|
{
|
|
@@ -8,13 +8,14 @@ command -v jq >/dev/null 2>&1 || exit 0
|
|
|
8
8
|
# Context Budget Advisor Hook
|
|
9
9
|
# Trigger: PostToolUse (Edit/Write/Agent/Task/Read/Glob/Grep/Bash)
|
|
10
10
|
# Purpose: Monitor context usage and advise ecomode activation based on task type
|
|
11
|
-
# Protocol: stdin JSON -> stdout pass-through
|
|
11
|
+
# Protocol: stdin JSON -> stdout pass-through; exit 2 only for continueOnBlock signals
|
|
12
12
|
|
|
13
13
|
input=$(cat)
|
|
14
14
|
|
|
15
15
|
# Read context info from status file if available
|
|
16
|
-
|
|
16
|
+
COST_FILE="/tmp/.codex-cost-${PPID}"
|
|
17
17
|
BUDGET_FILE="/tmp/.codex-context-budget-${PPID}"
|
|
18
|
+
SIGNAL_FILE="/tmp/.codex-context-budget-signal-${PPID}"
|
|
18
19
|
|
|
19
20
|
# Initialize budget tracking file
|
|
20
21
|
if [ ! -f "$BUDGET_FILE" ]; then
|
|
@@ -77,6 +78,43 @@ case "$task_type" in
|
|
|
77
78
|
*) THRESHOLD=80 ;;
|
|
78
79
|
esac
|
|
79
80
|
|
|
81
|
+
# Use statusline bridge data when available. Exiting 2 with continueOnBlock=true
|
|
82
|
+
# turns a high-context advisory into model-visible feedback without halting.
|
|
83
|
+
ctx_pct="0"
|
|
84
|
+
ctx_timestamp="0"
|
|
85
|
+
if [ -f "$COST_FILE" ]; then
|
|
86
|
+
IFS=$'\t' read -r _cost_usd ctx_pct ctx_timestamp _rl_5h _rl_7d _rl_5h_resets _rl_7d_resets < "$COST_FILE" 2>/dev/null || true
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
ctx_int="${ctx_pct%%.*}"
|
|
90
|
+
case "$ctx_int" in
|
|
91
|
+
''|*[!0-9]*) ctx_int=0 ;;
|
|
92
|
+
esac
|
|
93
|
+
case "$ctx_timestamp" in
|
|
94
|
+
''|*[!0-9]*) ctx_timestamp=0 ;;
|
|
95
|
+
esac
|
|
96
|
+
|
|
97
|
+
now=$(date +%s)
|
|
98
|
+
age=$((now - ${ctx_timestamp:-0}))
|
|
99
|
+
signal_key="${task_type}:${THRESHOLD}"
|
|
100
|
+
last_signal=""
|
|
101
|
+
if [ -f "$SIGNAL_FILE" ]; then
|
|
102
|
+
last_signal=$(cat "$SIGNAL_FILE" 2>/dev/null || echo "")
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
if [ "$age" -le 60 ] && [ "$ctx_int" -ge "$THRESHOLD" ] && [ "$last_signal" != "$signal_key" ]; then
|
|
106
|
+
echo "[Context Budget] ${ctx_int}% context used meets ${task_type} threshold ${THRESHOLD}%" >&2
|
|
107
|
+
echo "[Context Budget] Switch to ecomode, compact, or narrow the remaining task before continuing." >&2
|
|
108
|
+
echo "$signal_key" > "$SIGNAL_FILE"
|
|
109
|
+
echo "$input"
|
|
110
|
+
HOOK_END=$(date +%s%N 2>/dev/null || echo 0)
|
|
111
|
+
if [ "$HOOK_START" != "0" ] && [ "$HOOK_END" != "0" ]; then
|
|
112
|
+
HOOK_MS=$(( (HOOK_END - HOOK_START) / 1000000 ))
|
|
113
|
+
echo "[Hook Perf] $(basename "$0"): ${HOOK_MS}ms" >> "/tmp/.codex-hook-perf-${PPID}.log"
|
|
114
|
+
fi
|
|
115
|
+
exit 2
|
|
116
|
+
fi
|
|
117
|
+
|
|
80
118
|
# Emit advisory at milestones (every 25 tool calls)
|
|
81
119
|
if [ "$tool_count" -gt 0 ] && [ $((tool_count % 25)) -eq 0 ]; then
|
|
82
120
|
echo "[Context Budget] Task: ${task_type} | Threshold: ${THRESHOLD}% | Tools used: ${tool_count}" >&2
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# cost-cap-advisor.sh — Advisory hook for session cost monitoring
|
|
3
3
|
# Trigger: PostToolUse (Agent/Task)
|
|
4
4
|
# Purpose: Warn when session cost approaches configurable cap
|
|
5
|
-
# Protocol: stdin JSON -> stdout pass-through
|
|
5
|
+
# Protocol: stdin JSON -> stdout pass-through; exit 2 only for continueOnBlock wrap-up signals
|
|
6
6
|
|
|
7
7
|
input=$(cat)
|
|
8
8
|
|
|
@@ -30,10 +30,13 @@ if ! printf '%f' "$cost_usd" >/dev/null 2>&1; then
|
|
|
30
30
|
echo "$input"
|
|
31
31
|
exit 0
|
|
32
32
|
fi
|
|
33
|
+
if ! printf '%f' "$COST_CAP" >/dev/null 2>&1; then
|
|
34
|
+
echo "$input"
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
33
37
|
|
|
34
38
|
# Calculate percentage of cap used
|
|
35
|
-
|
|
36
|
-
cost_pct=$(echo "scale=0; $cost_usd * 100 / $COST_CAP" | bc 2>/dev/null || echo "0")
|
|
39
|
+
cost_pct=$(awk -v cost="$cost_usd" -v cap="$COST_CAP" 'BEGIN { if (cap <= 0) print 0; else printf "%d", (cost * 100 / cap) }' 2>/dev/null || echo "0")
|
|
37
40
|
|
|
38
41
|
# Staleness check — skip if data is older than 60 seconds
|
|
39
42
|
now=$(date +%s)
|
|
@@ -54,6 +57,8 @@ if [ "$cost_pct" -ge 100 ] && [ "$last_level" != "100" ]; then
|
|
|
54
57
|
echo "[Cost Cap] Session cost \$${cost_usd} has reached cap \$${COST_CAP} (${cost_pct}%)" >&2
|
|
55
58
|
echo "[Cost Cap] Consider wrapping up or increasing CLAUDE_COST_CAP" >&2
|
|
56
59
|
echo "100" > "$ADVISORY_FILE"
|
|
60
|
+
echo "$input"
|
|
61
|
+
exit 2
|
|
57
62
|
elif [ "$cost_pct" -ge 90 ] && [ "$last_level" != "90" ] && [ "$last_level" != "100" ]; then
|
|
58
63
|
echo "[Cost Cap] Session cost \$${cost_usd} at 90% of cap \$${COST_CAP}" >&2
|
|
59
64
|
echo "[Cost Cap] Ecomode recommended — consider /compact" >&2
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# SessionStart auto-update hook — interactive
|
|
2
|
+
# SessionStart auto-update hook — interactive omcustomcodex update check
|
|
3
3
|
# Trigger: SessionStart (runs BEFORE session-env-check.sh)
|
|
4
4
|
# Purpose: Check for oh-my-customcodex updates, prompt user, optionally update
|
|
5
5
|
# Protocol: stdin JSON -> stdout pass-through, exit 0 ALWAYS
|
|
@@ -135,17 +135,17 @@ if read -r -t "$INPUT_TIMEOUT" answer </dev/tty 2>/dev/null; then
|
|
|
135
135
|
echo " ✓ Updated to v${LATEST_VERSION}" >&2
|
|
136
136
|
|
|
137
137
|
# Check if project harness should be updated too
|
|
138
|
-
if [ -f ".omcustomrc.json" ]; then
|
|
138
|
+
if [ -f ".omcodexrc.json" ] || [ -f ".omcustomrc.json" ]; then
|
|
139
139
|
printf " Update project harness too? [y/N] " >/dev/tty 2>/dev/null
|
|
140
140
|
if read -r -t "$INPUT_TIMEOUT" harness_answer </dev/tty 2>/dev/null; then
|
|
141
141
|
case "$harness_answer" in
|
|
142
142
|
[yY]|[yY][eE][sS])
|
|
143
143
|
echo " Updating project harness..." >&2
|
|
144
|
-
if command -v
|
|
145
|
-
|
|
144
|
+
if command -v omcustomcodex >/dev/null 2>&1; then
|
|
145
|
+
omcustomcodex update --force >&2 2>&1 || echo " ⚠ Harness update failed (non-blocking)" >&2
|
|
146
146
|
echo " ✓ Project harness updated" >&2
|
|
147
147
|
else
|
|
148
|
-
echo " ⚠
|
|
148
|
+
echo " ⚠ omcustomcodex command not found after install" >&2
|
|
149
149
|
fi
|
|
150
150
|
;;
|
|
151
151
|
*)
|
|
@@ -126,8 +126,10 @@ OMCUSTOM_UPDATE_STATUS="unknown"
|
|
|
126
126
|
INSTALLED_VERSION=""
|
|
127
127
|
CACHED_LATEST=""
|
|
128
128
|
|
|
129
|
-
# Read installed version from .
|
|
130
|
-
if [ -f ".
|
|
129
|
+
# Read installed version from the Codex config, falling back to the legacy parent config.
|
|
130
|
+
if [ -f ".omcodexrc.json" ]; then
|
|
131
|
+
INSTALLED_VERSION=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' .omcodexrc.json 2>/dev/null | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
132
|
+
elif [ -f ".omcustomrc.json" ]; then
|
|
131
133
|
INSTALLED_VERSION=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' .omcustomrc.json 2>/dev/null | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
132
134
|
fi
|
|
133
135
|
|
|
@@ -222,8 +224,8 @@ case "$DRIFT_STATUS" in
|
|
|
222
224
|
esac
|
|
223
225
|
echo "" >&2
|
|
224
226
|
echo " [Lockfile Drift]" >&2
|
|
225
|
-
echo " Note: file-level lockfile drift (template hash changes) is checked via '
|
|
226
|
-
echo " Run '
|
|
227
|
+
echo " Note: file-level lockfile drift (template hash changes) is checked via 'omcustomcodex doctor'" >&2
|
|
228
|
+
echo " Run 'omcustomcodex doctor' to detect modified/removed template files since install." >&2
|
|
227
229
|
echo "------------------------------------" >&2
|
|
228
230
|
|
|
229
231
|
# SessionEnd hooks timeout (v2.1.74+)
|
|
@@ -238,12 +240,12 @@ echo " [Update Check]" >&2
|
|
|
238
240
|
if [ -n "$INSTALLED_VERSION" ] && [ -n "$CACHED_LATEST" ]; then
|
|
239
241
|
if [ "$OMCUSTOM_UPDATE_STATUS" = "available" ]; then
|
|
240
242
|
echo " ⚡ oh-my-customcodex v${CACHED_LATEST} available (current: v${INSTALLED_VERSION})" >&2
|
|
241
|
-
echo " Run '
|
|
243
|
+
echo " Run 'omcustomcodex update' to apply" >&2
|
|
242
244
|
else
|
|
243
245
|
echo " ✓ oh-my-customcodex is up to date (v${INSTALLED_VERSION})" >&2
|
|
244
246
|
fi
|
|
245
247
|
elif [ -n "$INSTALLED_VERSION" ]; then
|
|
246
|
-
echo " ℹ oh-my-customcodex v${INSTALLED_VERSION} (run '
|
|
248
|
+
echo " ℹ oh-my-customcodex v${INSTALLED_VERSION} (run 'omcustomcodex doctor --updates' to check for updates)" >&2
|
|
247
249
|
else
|
|
248
250
|
echo " ℹ oh-my-customcodex not detected in this project" >&2
|
|
249
251
|
fi
|
|
@@ -10,7 +10,7 @@ command -v jq >/dev/null 2>&1 || exit 0
|
|
|
10
10
|
# Purpose: Detect repetitive failure loops and advise recovery
|
|
11
11
|
# Protocol: stdin JSON -> process -> stdout pass-through
|
|
12
12
|
# - exit 0: advisory (normal cases, < HARD_BLOCK_THRESHOLD repetitions)
|
|
13
|
-
# - exit
|
|
13
|
+
# - exit 2: conversation block (extreme stuck loops, >= HARD_BLOCK_THRESHOLD repetitions)
|
|
14
14
|
|
|
15
15
|
# Hard block threshold: consecutive identical operations before blocking
|
|
16
16
|
HARD_BLOCK_THRESHOLD=${CLAUDE_STUCK_THRESHOLD:-3}
|
|
@@ -186,7 +186,7 @@ if [ "$hard_block" = true ]; then
|
|
|
186
186
|
HOOK_MS=$(( (HOOK_END - HOOK_START) / 1000000 ))
|
|
187
187
|
echo "[Hook Perf] $(basename "$0"): ${HOOK_MS}ms" >> "/tmp/.codex-hook-perf-${PPID}.log"
|
|
188
188
|
fi
|
|
189
|
-
exit
|
|
189
|
+
exit 2
|
|
190
190
|
fi
|
|
191
191
|
|
|
192
192
|
# Pass through
|
|
@@ -45,6 +45,10 @@ classes:
|
|
|
45
45
|
skills: [status, help, lists]
|
|
46
46
|
description: "System information and utilities"
|
|
47
47
|
|
|
48
|
+
GoalWorkflowSkill:
|
|
49
|
+
skills: ["omcustomcodex:goal"]
|
|
50
|
+
description: "Goal-to-execution workflow coordination"
|
|
51
|
+
|
|
48
52
|
VerificationSkill:
|
|
49
53
|
skills: [sauron-watch]
|
|
50
54
|
description: "Verification and compliance"
|
|
@@ -174,6 +178,16 @@ skills:
|
|
|
174
178
|
keywords: [review, code-review, best-practices, quality]
|
|
175
179
|
rule_references: []
|
|
176
180
|
|
|
181
|
+
"omcustomcodex:goal":
|
|
182
|
+
class: GoalWorkflowSkill
|
|
183
|
+
description: "Goal-to-execution workflow for disciplined Codex + OMX task completion"
|
|
184
|
+
user_invocable: true
|
|
185
|
+
model_invocable: true
|
|
186
|
+
scope: core
|
|
187
|
+
summary: "Keep a concrete objective visible through clarification, planning, execution, verification, and completion reporting"
|
|
188
|
+
keywords: [goal, omcustomcodex-goal, objective, planning, execution, verification, completion]
|
|
189
|
+
rule_references: [R020]
|
|
190
|
+
|
|
177
191
|
docker-best-practices:
|
|
178
192
|
class: BestPracticeSkill
|
|
179
193
|
description: "Docker patterns for optimized containerization"
|
|
@@ -72,6 +72,7 @@ disableSkillShellExecution: true # Disable inline shell execution in skills (v2
|
|
|
72
72
|
<!-- DETAIL: CC Version Compatibility History
|
|
73
73
|
`isolation`, `background`, `maxTurns`, `maxTokens`, `mcpServers`, `hooks`, `permissionMode`, `disallowedTools`, `limitations` are supported in Claude Code v2.1.63+. Hook types `PostCompact`, `Elicitation`, `ElicitationResult` require v2.1.76+. `CwdChanged`, `FileChanged` hook events and `managed-settings.d/` drop-in directory require v2.1.83+. Conditional `if` field for hooks requires v2.1.85+. `PermissionDenied` hook event requires v2.1.88+. `refreshInterval` setting for status line auto-refresh interval added in v2.1.97+. Monitor tool and subprocess sandboxing (`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`, `CLAUDE_CODE_SCRIPT_CAPS`) added in v2.1.98+. Settings resilience (unrecognized hook event names no longer cause settings.json to be ignored) improved in v2.1.101+. PreCompact hook block support (exit 2 / `{"decision":"block"}`) added in v2.1.105+. Skill description listing cap raised from 250 to 1,536 characters in v2.1.105+. Plugin `monitors` manifest key for background monitors added in v2.1.105+. `ENABLE_PROMPT_CACHING_1H` and `FORCE_PROMPT_CACHING_5M` env vars for prompt cache TTL control added in v2.1.108+. Skill tool can now discover and invoke built-in slash commands (`/init`, `/review`, `/security-review`) in v2.1.108+. `/recap` session context feature and `/undo` alias for `/rewind` added in v2.1.108+. `/tui` command and `tui` setting for fullscreen rendering added in v2.1.110+. PushNotification tool for mobile push notifications (Remote Control + config required) added in v2.1.110+. `autoScrollEnabled` config for fullscreen mode added in v2.1.110+. SDK/headless `TRACEPARENT`/`TRACESTATE` distributed trace linking added in v2.1.110+. Bash tool maximum timeout enforcement added in v2.1.110+. Write tool IDE diff feedback (informs model when user edits proposed content) added in v2.1.110+. `--resume`/`--continue` now resurrects unexpired scheduled tasks in v2.1.110+. `/focus` command (separated from Ctrl+O) added in v2.1.110+. `xhigh` effort level for Opus 4.7 (between `high` and `max`; other models fall back to `high`) added in v2.1.111+. `/effort` interactive slider with arrow-key navigation (when called without arguments) added in v2.1.111+. Auto mode no longer requires `--enable-auto-mode` in v2.1.111+. PowerShell tool progressive rollout (`CLAUDE_CODE_USE_POWERSHELL_TOOL` env var) added in v2.1.111+. Read-only bash commands with glob patterns (`ls *.ts`) and `cd <project-dir> &&` prefix no longer trigger permission prompt in v2.1.111+. `/less-permission-prompts` built-in skill for permission allowlist scanning added in v2.1.111+. `/ultrareview` parallel multi-agent cloud code review added in v2.1.111+. `/skills` menu sorting by estimated token count (press `t`) added in v2.1.111+. `OTEL_LOG_RAW_API_BODIES` env var for full API request/response body logging added in v2.1.111+. Plan files named after prompt content (not random words) in v2.1.111+. Plugin error handling improvements (dependency conflict errors, stale version recovery, install recovery) in v2.1.111+.
|
|
74
74
|
`sandbox.network.deniedDomains` setting for domain blocking within `allowedDomains` wildcards added in v2.1.113+. Subagent mid-stream stall detection with auto-fail after 10 minutes added in v2.1.113+. Bash `find -exec`/`-delete` no longer auto-approved under `Bash(find:*)` allow rules in v2.1.113+. Bash deny rules now match exec wrappers (`env`/`sudo`/`watch`/`ionice`/`setsid`) in v2.1.113+. Native binary spawning (per-platform optional dependency) replaces bundled JavaScript in v2.1.113+. `/loop` Esc now cancels pending wakeups in v2.1.113+.
|
|
75
|
+
Agent frontmatter `hooks:` fire when the agent runs as a main-thread agent via `--agent` flag in v2.1.116+. Hook JSON output `terminalSequence` field for desktop notifications, window title changes, and terminal bells without controlling terminal added in v2.1.141+. `claude agents --cwd <path>` for directory-scoped session lists added in v2.1.141+. Background agents launched via `/bg` preserve current permission mode in v2.1.141+. `CLAUDE_CODE_PLUGIN_PREFER_HTTPS` and `ANTHROPIC_WORKSPACE_ID` environment variables added in v2.1.141+ for HTTPS plugin clones and workspace-scoped federation.
|
|
75
76
|
-->
|
|
76
77
|
|
|
77
78
|
## Hook Event Types
|
|
@@ -160,6 +160,12 @@ Current guidance:
|
|
|
160
160
|
- In Claude Code `bypassPermissions`, broader protected-path writes such as `.claude/**`, `.git/**`, and `.vscode/**` are acceptable on v2.1.126+.
|
|
161
161
|
- Keep the `/tmp/{skill}-{timestamp}.md` pattern only as a legacy fallback for older Claude Code versions or sessions that still surface a protected-path prompt.
|
|
162
162
|
|
|
163
|
+
## Claude Compatibility Background Mode
|
|
164
|
+
|
|
165
|
+
Claude Code v2.1.141+ preserves the current permission mode when a session is detached with `/bg` or `←←` backgrounding. Earlier versions could revert to the default mode and surprise unattended release flows with permission prompts.
|
|
166
|
+
|
|
167
|
+
For this Codex port, native Codex/OMX subagents still follow the active Codex runtime tool policy. Claude compatibility prompts should keep delegated write authority explicit when a workflow relies on unattended edits, but v2.1.141+ no longer needs an extra `/bg` permission-mode workaround.
|
|
168
|
+
|
|
163
169
|
<!-- DETAIL: Autonomous Execution Mode
|
|
164
170
|
|
|
165
171
|
## Autonomous Execution Mode
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
Format: `─── [Spawn] {subagent_type}:{model} | {description} ───` — implemented in `.codex/hooks/hooks.json` (PreToolUse → Agent/Task matcher). Display for multi-step/parallel/long-running ops only.
|
|
17
17
|
|
|
18
|
+
> **Claude Code v2.1.141+ compatibility**: Hook JSON output can include `terminalSequence` to emit desktop notifications, window title changes, or terminal bells without a controlling terminal. Treat this as an optional companion to stderr HUD events and the command statusline; do not add terminal-control hook behavior until there is a concrete Codex-compatible UX need.
|
|
19
|
+
|
|
18
20
|
<!-- DETAIL: HUD Events full spec
|
|
19
21
|
### When to Display: Multi-step tasks, parallel execution, long-running operations. Skip for single brief operations.
|
|
20
22
|
### Parallel Display:
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: omcustomcodex:goal
|
|
3
|
+
description: Goal-to-execution workflow for disciplined Codex + OMX task completion
|
|
4
|
+
scope: core
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
user-invocable: true
|
|
7
|
+
argument-hint: "<objective>"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /omcustomcodex:goal - Goal-To-Execution Workflow
|
|
11
|
+
|
|
12
|
+
Use `/omcustomcodex:goal <objective>` when the user wants Codex to keep a concrete objective in view until it is genuinely complete.
|
|
13
|
+
|
|
14
|
+
This is the Codex + OMX port of the upstream goal workflow. It is implemented as a normal skill surface and does not depend on native Codex feature flags such as `features.goals`.
|
|
15
|
+
|
|
16
|
+
Native runtimes may reserve `/goal` for their own session-level completion tracker. Keep this workflow on the `omcustomcodex:` namespace so the workflow remains callable without shadowing the native command.
|
|
17
|
+
|
|
18
|
+
## Contract
|
|
19
|
+
|
|
20
|
+
When invoked with an objective:
|
|
21
|
+
|
|
22
|
+
1. Treat the supplied text as the concrete goal.
|
|
23
|
+
2. Ask only for requirements that are materially missing, risky, or blocking.
|
|
24
|
+
3. Inspect the relevant repository context before planning implementation.
|
|
25
|
+
4. Produce a short execution plan for non-trivial work.
|
|
26
|
+
5. Execute using existing project conventions, routing skills, and specialist agents when useful.
|
|
27
|
+
6. Verify completion before claiming the goal is done.
|
|
28
|
+
7. Report changed files, verification evidence, and remaining risks.
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
### 1. Capture Goal
|
|
33
|
+
|
|
34
|
+
Restate the objective in one sentence. If the runtime exposes goal tracking, register the objective there. Otherwise keep the objective visible in the active task state.
|
|
35
|
+
|
|
36
|
+
Do not broaden the goal beyond the user's words without confirming the added scope.
|
|
37
|
+
|
|
38
|
+
### 2. Clarify Only Blockers
|
|
39
|
+
|
|
40
|
+
Ask at most three short questions, and only when the answer changes the implementation path or risk profile. If reasonable defaults exist, state the assumption and continue.
|
|
41
|
+
|
|
42
|
+
### 3. Inspect Context
|
|
43
|
+
|
|
44
|
+
Search and read the smallest useful set of files before editing. Prefer `rg`/`rg --files` for repository discovery. Identify:
|
|
45
|
+
|
|
46
|
+
- Existing implementation patterns.
|
|
47
|
+
- Tests or validators that cover the affected surface.
|
|
48
|
+
- Provider-boundary constraints for this repository.
|
|
49
|
+
- User or worktree changes that must be preserved.
|
|
50
|
+
|
|
51
|
+
### 4. Plan
|
|
52
|
+
|
|
53
|
+
For non-trivial work, produce a concise plan with:
|
|
54
|
+
|
|
55
|
+
- Files or modules likely to change.
|
|
56
|
+
- Verification commands.
|
|
57
|
+
- Risks or assumptions.
|
|
58
|
+
|
|
59
|
+
Skip the visible plan for tiny, obvious changes, but still do the context check.
|
|
60
|
+
|
|
61
|
+
### 5. Execute
|
|
62
|
+
|
|
63
|
+
Use the repository's established tools and style. Keep edits scoped to the goal. Delegate through routing skills or agents when the task crosses ownership boundaries, needs specialized review, or benefits from parallel independent work.
|
|
64
|
+
|
|
65
|
+
In oh-my-customcodex, use `omcustomcodex` in command examples and operator guidance. Do not introduce `omcustom` instructions.
|
|
66
|
+
|
|
67
|
+
### 6. Verify
|
|
68
|
+
|
|
69
|
+
Run the narrowest meaningful verification first, then broaden when the change touches shared behavior, generated catalogs, release flow, or user-facing docs. If verification cannot run, report why.
|
|
70
|
+
|
|
71
|
+
### 7. Complete
|
|
72
|
+
|
|
73
|
+
Finish with:
|
|
74
|
+
|
|
75
|
+
- What changed.
|
|
76
|
+
- Verification evidence.
|
|
77
|
+
- Remaining risks or follow-up work.
|
|
78
|
+
|
|
79
|
+
Do not mark the goal complete until the acceptance criteria are satisfied or the user explicitly accepts a partial result.
|
|
80
|
+
|
|
81
|
+
## Acceptance Checklist
|
|
82
|
+
|
|
83
|
+
- Objective stayed fixed unless the user changed it.
|
|
84
|
+
- Blocking ambiguity was resolved or called out.
|
|
85
|
+
- Relevant context was inspected before edits.
|
|
86
|
+
- Implementation followed local patterns.
|
|
87
|
+
- Verification evidence is current.
|
|
88
|
+
- Final response includes changed files and residual risk.
|