oh-my-customcode 1.1.106 → 2.0.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.
@@ -1,73 +1,128 @@
1
1
  #!/bin/bash
2
2
  # cost-cap-advisor.sh — Advisory hook for session cost monitoring
3
- # Trigger: PostToolUse (Agent/Task)
4
- # Purpose: Warn when session cost approaches configurable cap
5
- # Protocol: stdin JSON -> stdout pass-through, exit 0 always (advisory only, R010)
3
+ # Trigger: PostToolUse (Edit/Write/Bash/Task/Agent), with continueOnBlock enabled
4
+ # Purpose: Warn once per threshold for the current numeric cost cap
5
+ # Protocol: stdin JSON -> stdout pass-through; first 100% warning exits 2, otherwise 0
6
6
 
7
- input=$(cat)
7
+ input=$(command cat)
8
8
 
9
- # Cost bridge file written by statusline.sh
9
+ # Cost bridge file written by statusline.sh; both files belong to the caller's PPID.
10
10
  COST_FILE="/tmp/.claude-cost-${PPID}"
11
11
  ADVISORY_FILE="/tmp/.claude-cost-advisory-${PPID}"
12
-
13
- # Configurable cap (default $5.00, override via CLAUDE_COST_CAP env var)
14
12
  COST_CAP="${CLAUDE_COST_CAP:-5.00}"
15
13
 
16
- # Check if cost data is available
17
- if [ ! -f "$COST_FILE" ]; then
14
+ pass_through() {
18
15
  printf '%s\n' "$input"
19
16
  exit 0
20
- fi
17
+ }
21
18
 
22
- # TSV: cost_usd, ctx_pct, timestamp, rl_5h_pct, rl_7d_pct, rl_5h_resets, rl_7d_resets
23
- IFS=$'\t' read -r cost_usd ctx_pct timestamp _rl_5h _rl_7d _rl_5h_resets _rl_7d_resets < "$COST_FILE" 2>/dev/null || {
24
- printf '%s\n' "$input"
25
- exit 0
19
+ # Decimal grammar excludes signs, exponents, whitespace and calculator expressions.
20
+ # Normalize strings without floating-point rounding: 005.00 and 5 share identity 5.
21
+ normalize_decimal() {
22
+ printf '%s\n' "$1" | LC_ALL=C awk 'END {
23
+ if (NR != 1) exit 1
24
+ value = $0
25
+ if (value !~ /^([0-9]+([.][0-9]*)?|[.][0-9]+)$/) exit 1
26
+ split(value, parts, "[.]")
27
+ whole = parts[1]
28
+ sub(/^0+/, "", whole)
29
+ if (whole == "") whole = "0"
30
+ fraction = parts[2]
31
+ sub(/0+$/, "", fraction)
32
+ if (fraction == "") printf "%s\n", whole
33
+ else printf "%s.%s\n", whole, fraction
34
+ }' 2>/dev/null
26
35
  }
27
36
 
28
- # Validate cost_usd is a number
29
- if ! printf '%f' "$cost_usd" >/dev/null 2>&1; then
30
- printf '%s\n' "$input"
31
- exit 0
32
- fi
37
+ cap_identity=$(normalize_decimal "$COST_CAP") || pass_through
38
+ [ "$cap_identity" != "0" ] || pass_through
33
39
 
34
- # Calculate percentage of cap used
35
- # Use bc for float arithmetic
36
- cost_pct=$(echo "scale=0; $cost_usd * 100 / $COST_CAP" | bc 2>/dev/null || echo "0")
40
+ # Missing/unreadable/non-regular bridge data cannot mutate the advisory state.
41
+ [ -f "$COST_FILE" ] && [ -r "$COST_FILE" ] || pass_through
42
+ # TSV: cost_usd, ctx_pct, timestamp, rl_5h_pct, rl_7d_pct, rl_5h_resets, rl_7d_resets
43
+ IFS=$'\t' read -r cost_usd ctx_pct timestamp _rl_5h _rl_7d _rl_5h_resets _rl_7d_resets < "$COST_FILE" 2>/dev/null || pass_through
44
+ cost_identity=$(normalize_decimal "$cost_usd") || pass_through
37
45
 
