@rulemetric/hooks 0.2.0 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulemetric/hooks",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -96,16 +96,38 @@ _rulemetric_ensure_session() {
96
96
  # the session.
97
97
  local launch_project_path="${RULEMETRIC_LAUNCH_PROJECT_PATH:-}"
98
98
 
99
+ # Detect headless `claude -p` (a.k.a. `--print`) by inspecting the parent
100
+ # process argv. Hooks are spawned by Claude Code, so $PPID is the Claude
101
+ # Code process itself. A `claude -p "prompt"` invocation has `-p` (or
102
+ # `--print`) in argv; an interactive `claude` invocation does not.
103
+ # Match as a word boundary so flag-clusters like `-pv` or paths
104
+ # containing `p` don't false-positive. The Linux/macOS `ps -o args=` flag
105
+ # is portable; we fall back to "interactive" on any error.
106
+ #
107
+ # Why this matters: tinyworlds' godogen pipeline (and similar batch
108
+ # workflows) fires `claude -p` 3x in parallel. Each spawn is a real,
109
+ # distinct Claude Code session — RuleMetric records each correctly — but
110
+ # the user reads them as duplicates. Tagging them at capture time lets
111
+ # the dashboard render a "headless" badge and (optionally) filter them
112
+ # from the default sessions view.
113
+ local is_headless="false"
114
+ local parent_args
115
+ parent_args=$(ps -o args= -p "$PPID" 2>/dev/null || echo "")
116
+ if echo "$parent_args" | grep -qE '(^|[[:space:]])(-p|--print)([[:space:]]|=|$)'; then
117
+ is_headless="true"
118
+ fi
119
+
99
120
  local metadata
100
121
  metadata=$(jq -n \
101
122
  --arg gitRemote "$git_remote" \
102
123
  --arg gitRootCommit "$git_root_commit" \
103
124
  --arg launchProjectPath "$launch_project_path" \
104
125
  --argjson isWorktree "$is_worktree" \
126
+ --argjson isHeadless "$is_headless" \
105
127
  '{} + (if $gitRemote != "" then {gitRemote: $gitRemote} else {} end)
106
128
  + (if $gitRootCommit != "" then {gitRootCommit: $gitRootCommit} else {} end)
107
129
  + (if $launchProjectPath != "" then {launchProjectPath: $launchProjectPath} else {} end)
108
- + {isWorktree: $isWorktree}')
130
+ + {isWorktree: $isWorktree, headless: $isHeadless}')
109
131
 
110
132
  # Optional org attribution (Phase 8.1). RULEMETRIC_ORG_ID is exported by
111
133
  # _config.sh — env wins over the local active-org file. If unset/empty, we