feat(hooks): 匯入 jsc-hooks 技能組並統一 marketplace 為 jsc #2
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/session-timer.sh\" start" } ] }
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/ste100-guard.sh\"" } ] }
|
||||
],
|
||||
"Stop": [
|
||||
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/session-timer.sh\" mark" } ] }
|
||||
],
|
||||
"SessionEnd": [
|
||||
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/session-timer.sh\" mark" } ] }
|
||||
],
|
||||
"PostToolUse": [
|
||||
{ "matcher": "Skill", "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/skill-usage.sh\"" } ] }
|
||||
]
|
||||
}
|
||||
}
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env sh
|
||||
# lib.sh — jsc hooks 共用函式。所有 hook 腳本 source 此檔。
|
||||
# 輸入相容:Claude 式 stdin JSON、或環境變數(codex/copilot/antigravity/kiro 接線時設定)。
|
||||
# 缺資料時安靜降級,hook 永遠 exit 0,不可中斷宿主 CLI。
|
||||
|
||||
JSC_HOME="${JSC_HOME:-$HOME/.jsc}"
|
||||
mkdir -p "$JSC_HOME/sessions" "$JSC_HOME/usage" 2>/dev/null || true
|
||||
|
||||
# 讀完 stdin(可能為空;非阻塞宿主)
|
||||
read_stdin() {
|
||||
if [ -t 0 ]; then STDIN_JSON=""; else STDIN_JSON=$(cat 2>/dev/null || true); fi
|
||||
}
|
||||
|
||||
# 從 stdin JSON 取字串欄位(naive 但足夠應付各 CLI 的扁平 payload)
|
||||
json_str() { # $1=欄位名
|
||||
printf '%s' "$STDIN_JSON" | tr -d '\n' \
|
||||
| sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" | head -n1
|
||||
}
|
||||
|
||||
# 目前 session id:stdin JSON > 環境變數 > 固定值
|
||||
session_id() {
|
||||
sid=$(json_str session_id)
|
||||
[ -n "$sid" ] || sid="${JSC_SESSION_ID:-${CLAUDE_SESSION_ID:-default}}"
|
||||
printf '%s' "$sid"
|
||||
}
|
||||
|
||||
# 目前 CLI 名稱:環境變數 > 依 stdin 特徵猜測 > unknown
|
||||
cli_name() {
|
||||
if [ -n "${JSC_CLI:-}" ]; then printf '%s' "$JSC_CLI"
|
||||
elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then printf 'claude'
|
||||
else printf 'unknown'; fi
|
||||
}
|
||||
|
||||
now_epoch() { date +%s; }
|
||||
now_iso() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env sh
|
||||
# session-timer.sh — 記錄工作階段花費時間(供 jsc-log:worklog 取用)。
|
||||
# 用法:
|
||||
# session-timer.sh start # SessionStart:記錄起始時間
|
||||
# session-timer.sh mark # Stop/SessionEnd:更新最後活動時間
|
||||
# session-timer.sh report [sid] # 印出 {sid} {seconds};無紀錄印 0
|
||||
HERE=$(dirname "$0"); . "$HERE/lib.sh"
|
||||
read_stdin
|
||||
sid=$(session_id)
|
||||
case "${1:-mark}" in
|
||||
start)
|
||||
f="$JSC_HOME/sessions/$sid.start"
|
||||
[ -f "$f" ] || now_epoch > "$f" ;;
|
||||
mark)
|
||||
now_epoch > "$JSC_HOME/sessions/$sid.end" ;;
|
||||
report)
|
||||
rsid="${2:-$sid}"
|
||||
s=$(cat "$JSC_HOME/sessions/$rsid.start" 2>/dev/null || echo "")
|
||||
e=$(cat "$JSC_HOME/sessions/$rsid.end" 2>/dev/null || now_epoch)
|
||||
if [ -n "$s" ]; then echo "$rsid $((e - s))"; else echo "$rsid 0"; fi ;;
|
||||
esac
|
||||
exit 0
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env sh
|
||||
# skill-usage.sh — 記錄技能使用與呼叫鏈(供 jsc-log:stats 統計)。
|
||||
# Claude: PostToolUse(matcher=Skill) 接線;其他 CLI 由 wrapper 以
|
||||
# JSC_SKILL=<name> skill-usage.sh 呼叫。
|
||||
# 產出:
|
||||
# $JSC_HOME/usage/skills.jsonl {ts,cli,session,skill}
|
||||
# $JSC_HOME/usage/chains.jsonl {ts,cli,session,from,to}(同 session 內前一技能 → 本技能)
|
||||
HERE=$(dirname "$0"); . "$HERE/lib.sh"
|
||||
read_stdin
|
||||
skill="${JSC_SKILL:-$(json_str skill)}"
|
||||
[ -n "$skill" ] || exit 0
|
||||
sid=$(session_id); cli=$(cli_name); ts=$(now_iso)
|
||||
printf '{"ts":"%s","cli":"%s","session":"%s","skill":"%s"}\n' \
|
||||
"$ts" "$cli" "$sid" "$skill" >> "$JSC_HOME/usage/skills.jsonl"
|
||||
last_f="$JSC_HOME/sessions/$sid.lastskill"
|
||||
last=$(cat "$last_f" 2>/dev/null || echo "")
|
||||
if [ -n "$last" ]; then
|
||||
printf '{"ts":"%s","cli":"%s","session":"%s","from":"%s","to":"%s"}\n' \
|
||||
"$ts" "$cli" "$sid" "$last" "$skill" >> "$JSC_HOME/usage/chains.jsonl"
|
||||
fi
|
||||
printf '%s' "$skill" > "$last_f"
|
||||
exit 0
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
# ste100-guard.sh — 於每次使用者提示時注入語言規則(hook > prompt 的強制層)。
|
||||
# Claude: UserPromptSubmit 的 stdout 會成為額外 context。
|
||||
# 其他 CLI: 由 hooks-install 以各自的規則檔(AGENTS.md 等)落地,本腳本仍可被 wrapper 呼叫。
|
||||
echo "[jsc] 輸出規則:所有回覆基於 STE100 使用繁體中文(短句、一句一指令、主動語態、術語一致、UTF-8 無亂碼)。"
|
||||
exit 0
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: hooks-install
|
||||
description: Wire jsc hooks (STE100 guard, session timer, skill usage logger) into every installed AI CLI. Detect CLIs via jsc-cli detect-clis.sh, then apply native hook config per CLI or fall back to instruction files. Use after installing or updating the jsc plugin set; not for writing new hooks.
|
||||
---
|
||||
|
||||
# hooks-install — 將 jsc hooks 接線到所有已安裝的 CLI
|
||||
|
||||
目標:讓三支 hook(`ste100-guard.sh`、`session-timer.sh`、`skill-usage.sh`)在每個 CLI 生效。
|
||||
細節流程**必須以 sub agent 執行**,主 agent 只回報結果摘要。
|
||||
|
||||
## 步驟
|
||||
|
||||
1. 執行 `jsc-cli/tools/detect-clis.sh` 取得已安裝的 CLI 與路徑。
|
||||
2. 對每個 CLI 依下表接線(hook 優先,無 hook 系統就降級為規則檔):
|
||||
|
||||
| CLI | 接線方式 |
|
||||
| --- | --- |
|
||||
| claude | plugin 安裝時自動載入 `jsc-hooks/hooks/hooks.json`,只需驗證:`claude plugin list` 有 `jsc-hooks` 且 `/hooks` 顯示已註冊 |
|
||||
| codex | `~/.codex/config.toml` 設定 `notify` 指向 `session-timer.sh mark`(帶 `JSC_CLI=codex`);STE100 規則追加到 `~/.codex/AGENTS.md`(prompt 降級) |
|
||||
| copilot | 無 hook 系統:STE100 規則追加到 `~/.config/copilot/copilot-instructions.md`(prompt 降級) |
|
||||
| antigravity | 無公開 hook 系統:STE100 規則追加到全域 rules 檔(prompt 降級) |
|
||||
| kiro | 於工作區 `.kiro/hooks/` 建立 agent hook,觸發時執行對應腳本(帶 `JSC_CLI=kiro`) |
|
||||
|
||||
3. 規則檔追加內容一律使用 `ste100-guard.sh` 的輸出文字,且以 `<!-- jsc-hooks -->` 標記包住,重複執行時整段取代不重複追加。
|
||||
4. 回報每個 CLI 的接線結果(成功 / 降級為 prompt / 跳過原因)。
|
||||
|
||||
## 注意
|
||||
|
||||
- Hook 腳本同時接受 stdin JSON 與環境變數(`JSC_CLI`、`JSC_SESSION_ID`、`JSC_SKILL`),wrapper 只需設環境變數。
|
||||
- 資料落在 `$JSC_HOME`(預設 `~/.jsc`),供 `jsc-log:worklog` 與 `jsc-log:stats` 取用。
|
||||
Reference in New Issue
Block a user