38
- # Staleness check — skip if data is older than 60 seconds
39
- now=$(date +%s)
40
- age=$((now - ${timestamp:-0}))
41
- if [ "$age" -gt 60 ]; then
42
- printf '%s\n' "$input"
43
- exit 0
46
+ # Validate timestamps outside shell arithmetic, including oversized numeric input.
47
+ # Preserve the existing policy: skip samples older than 60 seconds.
48
+ now=$(date +%s 2>/dev/null) || pass_through
49
+ printf '%s\t%s\n' "$timestamp" "$now" | LC_ALL=C awk -F '\t' 'END {
50
+ if (NR != 1 || NF != 2) exit 1
51
+ stamp = $1
52
+ now = $2
53
+ if (stamp !~ /^[0-9]+$/ || now !~ /^[0-9]+$/) exit 1
54
+ if (sprintf("%f", stamp + 0) !~ /^[0-9]+[.][0-9]+$/) exit 1
55
+ if (now - stamp > 60) exit 1
56
+ }' 2>/dev/null || pass_through
57
+
58
+ # bc preserves decimal identity/thresholds without a floating-point cap comparison.
59
+ # Remove bc's long-number line wrapping; reject any non-integer result.
60
+ cost_pct=$(printf 'scale=0; (%s * 100) / %s\n' "$cost_identity" "$cap_identity" | bc 2>/dev/null) || pass_through
61
+ cost_pct=$(printf '%s' "$cost_pct" | tr -d '\\\n')
62
+ [[ "$cost_pct" =~ ^[0-9]+$ ]] || pass_through
63
+
64
+ level=0
65
+ # Three or more decimal digits imply >=100; avoid shell integer overflow.
66
+ if [ "${#cost_pct}" -ge 3 ]; then
67
+ level=100
68
+ elif [ "$cost_pct" -ge 90 ]; then
69
+ level=90
70
+ elif [ "$cost_pct" -ge 75 ]; then
71
+ level=75
72
+ elif [ "$cost_pct" -ge 50 ]; then
73
+ level=50
44
74
  fi
45
75
 
46
- # Read last advisory level to avoid repeating the same warning
47
- last_level=""
48
- if [ -f "$ADVISORY_FILE" ]; then
49
- last_level=$(cat "$ADVISORY_FILE" 2>/dev/null || echo "")
76
+ last_level=0
77
+ state_matches=false
78
+ # State is one TSV line: normalized cap, high-water level (0/50/75/90/100).
79
+ # A legacy level-only or corrupt state has unknown cap and starts a fresh comparison.
80
+ if [ -e "$ADVISORY_FILE" ] || [ -L "$ADVISORY_FILE" ]; then
81
+ [ -f "$ADVISORY_FILE" ] && [ -r "$ADVISORY_FILE" ] && [ ! -L "$ADVISORY_FILE" ] || pass_through
82
+ state=$(command cat "$ADVISORY_FILE" 2>/dev/null) || pass_through
83
+ IFS=$'\t' read -r state_cap state_level state_extra <<< "$state"
84
+ if [ "$state" = "$state_cap"$'\t'"$state_level" ]; then
85
+ case "$state_level" in
86
+ 0|50|75|90|100)
87
+ old_cap_identity=$(normalize_decimal "$state_cap") || old_cap_identity=""
88
+ if [ "$old_cap_identity" = "$cap_identity" ]; then
89
+ last_level="$state_level"
90
+ state_matches=true
91
+ fi
92
+ ;;
93
+ esac
94
+ fi
50
95
  fi
51
96
 
