ソースを参照

audit fixes: RTK hook, settings unification, graphifyy, statusline

- Add RTK PreToolUse hook (rtk-rewrite.sh) and fix missing config
- Unify settings.json: merge hooks, marketplaces, model into project file
  so link.sh symlink is the single source of truth
- Add statusline: model, folder, git branch, context % progress bar
- Add graphifyy support: detect, install (pipx), lock, doctor, session-start
- Clarify ctx7/ruflo as standalone CLI (not MCP servers)
- Fix install-plugins.sh step numbering (duplicate step 6)
- Add version check in session-start (local vs origin/master)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bastien 1 ヶ月 前
コミット
26aec20d79
9 ファイル変更255 行追加4 行削除
  1. 7 0
      doctor.sh
  2. 1 0
      hooks/.rtk-hook.sha256
  3. 98 0
      hooks/rtk-rewrite.sh
  4. 13 1
      hooks/session-start.sh
  5. 48 0
      hooks/statusline.sh
  6. 39 1
      install-plugins.sh
  7. 5 0
      lib/detect-plugins.sh
  8. 8 2
      plugins.lock.json
  9. 36 0
      settings.json

+ 7 - 0
doctor.sh

@@ -180,6 +180,12 @@ else
   info "Ruflo CLI not installed (optional — enterprise multi-agent: npm install -g ruflo@latest --omit=optional)"
 fi
 
+if detect_graphifyy; then
+  pass "Graphifyy installed (graphify CLI)"
+else
+  info "Graphifyy not installed (optional — codebase knowledge graph: pipx install graphifyy)"
+fi
+
 echo ""
 
 # ────────────────────────────────────────────────────────────
@@ -246,6 +252,7 @@ if detect_frontend_design 2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 200
 if detect_uiux_pro_max    2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 400)); fi
 if detect_context7    2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 200)); fi
 if detect_ruflo       2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 1000)); fi
+if detect_graphifyy   2>/dev/null; then PLUGIN_TOKENS=$((PLUGIN_TOKENS + 300)); fi
 
 TOTAL_TOKENS=$((CLAUDE_MD_TOKENS + SKILL_DESC_TOKENS + PLUGIN_TOKENS))
 SESSION_BUDGET=11000

+ 1 - 0
hooks/.rtk-hook.sha256

@@ -0,0 +1 @@
+ef0d630994fd7ef5f2b84fb66cd6249c493bb8736bcacd4734d7c798125018fb  rtk-rewrite.sh

+ 98 - 0
hooks/rtk-rewrite.sh

