@pushrec/skills 0.3.2 → 0.3.4

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/README.md CHANGED
@@ -2,7 +2,15 @@
2
2
 
3
3
  CLI for the pushREC Agent Skills Marketplace. Install, manage, and update Claude Code skills.
4
4
 
5
- **Version:** `0.1.0` | **Published:** 2026-02-19
5
+ **Local repo version target:** `0.3.4`
6
+
7
+ **Do not assume npm latest from this file.** Verify before customer-facing instructions:
8
+
9
+ ```bash
10
+ npm view @pushrec/skills version
11
+ ```
12
+
13
+ As of 2026-02-27: npm `latest` = `0.2.0`, `next` = `0.3.2`. Local tree at `0.3.4` (Windows readiness). 19 test files, 139 tests passing.
6
14
 
7
15
  ## Quick Start
8
16
 
@@ -30,19 +38,22 @@ pushrec-skills auth login
30
38
 
31
39
  | Command | Description |
32
40
  |---------|-------------|
33
- | `pushrec-skills list` | Browse available skills |
34
- | `pushrec-skills install <name>` | Install a skill |
35
- | `pushrec-skills install --all` | Install all licensed skills |
36
- | `pushrec-skills update [name]` | Update installed skills |
37
- | `pushrec-skills search <query>` | Search the catalog |
38
- | `pushrec-skills info <name>` | Get skill details |
39
- | `pushrec-skills uninstall <name>` | Remove a skill |
41
+ | `pushrec-skills install [name]` | Install a skill (or `--all` for all available) |
42
+ | `pushrec-skills update [name]` | Update installed skills to latest versions |
43
+ | `pushrec-skills sync [name]` | Synchronize local skills with the registry (install missing + update installed) |
44
+ | `pushrec-skills list` | List available or installed skills |
45
+ | `pushrec-skills search <query>` | Search skills by keyword |
46
+ | `pushrec-skills info <name>` | Show detailed information about a skill |
47
+ | `pushrec-skills uninstall <name>` | Uninstall a skill from the active skills root |
48
+ | `pushrec-skills rollback <name>` | Rollback an installed skill to a backup snapshot |
40
49
 
41
- ### Utility
50
+ ### Setup & Utility
42
51
 
43
52
  | Command | Description |
44
53
  |---------|-------------|
45
- | `pushrec-skills health` | Check registry connectivity |
54
+ | `pushrec-skills setup` | One-command onboarding: verify license, activate device, install all skills |
55
+ | `pushrec-skills health` | Check registry server health (use `--full` for full diagnostic) |
56
+ | `pushrec-skills dashboard` | Launch the Generative UI dashboard |
46
57
 
47
58
  ## Registry
48
59
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pushrec-skills
3
- version: 1.0.0
3
+ version: 1.1.0
4
4
  description: "Universal entry point for all pushREC skill operations. Onboarding, skill discovery, troubleshooting, API key setup, and update guidance. Use when: first time using pushREC skills, need help finding the right skill, skill isn't working, setting up API keys, updating skills, or asking how skills work. Aliases: /onboarding, /start, /get-started, /help, /skills, /pushrec."
5
5
  category: meta-tools
6
6
  aliases: [onboarding, start, get-started, help, skills, pushrec]