52
- # Determine advisory level and emit warning (only once per level)
53
- if [ "$cost_pct" -ge 100 ] && [ "$last_level" != "100" ]; then
54
- echo "[Cost Cap] Session cost \$${cost_usd} has reached cap \$${COST_CAP} (${cost_pct}%)" >&2
55
- echo "[Cost Cap] Consider wrapping up or increasing CLAUDE_COST_CAP" >&2
56
- echo "100" > "$ADVISORY_FILE"
57
- printf '%s\n' "$input"
58
- exit 2
59
- elif [ "$cost_pct" -ge 90 ] && [ "$last_level" != "90" ] && [ "$last_level" != "100" ]; then
60
- echo "[Cost Cap] Session cost \$${cost_usd} at 90% of cap \$${COST_CAP}" >&2
61
- echo "[Cost Cap] Ecomode recommended — consider /compact" >&2
62
- echo "90" > "$ADVISORY_FILE"
63
- elif [ "$cost_pct" -ge 75 ] && [ "$last_level" != "75" ] && [ "$last_level" != "90" ] && [ "$last_level" != "100" ]; then
64
- echo "[Cost Cap] Session cost \$${cost_usd} at 75% of cap \$${COST_CAP}" >&2
65
- echo "75" > "$ADVISORY_FILE"
66
- elif [ "$cost_pct" -ge 50 ] && [ -z "$last_level" ]; then
67
- echo "[Cost Cap] Session cost \$${cost_usd} at 50% of cap \$${COST_CAP}" >&2
68
- echo "50" > "$ADVISORY_FILE"
97
+ if [ "$state_matches" = true ] && [ "$level" -le "$last_level" ]; then
98
+ pass_through
99
+ fi
100
+
101
+ # Persist cap changes even below 50%, so returning to an earlier cap resets correctly.
102
+ # Publish a complete state before warning; failed state I/O stays benign (rc0).
103
+ advisory_tmp=$(mktemp "${ADVISORY_FILE}.tmp.XXXXXX" 2>/dev/null) || pass_through
104
+ if ! { printf '%s\t%s\n' "$cap_identity" "$level" > "$advisory_tmp" && mv -f "$advisory_tmp" "$ADVISORY_FILE"; } 2>/dev/null; then
105
+ command rm -f "$advisory_tmp" 2>/dev/null
106
+ pass_through
69
107
  fi
70
108
 
71
- # Pass through — advisory only
72
- printf '%s\n' "$input"
73
- exit 0
109
+ case "$level" in
110
+ 100)
111
+ echo "[Cost Cap] Session cost \$${cost_usd} has reached cap \$${COST_CAP} (${cost_pct}%)" >&2
112
+ echo "[Cost Cap] Consider wrapping up or increasing CLAUDE_COST_CAP" >&2
113
+ printf '%s\n' "$input"
114
+ exit 2
115
+ ;;
116
+ 90)
117
+ echo "[Cost Cap] Session cost \$${cost_usd} at 90% of cap \$${COST_CAP}" >&2
118
+ echo "[Cost Cap] Ecomode recommended — consider /compact" >&2
119
+ ;;
120
+ 75)
121
+ echo "[Cost Cap] Session cost \$${cost_usd} at 75% of cap \$${COST_CAP}" >&2
122
+ ;;
123
+ 50)
124
+ echo "[Cost Cap] Session cost \$${cost_usd} at 50% of cap \$${COST_CAP}" >&2
125
+ ;;
126
+ esac
127
+
128
+ pass_through
@@ -39,12 +39,6 @@ if command -v gemini >/dev/null 2>&1; then
39
39
  fi
40
40
  fi
41
41
 
42
- # Check RTK CLI availability
43
- RTK_STATUS="unavailable"
44
- if command -v rtk >/dev/null 2>&1; then
45
- RTK_STATUS="available"
46
- fi
47
-
48
42
  # Check Agent Teams ENV-VAR INTENT — NOT activation (#1588)
49
43
  #
50
44
  # R018 Detection (.claude/rules/MUST-agent-teams.md) resolves Agent Teams as ACTIVE only when
@@ -216,7 +210,6 @@ STATUS_FILE="/tmp/.claude-env-status-${PPID}"
216
210
  cat > "$STATUS_FILE" << ENVEOF
217
211
  codex=${CODEX_STATUS}
218
212
  gemini=${GEMINI_STATUS}
219
- rtk=${RTK_STATUS}
220
213
  agent_teams=${AGENT_TEAMS_STATUS}
221
214
  git_branch=${CURRENT_BRANCH}
222
215
  claude_version=${CLAUDE_VERSION}
@@ -228,7 +221,6 @@ ENVEOF
228
221
  # Report to stderr (visible in conversation)
229
222
  echo " codex CLI: ${CODEX_STATUS}" >&2
230
223
  echo " gemini CLI: ${GEMINI_STATUS}" >&2
231
- echo " RTK CLI: ${RTK_STATUS}" >&2
232
224
  echo " Agent Teams: ${AGENT_TEAMS_STATUS}" >&2