@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+# rtk-hook-version: 3
+# RTK Claude Code hook — rewrites commands to use rtk for token savings.
+# Requires: rtk >= 0.23.0, jq
+#
+# This is a thin delegating hook: all rewrite logic lives in `rtk rewrite`,
+# which is the single source of truth (src/discover/registry.rs).
+# To add or change rewrite rules, edit the Rust registry — not this file.
+#
+# Exit code protocol for `rtk rewrite`:
+#   0 + stdout  Rewrite found, no deny/ask rule matched → auto-allow
+#   1           No RTK equivalent → pass through unchanged
+#   2           Deny rule matched → pass through (Claude Code native deny handles it)
+#   3 + stdout  Ask rule matched → rewrite but let Claude Code prompt the user
+
+if ! command -v jq &>/dev/null; then
+  echo "[rtk] WARNING: jq is not installed. Hook cannot rewrite commands. Install jq: https://jqlang.github.io/jq/download/" >&2
+  exit 0
+fi
+
+if ! command -v rtk &>/dev/null; then
+  echo "[rtk] WARNING: rtk is not installed or not in PATH. Hook cannot rewrite commands. Install: https://github.com/rtk-ai/rtk#installation" >&2
+  exit 0
+fi
+
+# Version guard: rtk rewrite was added in 0.23.0.
+# Older binaries: warn once and exit cleanly (no silent failure).
+RTK_VERSION=$(rtk --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
+if [ -n "$RTK_VERSION" ]; then
+  MAJOR=$(echo "$RTK_VERSION" | cut -d. -f1)
+  MINOR=$(echo "$RTK_VERSION" | cut -d. -f2)
+  # Require >= 0.23.0
+  if [ "$MAJOR" -eq 0 ] && [ "$MINOR" -lt 23 ]; then
+    echo "[rtk] WARNING: rtk $RTK_VERSION is too old (need >= 0.23.0). Upgrade: cargo install rtk" >&2
+    exit 0
+  fi
+fi
+
+INPUT=$(cat)
+CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
+
+if [ -z "$CMD" ]; then
+  exit 0
+fi
+
+# Delegate all rewrite + permission logic to the Rust binary.
+REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null)
+EXIT_CODE=$?
+
+case $EXIT_CODE in
+  0)
+    # Rewrite found, no permission rules matched — safe to auto-allow.
+    # If the output is identical, the command was already using RTK.
+    [ "$CMD" = "$REWRITTEN" ] && exit 0
+    ;;
+  1)
+    # No RTK equivalent — pass through unchanged.
+    exit 0
+    ;;
+  2)
+    # Deny rule matched — let Claude Code's native deny rule handle it.
+    exit 0
+    ;;
+  3)
+    # Ask rule matched — rewrite the command but do NOT auto-allow so that
+    # Claude Code prompts the user for confirmation.
+    ;;
+  *)
+    exit 0
+    ;;
+esac
+
+ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input')
+UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd')
+
+if [ "$EXIT_CODE" -eq 3 ]; then
+  # Ask: rewrite the command, omit permissionDecision so Claude Code prompts.
+  jq -n \
+    --argjson updated "$UPDATED_INPUT" \
+    '{
+      "hookSpecificOutput": {
+        "hookEventName": "PreToolUse",
+        "updatedInput": $updated
+      }
+    }'
+else
+  # Allow: rewrite the command and auto-allow.
+  jq -n \
+    --argjson updated "$UPDATED_INPUT" \
+    '{
+      "hookSpecificOutput": {
+        "hookEventName": "PreToolUse",
+        "permissionDecision": "allow",
+        "permissionDecisionReason": "RTK auto-rewrite",
+        "updatedInput": $updated
+      }
+    }'
+fi

+ 13 - 1
hooks/session-start.sh

@@ -48,7 +48,7 @@ unset _lib
 TOGGLE_ACTIVE=()
 TOGGLE_INACTIVE=()
 
-for plugin in gstack uiux_pro_max frontend_design plugin_dev context7 ruflo; do
+for plugin in gstack uiux_pro_max frontend_design plugin_dev context7 ruflo graphifyy; do
   # Map function name to display name
   case "$plugin" in
     uiux_pro_max)    display="ui-ux-pro-max" ;;
@@ -83,6 +83,7 @@ if [ -n "$_claude_real" ]; then
 else
   CONFIG_VERSION="?"
 fi
+REPO_DIR="${_repo_dir:-}"
 unset _claude_real _repo_dir
 
 # Quick passive token cost estimate (Pro session budget = ~11k tokens)
@@ -94,6 +95,7 @@ detect_plugin_dev  2>/dev/null && _passive_t=$((_passive_t + 100))
 detect_uiux_pro_max    2>/dev/null && _passive_t=$((_passive_t + 400))
 detect_context7    2>/dev/null && _passive_t=$((_passive_t + 200))
 detect_ruflo       2>/dev/null && _passive_t=$((_passive_t + 1000))
+detect_graphifyy   2>/dev/null && _passive_t=$((_passive_t + 300))
 _budget_pct=$((_passive_t * 100 / 11000))
 if [ "$_budget_pct" -gt 50 ]; then
   TOKEN_WARN="⚠️  ~${_passive_t}t passif (${_budget_pct}% budget)"
@@ -141,6 +143,16 @@ unset _active_count _inactive_count
 printf "│  🖥️  CLI : %-40s│\n" "$GSD_STATUS"
 [ -n "$TOKEN_WARN" ] && printf "│  💰 %-44s│\n" "${TOKEN_WARN:0:44}"
 printf "│  📦 v%-45s│\n" "$CONFIG_VERSION"