@@ -143,7 +143,7 @@ Write `progress.json` with `first_win: {status: "completed", skill_recommended:
143
143
  Present a personalized overview of available skills organized by level. Show only levels relevant to their profile.
144
144
 
145
145
  **Structure:**
146
- - **Level 0 -- Foundation (available now):** Group by category relevant to their profile. Highlight 5-8 most relevant skills with one-line descriptions. Mention total count (80+ skills).
146
+ - **Level 0 -- Foundation (available now):** Group by category relevant to their profile. Highlight 5-8 most relevant skills with one-line descriptions. Mention total count (check `~/.claude/skills/registry.json` for current `skill_count` — never hardcode).
147
147
  - **Level 1 -- Google Workspace:** List capabilities unlocked (Gmail, Sheets, Docs, Calendar, Drive, Contacts, Slides). Note: "~15 minutes one-time setup."
148
148
  - **Level 2 -- Creative and Data:** List key capabilities (AI image generation, voice synthesis, vision analysis, CRM). Note per-service setup time.
149
149
  - **Level 3 -- Communication:** List capabilities (SMS, AI phone agents, web scraping). Note KYC requirements.
@@ -232,6 +232,10 @@ Check for missing prerequisites, missing API keys, or license issues.
232
232
  | Skill produces no output | Skill invocation issue | Verify skill name, try `/skill-name` syntax |
233
233
  | Import errors in scripts | Missing Python dependencies | Check skill's requirements, run `pip install` or `uv run --with` |
234
234
  | License validation fails | License issue | Run `npx @pushrec/skills auth login` to re-authenticate |
235
+ | Hook errors in session output | Broken or incompatible hook | Check `~/.claude/settings.json` hooks array, remove or fix the offending hook |
236
+ | Rate limit / throttle errors | API quota exceeded | Wait and retry, or check service dashboard for quota limits |
237
+ | "No space left on device" | Disk full | Free disk space, check `df -h` output |
238
+ | Version mismatch warnings | Claude Code outdated | Run `claude update` to update to latest version |
235
239
 
236
240
  ### Step 4: Escalation
237
241
 
@@ -316,6 +320,7 @@ Note: `install --all` skips already-installed skills (no duplicates). Running it
316
320
  | Skipping the diagnostic on first run | Always run diagnostic.py in Phase 0 |
317
321
  | Proceeding after critical failures | STOP and help fix prerequisites before continuing |
318
322
  | Recommending L1+ skills without mentioning API key requirements | Always state the setup requirement alongside the recommendation |
323
+ | Hardcoding skill counts | Always query dynamically or use safe-floor estimates |
319
324
 
320
325
  ### Verification Checklist
321
326
 
@@ -338,6 +343,7 @@ Before finishing any response, verify:
338
343
  | Update skills | `npx @pushrec/skills update` |
339
344
  | Install new skills | `npx @pushrec/skills install --all` |
340
345
  | List all skills | `npx @pushrec/skills list` |
346
+ | Check CLI version | `npx @pushrec/skills --version` |
341
347
  | Get help | Post in skool.com/pushrec-2909 |
342
348
  | Reset onboarding | Type `/pushrec-skills` and say "reset" |
343
349
 
@@ -349,12 +355,27 @@ Before finishing any response, verify:
349
355
 
350
356
  ### State Files
351
357
 
358
+ The `state/` directory is created automatically on first write. No manual setup needed.
359
+
352
360
  | File | Purpose |
353
361
  |------|---------|
354
362
  | `state/profile.json` | Business profile from adaptive profiling |
355
363
  | `state/progress.json` | Completed phases, unlocked levels, skills invoked |
356
364
 
365
+ **Error recovery:** If `profile.json` or `progress.json` fails to parse (corrupt JSON), offer the user a reset: `rm ~/.claude/skills/pushrec-skills/state/*.json` and restart onboarding.
366
+
357
367
  ### Community
358
368
 
359
369
  - **Skool:** skool.com/pushrec-2909
360
370
  - **Live Q&A:** check Skool for scheduled sessions
371
+
372
+ ---
373
+
374
+ ## See Also
375
+
376
+ | Resource | Path | Purpose |
377
+ |----------|------|---------|
378
+ | Agent Skills Marketplace | `~/pushrec-vault/1-Projects/agent-skills-marketplace/` | License-gated skill distribution (ThriveCart + Convex + Vercel) |
379
+ | GTM Sprint | `~/pushrec-vault/1-Projects/gtm-sprint-claude-skills/` | Launch strategy, offer tiers, voice bible |
380
+ | Generative UI Dashboard | `~/.claude/skills/generative-ui/` | Visual dashboard with SkillBrowser (verify count via registry.json), SetupChecklist |
381
+ | Registry Runbook | `~/pushrec-vault/1-Projects/agent-skills-marketplace/registry/CLAUDE.md` | Zero-assumptions technical reference (687 lines) |
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env python3
2
+ """SessionStart hook for pushREC Skills onboarding nudge.
3
+
4
+ Reads progress.json and outputs a brief reminder if onboarding is incomplete.
5
+ Exit code 0 always — hooks must never fail the session.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ import sys
11
+ from datetime import datetime, timezone
12
+
13
+ PROGRESS_FILE = os.path.expanduser(
14
+ "~/.claude/skills/pushrec-skills/state/progress.json"
15
+ )
16
+
17
+ # Canonical phase order for determining which phase comes next
18
+ PHASE_ORDER = [
19
+ ("diagnostic", "System Diagnostic"),
20
+ ("profiling", "Adaptive Profiling"),
21
+ ("cc101", "Claude Code 101"),
22
+ ("first_win", "First Win"),
23
+ ("skill_map", "Skill Map"),
24
+ ("unlock_guide", "Progressive Unlock"),
25
+ ]
26
+
27
+
28
+ def main():
29
+ # Prevent hook loops
30
+ if os.environ.get("stop_hook_active"):
31
+ return
32
+
33
+ # No progress file -> first-time user
34
+ if not os.path.exists(PROGRESS_FILE):
35
+ print(
36
+ "pushREC Skills: Welcome! Type /pushrec-skills to start your "
37
+ "personalized onboarding (takes ~30 min)."
38
+ )
39
+ return
40
+
41
+ # Read and parse progress
42
+ try:
43
+ with open(PROGRESS_FILE, "r") as f:
44
+ progress = json.load(f)
45
+ except json.JSONDecodeError as exc:
46
+ sys.stderr.write(f"pushrec-skills: progress.json parse error: {exc}\n")
47
+ return
48
+ except OSError as exc:
49
+ sys.stderr.write(f"pushrec-skills: progress.json read error: {exc}\n")
50
+ return
51
+
52
+ phases = progress.get("phases", {})
53
+ total_phases = len(PHASE_ORDER)
54
+ completed_count = sum(
55
+ 1
56
+ for p in phases.values()
57
+ if isinstance(p, dict) and p.get("status") in ("completed", "skipped")
58
+ )
59
+
60
+ # All phases done -- nothing to show
61
+ if completed_count >= total_phases:
62
+ return
63
+
64
+ # Determine the next incomplete phase
65
+ next_phase_name = None
66
+ for phase_key, phase_label in PHASE_ORDER:
67
+ phase_data = phases.get(phase_key, {})
68
+ if not isinstance(phase_data, dict) or phase_data.get("status") not in (
69
+ "completed",
70
+ "skipped",
71
+ ):
72
+ next_phase_name = phase_label
73
+ break
74
+
75
+ # Build the nudge message
76
+ prefix = ""
77
+ last_session_at = progress.get("last_session_at")
78
+ if last_session_at:
79
+ try:
80
+ last_dt = datetime.fromisoformat(last_session_at.replace("Z", "+00:00"))
81
+ now = datetime.now(timezone.utc)
82
+ days_since = (now - last_dt).days
83
+ if days_since > 7:
84
+ prefix = "Welcome back! It's been a while. "
85
+ except (ValueError, TypeError):
86
+ pass
87
+
88
+ if next_phase_name:
89
+ print(
90
+ f"{prefix}pushREC Skills: {completed_count}/{total_phases} phases complete. "
91
+ f"Next up: {next_phase_name}. Type /pushrec-skills to continue."
92
+ )
93
+ else:
94
+ print(
95
+ f"{prefix}pushREC Skills: {completed_count}/{total_phases} phases complete. "
96
+ "Type /pushrec-skills to continue where you left off."
97
+ )
98
+
99
+
100
+ if __name__ == "__main__":
101
+ try:
102
+ main()
103
+ except Exception:
104
+ pass # Never crash the session
105
+ sys.exit(0)
@@ -1,5 +1,5 @@
1
1
  # pushREC Skills Prerequisites
2
- # version: 1.0.0
2
+ # version: 1.1.0
3
3
  #
4
4
  # Skills NOT listed here require NO API keys or credentials (Level 0).
5
5
  # 80+ skills work immediately after install with zero configuration.
@@ -24,7 +24,7 @@ gmail:
24
24
  service: Google Cloud Console
25
25
  setup_url: https://console.cloud.google.com/apis/credentials
26
26
  setup_time: "15 minutes (one-time for all Google services)"
27
- credentials_path: "~/.gmail-mcp/gcp-oauth.keys.json"
27
+ credentials_path: "~/.claude/.credentials/gmail-oauth.keys.json"
28
28
  notes: "OAuth2 browser consent flow. Tokens stored at ~/.gmail-mcp/credentials.json"
29
29
 
30
30
  google-sheets:
@@ -57,7 +57,7 @@ google-calendar:
57
57
  service: Google Cloud Console
58
58
  setup_url: https://console.cloud.google.com/apis/credentials
59
59
  setup_time: "15 minutes (shared with other Google services)"
60
- credentials_path: "~/.calendar-mcp/gcp-oauth.keys.json"
60
+ credentials_path: "~/.claude/.credentials/calendar-oauth.keys.json"
61
61
  notes: "OAuth2 browser consent flow."
62
62
 
63
63
  google-drive:
@@ -68,7 +68,7 @@ google-drive:
68
68
  service: Google Cloud Console
69
69
  setup_url: https://console.cloud.google.com/apis/credentials
70
70
  setup_time: "15 minutes (shared with other Google services)"
71
- credentials_path: "~/.drive-mcp/gcp-oauth.keys.json"
71
+ credentials_path: "~/.claude/.credentials/drive-oauth.keys.json"
72
72
  notes: "OAuth2 browser consent flow."
73
73
 
74
74
  google-contacts:
@@ -79,7 +79,7 @@ google-contacts:
79
79
  service: Google Cloud Console
80
80
  setup_url: https://console.cloud.google.com/apis/credentials
81
81
  setup_time: "15 minutes (shared with other Google services)"
82
- credentials_path: "~/.contacts-mcp/gcp-oauth.keys.json"
82
+ credentials_path: "~/.claude/.credentials/contacts-oauth.keys.json"
83
83
  notes: "Read-only. Shares GCP project with Gmail."
84
84
 
85
85
  google-slides:
@@ -156,7 +156,13 @@ ocr-processor:
156
156
  service: Google AI Studio
157
157
  setup_url: https://aistudio.google.com/apikey
158
158
  setup_time: "2 minutes (shared with gemini-vision)"
159
- notes: "Primary provider: Gemini. Also supports MISTRAL_API_KEY as alternative."
159
+ notes: "Primary provider: Gemini."
160
+ - env: MISTRAL_API_KEY
161
+ type: api_key
162
+ service: Mistral AI
163
+ setup_url: https://console.mistral.ai/api-keys
164
+ setup_time: "2 minutes"
165
+ notes: "Alternative provider for OCR. Set in ~/.claude/.env as MISTRAL_API_KEY=xxx"
160
166
 
161
167
  airtable:
162
168
  level: 2
@@ -248,6 +254,37 @@ skool-api:
248
254
  setup_time: "5 minutes (browser login)"
249
255
  notes: "Cookie-based auth persisted at ~/.skool/cookies.json. No API key - uses browser login."
250
256
 
257
+ # ============================================================================
258
+ # LEVEL 2 (continued): General-purpose API keys
259
+ # Used by multiple skills or for advanced integrations.
260
+ # ============================================================================
261
+
262
+ deep-research:
263
+ level: 2
264
+ requires:
265
+ - env: OPENAI_API_KEY
266
+ type: api_key
267
+ service: OpenAI
268
+ setup_url: https://platform.openai.com/api-keys
269
+ setup_time: "2 minutes"
270
+ notes: "Used by deep-research and other skills that support OpenAI models."
271
+ - env: ANTHROPIC_API_KEY
272
+ type: api_key
273
+ service: Anthropic
274
+ setup_url: https://console.anthropic.com/settings/keys
275
+ setup_time: "2 minutes"
276
+ notes: "Used for API-routed sub-agents and headless operations."
277
+
278
+ browser-automation:
279
+ level: 2
280
+ requires:
281
+ - env: RAPIDAPI_KEY
282
+ type: api_key
283
+ service: RapidAPI
284
+ setup_url: https://rapidapi.com/developer/dashboard
285
+ setup_time: "3 minutes"
286
+ notes: "Used by browser-automation and data enrichment integrations."
287
+
251
288
  # ============================================================================
252
289
  # LEVEL 3: Service Accounts
253
290
  # Require KYC verification, usage-based billing, or special configuration.
@@ -14,12 +14,14 @@ import sys
14
14
  from datetime import datetime, timezone
15
15
  from pathlib import Path
16
16
 
17
- VERSION = "1.0.0"
17
+ VERSION = "1.1.0"
18
18
  SKILLS_DIR = Path.home() / ".claude" / "skills"
19
19
  CONFIG_PATH = Path.home() / ".pushrec" / "config.json"
20
20
  ENV_PATH = Path.home() / ".claude" / ".env"
21
+ PREREQUISITES_PATH = Path(__file__).resolve().parent.parent / "references" / "prerequisites.yaml"
21
22
 
22
- KNOWN_KEY_PREFIXES = [
23
+ # Fallback list used when prerequisites.yaml cannot be read
24
+ _FALLBACK_KEY_PREFIXES = [
23
25
  "ELEVENLABS_API_KEY",
24
26
  "OPENAI_API_KEY",
25
27
  "ANTHROPIC_API_KEY",
@@ -41,6 +43,29 @@ KNOWN_KEY_PREFIXES = [
41
43
  ]
42
44
 
43
45
 
46
+ def load_key_prefixes():
47
+ """Load API key env var names from prerequisites.yaml, falling back to hardcoded list."""
48
+ try:
49
+ with open(PREREQUISITES_PATH, "r") as f:
50
+ content = f.read()
51
+ # Simple YAML parsing: extract all `env: VALUE` lines (no PyYAML dependency)
52
+ prefixes = set()
53
+ for line in content.splitlines():
54
+ stripped = line.strip()
55
+ if stripped.startswith("- env:") or stripped.startswith("env:"):
56
+ value = stripped.split(":", 1)[1].strip()
57
+ if value:
58
+ prefixes.add(value)
59
+ if prefixes:
60
+ return sorted(prefixes)
61
+ except (OSError, ValueError):
62
+ pass
63
+ return _FALLBACK_KEY_PREFIXES
64
+
65
+
66
+ KNOWN_KEY_PREFIXES = load_key_prefixes()
67
+
68
+
44
69
  def run_command(args):
45
70
  """Run a shell command and return (success, stdout_stripped)."""
46
71
  try:
@@ -176,6 +201,8 @@ def check_obsidian():
176
201
 
177
202
 
178
203
  def main():
204
+ # Exit silently in headless mode — hooks must never block headless sessions
205
+ # (e.g. CI pipelines, sub-agents) with interactive diagnostics or stdout noise.
179
206
  if os.environ.get("CLAUDE_HEADLESS"):
180
207
  sys.exit(0)
181
208
 
@@ -219,6 +246,8 @@ def main():
219
246
  "version": VERSION,
220
247
  "timestamp": datetime.now(timezone.utc).isoformat(),
221
248
  "platform": platform.system().lower(),
249
+ "npm_version": checks["npm"].get("version"),
250
+ "skills_count": checks["skills_installed"].get("count", 0),
222
251
  "checks": checks,
223
252
  "exit_code": exit_code,
224
253
  "summary": summary,