返回 last30days-skill
session-start-hook-not-for-skill-nux.md
根目录 / docs / solutions / workflow-issues / session-start-hook-not-for-skill-nux.md
1 ---
2 title: Skill NUX belongs in SKILL.md Step 0, not a SessionStart hook
3 date: 2026-09-17
4 category: docs/solutions/workflow-issues
5 module: skills/last30days/SKILL.md
6 problem_type: workflow_issue
7 component: development_workflow
8 severity: medium
9 symptoms:
10 - Claude Code or Grok sessions print last30days status even when /last30days is not invoked
11 - ~/Documents/Last30Days is created on every session start
12 - Unconfigured installs see a setup-wizard pitch in every project, indefinitely
13 root_cause: design_error
14 resolution_type: code_fix
15 related_components:
16 - hooks/hooks.json
17 - hooks/scripts/check-config.sh
18 - last30days.py --preflight
19 tags:
20 - session-start
21 - nux
22 - preflight
23 - plugin-hooks
24 - onboarding
25 ---
26
27 # Skill NUX belongs in SKILL.md Step 0, not a SessionStart hook
28
29 ## Problem
30
31 The plugin installed a `SessionStart` hook (`hooks/scripts/check-config.sh`) that ran in every Claude Code and Grok session, in every project, whether or not anyone invoked `/last30days`. It printed a welcome or source-count banner, optionally upsold ScrapeCreators, created `~/Documents/Last30Days`, scanned Keychain item names, and auto-chmod'd `.env` files.
32
33 That is the wrong layer for skill onboarding. A trusted plugin hook cannot be "just for last30days users."
34
35 ## Root cause
36
37 [PR #58](https://github.com/mvanhorn/last30days-skill/pull/58) (2026-03-10) added a silent-when-configured missing-keys warning. [PR #126](https://github.com/mvanhorn/last30days-skill/pull/126) (v2.9.6) rewrote it into an always-print NUX. Later PRs piled on mkdir (#476), Keychain presence, and security patches (#914 cwd-adjacent `.env` RCE, #1074 decoy `check-config.sh` from session cwd). `--preflight` in the non-modal first-run flow was a second copy of the same permission summary.
38
39 SKILL.md Step 0 already owns consent (cookies, ScrapeCreators). The engine already creates the save dir on first save. `last30days.py --preflight` is a secret-free inspector for humans, scripts, and the MCP `preflight` tool — not a required first-run beat.
40
41 ## Solution
42
43 - Do not ship `hooks/hooks.json` or a SessionStart command. Plugin auto-discovery would load it.
44 - First-run NUX stays in SKILL.md Step 0 (modal / non-modal / Grok Bot). Detect setup from key presence; do not dump `.env`.
45 - `--preflight` stays as an opt-in inspector and frozen JSON contract. Do not run it as a required first-run step.
46 - `lib/preflight.py` (Class 1 query refuse-gate) is unrelated and stays in the engine.
47
48 ## Prevention
49
50 If a future change wants "status at session start," put it behind an explicit user-installed hook or a slash-command invocation. A marketplace plugin SessionStart hook is not an opt-in.
51
51 lines MARKDOWN