+# Version check: compare local vs remote (non-blocking)
+_remote_ver=""
+if [ -n "$REPO_DIR" ] && [ -d "$REPO_DIR/.git" ]; then
+  _remote_ver=$(cd "$REPO_DIR" 2>/dev/null && git fetch origin --quiet 2>/dev/null && git show origin/master:version.txt 2>/dev/null || true)
+fi
+if [ -n "$_remote_ver" ] && [ "$_remote_ver" != "$CONFIG_VERSION" ]; then
+  printf "│  🔄 update available: v%-27s│\n" "$_remote_ver"
+fi
+unset _remote_ver REPO_DIR
+
 echo "│  💡 /plugin-check  before starting a new project  │"
 echo "│  🩺 /health  to run full diagnostic               │"
 echo "└───────────────────────────────────────────────────┘"

+ 48 - 0
hooks/statusline.sh

@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+# Claude Code statusline — folder, git branch, model, context %
+# Receives JSON on stdin from Claude Code.
+
+INPUT=$(cat)
+
+MODEL=$(echo "$INPUT" | jq -r '.model.display_name // "?"')
+DIR=$(echo "$INPUT" | jq -r '.cwd // "?"')
+FOLDER="${DIR##*/}"
+PCT=$(echo "$INPUT" | jq -r \
+  '.context_window.used_percentage // 0' \
+  | cut -d. -f1)
+
+# Git branch (fast, no network)
+BRANCH=""
+if [ -d "$DIR" ]; then
+  BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)
+fi
+BRANCH_STR="${BRANCH:+ ($BRANCH)}"
+
+# Progress bar (20 chars wide)
+WIDTH=20
+FILLED=$((PCT * WIDTH / 100))
+EMPTY=$((WIDTH - FILLED))
+if [ "$FILLED" -gt 0 ]; then
+  printf -v FILL "%${FILLED}s"
+else
+  FILL=""
+fi
+if [ "$EMPTY" -gt 0 ]; then
+  printf -v PAD "%${EMPTY}s"
+else
+  PAD=""
+fi
+BAR="${FILL// /█}${PAD// /░}"
+
+# Color: green <50%, yellow 50-79%, red >=80%
+if [ "$PCT" -ge 80 ]; then
+  COLOR="\033[31m"
+elif [ "$PCT" -ge 50 ]; then
+  COLOR="\033[33m"
+else
+  COLOR="\033[32m"
+fi
+RESET="\033[0m"
+
+# Output: single line
+echo -e "$MODEL | $FOLDER${BRANCH_STR} | ${COLOR}${BAR}${RESET} ${PCT}%"

+ 39 - 1
install-plugins.sh

@@ -147,6 +147,21 @@ else
   esac
 fi
 
+# --- pipx (for Graphifyy) ---
+if command -v pipx &>/dev/null; then
+  ok "pipx $(pipx --version 2>/dev/null)"
+else
+  info "Installing pipx..."
+  case $OS in
+    macos)        brew install pipx ;;
+    linux-apt)    sudo apt-get install -y pipx ;;
+    linux-dnf)    sudo dnf install -y pipx ;;
+    linux-pacman) sudo pacman -S --noconfirm python-pipx ;;
+    *) warn "Cannot auto-install pipx on $OS" ;;
+  esac
+  pipx ensurepath 2>/dev/null || true
+fi
+
 # --- Claude Code CLI ---
 if command -v claude &>/dev/null; then
   ok "Claude Code $(claude --version 2>/dev/null | head -1)"
@@ -349,7 +364,7 @@ install_plugin "ui-ux-pro-max" "ui-ux-pro-max-skill"
 echo ""
 
 # ============================================================
-# STEP 6 — CONTEXT7 CLI (ctx7)
+# STEP 7 — CONTEXT7 CLI (ctx7)
 # ============================================================
 echo "── Step 7: Context7 CLI ─────────────────────────────────────"
 echo ""
@@ -374,6 +389,28 @@ if command -v ctx7 &>/dev/null; then
   info "Free higher rate limits: ctx7 login (OAuth) or --api-key from context7.com/dashboard"
 fi
 
