oh-my-customcode 0.67.0 → 0.68.1
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 +14 -0
- package/dist/cli/index.js +22 -5
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +10 -0
- package/templates/.claude/hooks/scripts/rtk-intercept.sh +77 -0
- package/templates/.claude/hooks/scripts/session-env-check.sh +9 -0
- package/templates/.claude/rules/MUST-agent-design.md +3 -0
- package/templates/manifest.json +1 -1
package/README.md
CHANGED
|
@@ -294,6 +294,20 @@ your-project/
|
|
|
294
294
|
|
|
295
295
|
---
|
|
296
296
|
|
|
297
|
+
## Optional External Tools
|
|
298
|
+
|
|
299
|
+
oh-my-customcode works fully without any external tools. These optional integrations provide additional capabilities when installed:
|
|
300
|
+
|
|
301
|
+
| Tool | Purpose | Install | Skill |
|
|
302
|
+
|------|---------|---------|-------|
|
|
303
|
+
| [RTK](https://github.com/rtk-ai/rtk) | 60-90% token savings on CLI output | `brew install rtk` | `/rtk-exec` |
|
|
304
|
+
| [Codex CLI](https://github.com/openai/codex) | OpenAI Codex hybrid workflows | `npm i -g @openai/codex` | `/codex-exec` |
|
|
305
|
+
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | Google Gemini hybrid workflows | `npm i -g @anthropic-ai/gemini-cli` | `/gemini-exec` |
|
|
306
|
+
|
|
307
|
+
When installed, each tool is **auto-detected** at session start and its features become available. When not installed, all commands gracefully fall back to Claude-native alternatives.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
297
311
|
## Development
|
|
298
312
|
|
|
299
313
|
```bash
|
package/dist/cli/index.js
CHANGED
|
@@ -9325,7 +9325,7 @@ var init_package = __esm(() => {
|
|
|
9325
9325
|
workspaces: [
|
|
9326
9326
|
"packages/*"
|
|
9327
9327
|
],
|
|
9328
|
-
version: "0.
|
|
9328
|
+
version: "0.68.1",
|
|
9329
9329
|
description: "Batteries-included agent harness for Claude Code",
|
|
9330
9330
|
type: "module",
|
|
9331
9331
|
bin: {
|
|
@@ -25513,6 +25513,19 @@ function compareSemver(a, b) {
|
|
|
25513
25513
|
}
|
|
25514
25514
|
return 0;
|
|
25515
25515
|
}
|
|
25516
|
+
function isVersionPlausible(currentVersion, candidateVersion) {
|
|
25517
|
+
const current = normalizeVersion(currentVersion).split(".").map((n) => parseInt(n, 10) || 0);
|
|
25518
|
+
const candidate = normalizeVersion(candidateVersion).split(".").map((n) => parseInt(n, 10) || 0);
|
|
25519
|
+
const majorDiff = (candidate[0] ?? 0) - (current[0] ?? 0);
|
|
25520
|
+
const minorDiff = (candidate[1] ?? 0) - (current[1] ?? 0);
|
|
25521
|
+
if (majorDiff >= 1) {
|
|
25522
|
+
return false;
|
|
25523
|
+
}
|
|
25524
|
+
if (majorDiff === 0 && minorDiff >= 10) {
|
|
25525
|
+
return false;
|
|
25526
|
+
}
|
|
25527
|
+
return true;
|
|
25528
|
+
}
|
|
25516
25529
|
function isInteractiveSession(stdin = process.stdin, stdout = process.stdout) {
|
|
25517
25530
|
return Boolean(stdin.isTTY && stdout.isTTY);
|
|
25518
25531
|
}
|
|
@@ -25639,12 +25652,16 @@ function checkSelfUpdate(options) {
|
|
|
25639
25652
|
let usedCache = false;
|
|
25640
25653
|
const cache = readCache(cachePath);
|
|
25641
25654
|
if (cache && isCacheFresh(cache, now, cacheTtlMs)) {
|
|
25642
|
-
|
|
25643
|
-
|
|
25655
|
+
const cachedVersion = normalizeVersion(cache.latestVersion);
|
|
25656
|
+
if (isVersionPlausible(currentVersion, cachedVersion)) {
|
|
25657
|
+
latestVersion = cachedVersion;
|
|
25658
|
+
usedCache = true;
|
|
25659
|
+
}
|
|
25644
25660
|
}
|
|
25645
25661
|
if (!latestVersion) {
|
|
25646
|
-
|
|
25647
|
-
if (
|
|
25662
|
+
const fetched = fetchLatestVersion(packageName);
|
|
25663
|
+
if (fetched && isVersionPlausible(currentVersion, fetched)) {
|
|
25664
|
+
latestVersion = fetched;
|
|
25648
25665
|
writeCache(cachePath, latestVersion, now);
|
|
25649
25666
|
}
|
|
25650
25667
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -82,6 +82,16 @@
|
|
|
82
82
|
],
|
|
83
83
|
"description": "Schema-based tool input validation — Phase 1 advisory only"
|
|
84
84
|
},
|
|
85
|
+
{
|
|
86
|
+
"matcher": "tool == \"Bash\"",
|
|
87
|
+
"hooks": [
|
|
88
|
+
{
|
|
89
|
+
"type": "command",
|
|
90
|
+
"command": "bash .claude/hooks/scripts/rtk-intercept.sh"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"description": "RTK auto-intercept — transparently rewrites CLI commands through RTK proxy when available (R015 advisory)"
|
|
94
|
+
},
|
|
85
95
|
{
|
|
86
96
|
"matcher": "tool == \"Task\" || tool == \"Agent\"",
|
|
87
97
|
"hooks": [
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# RTK Auto-Intercept Hook
|
|
3
|
+
# Trigger: PreToolUse (Bash matcher)
|
|
4
|
+
# Purpose: Transparently rewrite CLI commands through RTK proxy
|
|
5
|
+
# Protocol: stdin JSON → stdout modified JSON, exit 0 always
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
input=$(cat)
|
|
10
|
+
|
|
11
|
+
# Only intercept Bash tool calls
|
|
12
|
+
tool_name=$(echo "$input" | jq -r '.tool // empty' 2>/dev/null || echo "")
|
|
13
|
+
if [ "$tool_name" != "Bash" ]; then
|
|
14
|
+
echo "$input"
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Check RTK availability
|
|
19
|
+
RTK_AVAILABLE=false
|
|
20
|
+
STATUS_FILE="/tmp/.claude-env-status-${PPID}"
|
|
21
|
+
if [ -f "$STATUS_FILE" ] && grep -q "rtk=available" "$STATUS_FILE" 2>/dev/null; then
|
|
22
|
+
RTK_AVAILABLE=true
|
|
23
|
+
elif command -v rtk >/dev/null 2>&1; then
|
|
24
|
+
RTK_AVAILABLE=true
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
if [ "$RTK_AVAILABLE" != "true" ]; then
|
|
28
|
+
echo "$input"
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Extract command
|
|
33
|
+
cmd=$(echo "$input" | jq -r '.tool_input.command // empty' 2>/dev/null || echo "")
|
|
34
|
+
if [ -z "$cmd" ]; then
|
|
35
|
+
echo "$input"
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Skip if already using rtk
|
|
40
|
+
if echo "$cmd" | grep -qE '^rtk\b'; then
|
|
41
|
+
echo "$input"
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Skip complex commands (pipes, redirections, background, subshells, semicolons with multiple commands)
|
|
46
|
+
if echo "$cmd" | grep -qE '[|><&]|;\s*\w'; then
|
|
47
|
+
echo "$input"
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# RTK-supported command prefixes
|
|
52
|
+
RTK_CMDS="ls find tree du cat head tail wc grep rg git cargo npm pnpm bun pip pytest vitest jest rspec eslint tsc ruff docker kubectl"
|
|
53
|
+
|
|
54
|
+
# Extract first word of command (skip env var assignments like FOO=bar)
|
|
55
|
+
first_word=$(echo "$cmd" | sed 's/^[A-Z_]*=[^ ]* //' | awk '{print $1}')
|
|
56
|
+
|
|
57
|
+
# Check if command is RTK-supported
|
|
58
|
+
SUPPORTED=false
|
|
59
|
+
for rtk_cmd in $RTK_CMDS; do
|
|
60
|
+
if [ "$first_word" = "$rtk_cmd" ]; then
|
|
61
|
+
SUPPORTED=true
|
|
62
|
+
break
|
|
63
|
+
fi
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
if [ "$SUPPORTED" != "true" ]; then
|
|
67
|
+
echo "$input"
|
|
68
|
+
exit 0
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Rewrite command with rtk prefix
|
|
72
|
+
new_cmd="rtk $cmd"
|
|
73
|
+
echo "[RTK] Intercepted: $cmd → $new_cmd" >&2
|
|
74
|
+
|
|
75
|
+
# Output modified JSON
|
|
76
|
+
echo "$input" | jq --arg new_cmd "$new_cmd" '.tool_input.command = $new_cmd'
|
|
77
|
+
exit 0
|
|
@@ -60,6 +60,15 @@ if [ "$CLAUDE_VERSION" != "unknown" ]; then
|
|
|
60
60
|
fi
|
|
61
61
|
fi
|
|
62
62
|
|
|
63
|
+
# v2.1.88+ features notice
|
|
64
|
+
if [ "$CLAUDE_VERSION" != "unknown" ]; then
|
|
65
|
+
if printf '%s\n' "2.1.88" "$CLAUDE_VERSION" | sort -V | head -1 | grep -q "^2\.1\.88$"; then
|
|
66
|
+
if [ -z "${CLAUDE_CODE_NO_FLICKER:-}" ]; then
|
|
67
|
+
echo " [v2.1.88] Tip: CLAUDE_CODE_NO_FLICKER=1 for flicker-free rendering" >&2
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
|
|
63
72
|
# Git workflow reminder
|
|
64
73
|
CURRENT_BRANCH="unknown"
|
|
65
74
|
if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
@@ -85,6 +85,7 @@ All supported hook event types in Claude Code. Agents and skills can reference t
|
|
|
85
85
|
| `Elicitation` | Agent requests user input | question | command, prompt | v2.1.76+ |
|
|
86
86
|
| `ElicitationResult` | User responds to elicitation | answer | command, prompt | v2.1.76+ |
|
|
87
87
|
| `PostMessage` | After message sent | message_type | command | v2.1.76+ |
|
|
88
|
+
| `PermissionDenied` | Auto mode classifier denial | tool, tool_input, denial_reason | command, prompt | v2.1.88+ |
|
|
88
89
|
| `TeammateIdle` | Agent Teams member idle | teammate_id | command | v2.1.83+ |
|
|
89
90
|
| `TaskCreated` | Task created | task_id, description | command | v2.1.83+ |
|
|
90
91
|
| `TaskCompleted` | Task completed | task_id, result | command | v2.1.83+ |
|
|
@@ -110,6 +111,8 @@ hooks:
|
|
|
110
111
|
command: "echo hook"
|
|
111
112
|
```
|
|
112
113
|
|
|
114
|
+
> **v2.1.85+**: `if` field supports permission rule syntax for conditional hook execution. **v2.1.88** extended `if` matching to support compound commands (`ls && git push`) and commands with env-var prefixes (`FOO=bar git push`).
|
|
115
|
+
|
|
113
116
|
## Permission Mode Guidance
|
|
114
117
|
|
|
115
118
|
When spawning agents via the Agent tool, CC applies a default `mode` of `acceptEdits` if not explicitly specified. To maintain consistent permission behavior:
|
package/templates/manifest.json
CHANGED