233
225
  if [ "$AGENT_TEAMS_STATUS" = "env-set" ]; then
234
226
  echo " CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is set — this is INTENT, not activation." >&2
@@ -238,7 +238,7 @@ experimental:
238
238
  cacheTtl: "5m" # "5m" | "1h" — subagent prompt cache TTL when not otherwise set (v2.1.248+)
239
239
  ```
240
240
 
241
- > **Note**: When `disableSkillShellExecution` is enabled (v2.1.91+), skills that rely on inline shell execution (e.g., `rtk-exec`) will have their shell blocks disabled. This is a security hardening option.
241
+ > **Note**: When `disableSkillShellExecution` is enabled (v2.1.91+), skills that rely on inline shell execution will have their shell blocks disabled. This is a security hardening option.
242
242
  -->
243
243
 
244
244
  <!-- DETAIL: CC Version Compatibility History
@@ -259,7 +259,7 @@ MEMORY.md supports an optional `## User Model` section (DISTINCT from `## Behavi
259
259
  - Focus: AI agent orchestration, CLI tooling
260
260
 
261
261
  ### Override Decisions [confidence: low]
262
- - Overrode /scout SKIP verdict → INTEGRATE for RTK (#756)
262
+ - Overrode /scout SKIP verdict → INTEGRATE for RTK (#756) (과거 결정 예시입니다. RTK 프로젝트 통합은 v2.0.0에서 퇴역하며 현재 실행 추천으로 해석하지 마십시오.)
263
263
 
264
264
  ### Categories
265
265
 
@@ -81,16 +81,6 @@
81
81
  "matcher": "Write|Edit|Bash",
82
82
  "description": "Schema-based tool input validation — Phase 1 advisory only"
83
83
  },
84
- {
85
- "hooks": [
86
- {
87
- "type": "command",
88
- "command": "bash \"${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/scripts/rtk-intercept.sh\""
89
- }
90
- ],
91
- "matcher": "Bash",
92
- "description": "RTK auto-intercept — transparently rewrites CLI commands through RTK proxy when available (R013 advisory)"
93
- },
94
84
  {
95
85
  "hooks": [
96
86
  {
@@ -552,14 +552,6 @@ agents:
552
552
  base_confidence: 85
553
553
  routing_rule: "MUST use professor-triage skill for codebase-driven issue analysis and automated triage"
554
554
 
555
- rtk-exec:
556
- keywords:
557
- korean: [rtk, 토큰절감, 출력압축, 토큰최적화]
558
- english: [rtk, "token savings", "compress output", "token optimization"]
559
- file_patterns: []
560
- supported_actions: [optimize, compress, proxy]
561
- base_confidence: 85
562
-
563
555
  # ---------------------------------------------------------------------------
564
556
  # Skill Triggers — route user intent to skill invocation
565
557
  # ---------------------------------------------------------------------------
@@ -118,7 +118,7 @@ project/
118
118
  +-- CLAUDE.md # 진입점
119
119
  +-- .claude/
120
120
  | +-- agents/ # 서브에이전트 정의 (50 파일)
121
- | +-- skills/ # 스킬 (115 디렉토리)
121
+ | +-- skills/ # 스킬 (114 디렉토리)
122
122
  | +-- rules/ # 전역 규칙 (R000-R023)
123
123
  | +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
124
124
  | +-- contexts/ # 컨텍스트 파일 (ecomode)
@@ -130,7 +130,7 @@ project/
130
130
  +-- CLAUDE.md # Entry point
131
131
  +-- .claude/
132
132
  | +-- agents/ # Subagent definitions (50 files)
133
- | +-- skills/ # Skills (115 directories)
133
+ | +-- skills/ # Skills (114 directories)
134
134
  | +-- rules/ # Global rules (R000-R023)
135
135
  | +-- hooks/ # Hook scripts (security, validation, HUD)
136
136
  | +-- contexts/ # Context files (ecomode)
@@ -130,7 +130,7 @@ project/
130
130
  +-- CLAUDE.md # 진입점
131
131
  +-- .claude/
132
132
  | +-- agents/ # 서브에이전트 정의 (50 파일)
133
- | +-- skills/ # 스킬 (115 디렉토리)
133
+ | +-- skills/ # 스킬 (114 디렉토리)
134
134
  | +-- rules/ # 전역 규칙 (R000-R023)
135
135
  | +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
136
136
  | +-- contexts/ # 컨텍스트 파일 (ecomode)
@@ -48,11 +48,11 @@ templates/
48
48
  ├── manifest.json # 배포 컴포넌트 카운트 및 메타데이터
49
49
  ├── .claude/
50
50
  │ ├── agents/ # 에이전트 정의 파일 (*.md, 50개)
51
- │ ├── skills/ # 스킬 모듈 (각 디렉토리에 SKILL.md, 115개)
51
+ │ ├── skills/ # 스킬 모듈 (각 디렉토리에 SKILL.md, 114개)
52
52
  │ ├── rules/ # 전역 규칙 (R000–R023, 23개)
53
53
  │ ├── hooks/
54
54
  │ │ ├── hooks.json # 훅 이벤트 설정 (PreToolUse/PostToolUse 등)
55
- │ │ └── scripts/ # 훅 셸 스크립트 (34개)
55
+ │ │ └── scripts/ # 훅 셸 스크립트 (41개)
56
56
  │ ├── contexts/ # 컨텍스트 설정 파일 (ecomode 등)
57
57
  │ └── ontology/ # Ontology-RAG 지식 그래프
58
58
  └── guides/ # 레퍼런스 문서 디렉토리 (56개)
@@ -87,7 +87,7 @@ CI의 `verify-template-sync.sh`가 소스와 templates/ 간 일치를 검증합
87
87
  | System | 4 |
88
88
  | Agora | 1 |
89
89
 
90
- ### Skills (115)
90
+ ### Skills (114)
91
91
 
92
92
  `.claude/skills/*/SKILL.md` — 재사용 가능한 스킬 모듈.
93
93
 
@@ -116,7 +116,7 @@ CI의 `verify-template-sync.sh`가 소스와 templates/ 간 일치를 검증합
116
116
 
117
117
  각 디렉토리는 단일 토픽에 대한 best practices, 튜토리얼, 또는 설계 가이드를 담습니다. 에이전트가 작업 중 참조합니다 (R006 관심사 분리).
118
118
 
119
- ### Hooks (42)
119
+ ### Hooks (41)
120
120
 
121
121
  `.claude/hooks/scripts/*.sh` — 라이프사이클 훅 스크립트.
122
122
 
@@ -183,6 +183,8 @@ v1.1.29(#1484)에서 제거되었습니다.
183
183
 
184
184
  DEFER 기간 동안의 cross-tool integration 우회 경로:
185
185
 
186
+ 아래 대안과 use case 범위는 당시 결정 이력으로 보존합니다. RTK 프로젝트 통합은 v2.0.0에서 퇴역하므로 RTK proxy skill을 현재 실행 경로로 사용하지 마십시오. 이 기록의 효과 범위를 현재 버전에서 새로 실측했다는 뜻은 아닙니다.
187
+
186
188
  - **RTK proxy skill**: 기존 infra 활용, Cursor 등에서 oh-my-customcode skill 호출
187
189
  - **Codex/Gemini exec skill**: 외부 LLM executor를 skill로 래핑, harness 종속성 없음
188
190
 
@@ -8,18 +8,13 @@ Inspired by OpenHarness's provider profile switching pattern, adapted for oh-my-
8
8
 
9
9
  ## Provider Matrix
10
10
 
11
- | Provider | Skill | CLI Dependency | Model | Strengths |
12
- |----------|-------|---------------|-------|-----------|
13
- | RTK (proxy) | `rtk-exec` | `rtk` CLI | Configurable | Token-optimized output, cost reduction |
11
+ v2.0.0에서는 사용자 결정에 따라 프로젝트 RTK 통합과 공개 `rtk-exec` 스킬을 퇴역합니다. 이 가이드의 RTK 실행 예시·추천을 사용하지 마십시오. 머신에 별도로 설치한 RTK 바이너리는 이 변경으로 제거하지 않습니다.
14
12
 
15
13
  ## Availability Detection
16
14
 
17
15
  The `session-env-check.sh` hook (SessionStart) auto-detects available providers:
18
16
 
19
- ```
20
- [SessionStart] Checking external CLI availability...
21
- rtk: ✓ available
22
- ```
17
+ RTK availability 점검과 상태 출력은 퇴역합니다. Codex·Gemini 등 나머지 CLI availability 점검은 기존 session hook 계약을 유지합니다.
23
18
 
24
19
  Providers are opt-in — missing CLIs are silently skipped.
25
20
 
@@ -27,15 +22,11 @@ Providers are opt-in — missing CLIs are silently skipped.
27
22
 
28
23
  ### Direct Invocation
29
24
 
30
- ```
31
- /rtk-exec "List files matching pattern X"
32
- ```
25
+ 공개 `/rtk-exec` 명령은 제거됩니다. 이 문서에서 다른 provider의 실행 스킬이나 자동 대체 명령을 새로 지정하지 않습니다.
33
26
 
34
27
  ### Provider Selection Guide
35
28
 
36
- | Task | Recommended Provider | Rationale |
37
- |------|---------------------|-----------|
38
- | Token-heavy batch operations | rtk-exec | Compressed output reduces context cost |
29
+ 기존 RTK 추천 항목은 제거됩니다. provider를 선택할 때는 사용 가능한 스킬의 실제 계약과 CLI 설정을 확인하십시오.
39
30
 
40
31
  ### Integration with Existing Skills
41
32
 
@@ -49,18 +40,16 @@ Providers are opt-in — missing CLIs are silently skipped.
49
40
  | Aspect | Multi-Model Routing | Multi-Provider Exec |
50
41
  |--------|--------------------|--------------------|
51
42
  | Scope | Claude model selection | Cross-provider execution |
52
- | Models | haiku / sonnet / opus | RTK proxy |
43
+ | Models | haiku / sonnet / opus | 명시적으로 선택한 외부 provider의 모델 |
53
44
  | Mechanism | `model` frontmatter field | Exec skill invocation |
54
- | Use case | Cost/quality optimization within Claude | Token-optimized output via RTK proxy |
45
+ | Use case | Cost/quality optimization within Claude | 명시적으로 선택한 외부 provider 실행 |
55
46
  | Guide | `guides/multi-model-routing/` | `guides/multi-provider-exec/` |
56
47
 
57
48
  ## Configuration
58
49
 
59
50
  No global configuration required. Each exec skill reads its own CLI configuration:
60
51
 
61
- | Skill | Config Source |
62
- |-------|-------------|
63
- | rtk-exec | RTK proxy running on localhost |
52
+ RTK 전용 설정 연결은 제거됩니다. 이 변경은 다른 CLI의 사용자 설정을 삭제하지 않습니다.
64
53
 
65
54
  ## Limitations
66
55
 
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.1.106",
3
- "lastUpdated": "2026-09-03",
2
+ "version": "2.0.0",
3
+ "lastUpdated": "2026-10-06",
4
4
  "omcustomMinClaudeCode": "2.1.121",
5
5
  "omcustomMinClaudeCodeReason": "Sensitive-path direct Write/Edit on .claude/** under bypassPermissions (R010 deprecation, #1101)",
6
6
  "components": [
@@ -20,7 +20,7 @@
20
20
  "name": "skills",
21
21
  "path": ".claude/skills",
22
22
  "description": "Reusable skill modules (includes slash commands)",
23
- "files": 115
23
+ "files": 114
24
24
  },
25
25
  {
26
26
  "name": "guides",
@@ -1,77 +0,0 @@
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=$(printf '%s\n' "$input" | jq -r '.tool // empty' 2>/dev/null || echo "")
13
- if [ "$tool_name" != "Bash" ]; then
14
- printf '%s\n' "$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
- printf '%s\n' "$input"
29
- exit 0
30
- fi
31
-
32
- # Extract command
33
- cmd=$(printf '%s\n' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null || echo "")
34
- if [ -z "$cmd" ]; then
35
- printf '%s\n' "$input"
36
- exit 0
37
- fi
38
-
39
- # Skip if already using rtk
40
- if echo "$cmd" | grep -qE '^rtk\b'; then
41
- printf '%s\n' "$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
- printf '%s\n' "$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
- printf '%s\n' "$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
- printf '%s\n' "$input" | jq --arg new_cmd "$new_cmd" '.tool_input.command = $new_cmd'
77
- exit 0