+# ============================================================
+# STEP 8 — GRAPHIFYY (codebase knowledge graph)
+# ============================================================
+echo "── Step 8: Graphifyy — Knowledge Graph ──────────────────────"
+echo ""
+if command -v graphify &>/dev/null; then
+  ok "graphify already installed"
+else
+  info "Installing graphifyy via pipx..."
+  pipx install graphifyy 2>/dev/null \
+    && ok "graphifyy installed" \
+    || err "graphifyy install failed — run manually: pipx install graphifyy"
+fi
+if command -v graphify &>/dev/null; then
+  info "Running graphify install (dependencies)..."
+  graphify install 2>/dev/null || warn "graphify install failed — run manually"
+  info "Configuring Claude Code integration..."
+  graphify claude install 2>/dev/null || warn "graphify claude install failed — run manually"
+  ok "Graphifyy configured for Claude Code"
+fi
+echo ""
+
 # ============================================================
 # SUMMARY
 # ============================================================
@@ -396,6 +433,7 @@ echo "    🔄 frontend-design     — UI design skill (~200 tokens) [claude-cod
 echo "    🔄 ui-ux-pro-max       — user scope (~400 tokens)"
 echo "    🔄 context7 CLI        — ctx7 (npm global, standalone or MCP setup)"
 echo "    🔄 ruflo CLI           — enterprise multi-agent orchestration (~500-1500 tokens)"
+echo "    🔄 graphifyy           — codebase knowledge graph (pipx, PreToolUse hook)"
 echo ""
 echo "  All plugins installed at: user scope (~/.claude/plugins/)"
 echo "  GStack at: ~/.claude/skills/gstack/ (symlink → submodule)"

+ 5 - 0
lib/detect-plugins.sh

@@ -67,3 +67,8 @@ detect_ruflo() {
   # Ruflo CLI — installed globally via npm
   command -v ruflo &>/dev/null
 }
+
+detect_graphifyy() {
+  # Graphifyy — codebase knowledge graph, installed via pipx
+  command -v graphify &>/dev/null
+}

+ 8 - 2
plugins.lock.json

@@ -18,11 +18,17 @@
   "ruflo": {
     "source": "npm:ruflo",
     "version": "3.5.58",
-    "note": "Enterprise multi-agent MCP server (formerly claude-flow). Requires manual MCP config after install. Check latest at https://www.npmjs.com/package/ruflo before updating."
+    "note": "Enterprise multi-agent orchestration CLI (formerly claude-flow). Standalone CLI, not an MCP server. Check latest at https://www.npmjs.com/package/ruflo before updating."
   },
   "ctx7": {
     "source": "npm:ctx7",
     "version": "latest",
-    "note": "Context7 CLI \u2014 doc lookup for fast-evolving libs. Install: npm install -g ctx7. Setup for Claude Code: ctx7 setup --claude. Standalone: ctx7 docs /vercel/next.js \"middleware\"."
+    "note": "Context7 CLI — doc lookup for fast-evolving libs. Standalone CLI, not an MCP server. Install: npm install -g ctx7. Standalone: ctx7 docs /vercel/next.js \"middleware\"."
+  },
+  "graphifyy": {
+    "source": "pypi:graphifyy",
+    "version": "latest",
+    "managed_by": "pipx",
+    "note": "Codebase knowledge graph. CLI is 'graphify'. Install: pipx install graphifyy && graphify install && graphify claude install. Adds PreToolUse hook for Glob/Grep."
   }
 }

+ 36 - 0
settings.json

@@ -197,6 +197,42 @@
           }
         ]
       }
+    ],
+    "PreToolUse": [
+      {
+        "matcher": "Bash",
+        "hooks": [
+          {
+            "type": "command",
+            "command": "bash ~/.claude/hooks/rtk-rewrite.sh"
+          }
+        ]
+      }
     ]
+  },
+  "extraKnownMarketplaces": {
+    "claude-code-plugins": {
+      "source": {
+        "source": "github",
+        "repo": "anthropics/claude-code"
+      }
+    },
+    "superpowers-marketplace": {
+      "source": {
+        "source": "github",
+        "repo": "obra/superpowers-marketplace"
+      }
+    },
+    "ui-ux-pro-max-skill": {
+      "source": {
+        "source": "github",
+        "repo": "nextlevelbuilder/ui-ux-pro-max-skill"
+      }
+    }
+  },
+  "model": "opus",
+  "statusLine": {
+    "type": "command",
+    "command": "bash ~/.claude/hooks/statusline.sh"
   }
 }