@pushrec/skills 0.1.0 → 0.3.2

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.
@@ -0,0 +1,375 @@
1
+ # pushREC Skills Prerequisites
2
+ # version: 1.0.0
3
+ #
4
+ # Skills NOT listed here require NO API keys or credentials (Level 0).
5
+ # 80+ skills work immediately after install with zero configuration.
6
+ #
7
+ # Level definitions:
8
+ # L1: Google OAuth2 - one-time browser consent flow (~15 min total)
9
+ # L2: API keys - individual service signups (~2-5 min each)
10
+ # L3: Service accounts - KYC verification or usage-based billing (~10 min each)
11
+ # L4: Applications - requires desktop app (Obsidian) installed
12
+
13
+ # ============================================================================
14
+ # LEVEL 1: Google OAuth2
15
+ # One-time setup: Create a Google Cloud project, enable APIs, create OAuth
16
+ # credentials. All Google skills share the same GCP project.
17
+ # ============================================================================
18
+
19
+ gmail:
20
+ level: 1
21
+ requires:
22
+ - env: GOOGLE_OAUTH_CREDENTIALS
23
+ type: oauth2
24
+ service: Google Cloud Console
25
+ setup_url: https://console.cloud.google.com/apis/credentials
26
+ setup_time: "15 minutes (one-time for all Google services)"
27
+ credentials_path: "~/.gmail-mcp/gcp-oauth.keys.json"
28
+ notes: "OAuth2 browser consent flow. Tokens stored at ~/.gmail-mcp/credentials.json"
29
+
30
+ google-sheets:
31
+ level: 1
32
+ requires:
33
+ - env: GOOGLE_OAUTH_CREDENTIALS
34
+ type: oauth2
35
+ service: Google Cloud Console
36
+ setup_url: https://console.cloud.google.com/apis/credentials
37
+ setup_time: "15 minutes (shared with other Google services)"
38
+ credentials_path: "~/.claude/.credentials/sheets-client-secret.json"
39
+ notes: "OAuth2 preferred. Service Account fallback supported."
40
+
41
+ google-docs:
42
+ level: 1
43
+ requires:
44
+ - env: GOOGLE_OAUTH_CREDENTIALS
45
+ type: oauth2
46
+ service: Google Cloud Console
47
+ setup_url: https://console.cloud.google.com/apis/credentials
48
+ setup_time: "15 minutes (shared with other Google services)"
49
+ credentials_path: "~/.claude/.credentials/docs-client-secret.json"
50
+ notes: "OAuth2 preferred. Service Account fallback supported."
51
+
52
+ google-calendar:
53
+ level: 1
54
+ requires:
55
+ - env: GOOGLE_OAUTH_CREDENTIALS
56
+ type: oauth2
57
+ service: Google Cloud Console
58
+ setup_url: https://console.cloud.google.com/apis/credentials
59
+ setup_time: "15 minutes (shared with other Google services)"
60
+ credentials_path: "~/.calendar-mcp/gcp-oauth.keys.json"
61
+ notes: "OAuth2 browser consent flow."
62
+
63
+ google-drive:
64
+ level: 1
65
+ requires:
66
+ - env: GOOGLE_OAUTH_CREDENTIALS
67
+ type: oauth2
68
+ service: Google Cloud Console
69
+ setup_url: https://console.cloud.google.com/apis/credentials
70
+ setup_time: "15 minutes (shared with other Google services)"
71
+ credentials_path: "~/.drive-mcp/gcp-oauth.keys.json"
72
+ notes: "OAuth2 browser consent flow."
73
+
74
+ google-contacts:
75
+ level: 1
76
+ requires:
77
+ - env: GOOGLE_OAUTH_CREDENTIALS
78
+ type: oauth2
79
+ service: Google Cloud Console
80
+ setup_url: https://console.cloud.google.com/apis/credentials
81
+ setup_time: "15 minutes (shared with other Google services)"
82
+ credentials_path: "~/.contacts-mcp/gcp-oauth.keys.json"
83
+ notes: "Read-only. Shares GCP project with Gmail."
84
+
85
+ google-slides:
86
+ level: 1
87
+ requires:
88
+ - env: GOOGLE_OAUTH_CREDENTIALS
89
+ type: oauth2
90
+ service: Google Cloud Console
91
+ setup_url: https://console.cloud.google.com/apis/credentials
92
+ setup_time: "15 minutes (shared with other Google services)"
93
+ credentials_path: "~/.claude/.credentials/slides-token.json"
94
+ notes: "OAuth2 or Service Account (GOOGLE_SERVICE_ACCOUNT_JSON)."
95
+
96
+ finance-manager:
97
+ level: 1
98
+ requires:
99
+ - env: GOOGLE_OAUTH_CREDENTIALS
100
+ type: oauth2
101
+ service: Google Cloud Console
102
+ setup_url: https://console.cloud.google.com/apis/credentials
103
+ setup_time: "15 minutes (shared with other Google services)"
104
+ notes: "Composes gmail + google-sheets + google-docs + ocr-processor. Set up Google OAuth first."
105
+
106
+ # ============================================================================
107
+ # LEVEL 2: API Keys
108
+ # Individual service signups. Each key takes 2-5 minutes to obtain.
109
+ # ============================================================================
110
+
111
+ fal-ai:
112
+ level: 2
113
+ requires:
114
+ - env: FAL_KEY
115
+ type: api_key
116
+ service: FAL.ai
117
+ setup_url: https://fal.ai/dashboard/keys
118
+ setup_time: "2 minutes"
119
+ notes: "Set in ~/.claude/.env as FAL_KEY=your-key"
120
+
121
+ ultimate-infographics:
122
+ level: 2
123
+ requires:
124
+ - env: FAL_KEY
125
+ type: api_key
126
+ service: FAL.ai
127
+ setup_url: https://fal.ai/dashboard/keys
128
+ setup_time: "2 minutes (shared with fal-ai)"
129
+ notes: "Uses fal-ai for Seedream 4.5 image generation."
130
+
131
+ elevenlabs:
132
+ level: 2
133
+ requires:
134
+ - env: ELEVENLABS_API_KEY
135
+ type: api_key
136
+ service: ElevenLabs
137
+ setup_url: https://elevenlabs.io/app/settings/api-keys
138
+ setup_time: "2 minutes"
139
+ notes: "Set in ~/.claude/.env as ELEVENLABS_API_KEY=sk_xxx"
140
+
141
+ gemini-vision:
142
+ level: 2
143
+ requires:
144
+ - env: GOOGLE_API_KEY
145
+ type: api_key
146
+ service: Google AI Studio
147
+ setup_url: https://aistudio.google.com/apikey
148
+ setup_time: "2 minutes"
149
+ notes: "Shared with ocr-processor. Set in ~/.claude/.env as GOOGLE_API_KEY=AIza..."
150
+
151
+ ocr-processor:
152
+ level: 2
153
+ requires:
154
+ - env: GOOGLE_API_KEY
155
+ type: api_key
156
+ service: Google AI Studio
157
+ setup_url: https://aistudio.google.com/apikey
158
+ setup_time: "2 minutes (shared with gemini-vision)"
159
+ notes: "Primary provider: Gemini. Also supports MISTRAL_API_KEY as alternative."
160
+
161
+ airtable:
162
+ level: 2
163
+ requires:
164
+ - env: AIRTABLE_API_KEY
165
+ type: api_key
166
+ service: Airtable
167
+ setup_url: https://airtable.com/create/tokens
168
+ setup_time: "3 minutes"
169
+ notes: "Personal Access Token (pat prefix). Set as AIRTABLE_API_KEY=patXXX"
170
+
171
+ crm:
172
+ level: 2
173
+ requires:
174
+ - env: AIRTABLE_API_KEY
175
+ type: api_key
176
+ service: Airtable
177
+ setup_url: https://airtable.com/create/tokens
178
+ setup_time: "3 minutes (shared with airtable)"
179
+ notes: "CRM orchestration layer built on Airtable. Same API key."
180
+
181
+ deploy-vercel:
182
+ level: 2
183
+ requires:
184
+ - env: VERCEL_TOKEN
185
+ type: api_key
186
+ service: Vercel
187
+ setup_url: https://vercel.com/account/tokens
188
+ setup_time: "2 minutes"
189
+ notes: "Personal access token. Set in ~/.claude/.env as VERCEL_TOKEN=xxx"
190
+
191
+ retell-ai:
192
+ level: 2
193
+ requires:
194
+ - env: RETELL_API_KEY
195
+ type: api_key
196
+ service: Retell AI
197
+ setup_url: https://www.retellai.com/dashboard
198
+ setup_time: "3 minutes"
199
+ notes: "Set in ~/.claude/.env as RETELL_API_KEY=key_xxx"
200
+
201
+ exa:
202
+ level: 2
203
+ requires:
204
+ - env: EXA_API_KEY
205
+ type: api_key
206
+ service: Exa.ai
207
+ setup_url: https://dashboard.exa.ai/api-keys
208
+ setup_time: "2 minutes"
209
+ notes: "AI-native search API. Set in ~/.claude/.env as EXA_API_KEY=xxx"
210
+
211
+ gumroad:
212
+ level: 2
213
+ requires:
214
+ - env: GUMROAD_ACCESS_TOKEN
215
+ type: api_key
216
+ service: Gumroad
217
+ setup_url: https://app.gumroad.com/settings/advanced#application-form
218
+ setup_time: "3 minutes"
219
+ notes: "OAuth access token. Also supports ~/.gumroad/credentials file."
220
+
221
+ convex:
222
+ level: 2
223
+ requires:
224
+ - env: CONVEX_DEPLOY_KEY
225
+ type: api_key
226
+ service: Convex
227
+ setup_url: https://dashboard.convex.dev
228
+ setup_time: "3 minutes"
229
+ notes: "Deploy key for Convex projects. Set in ~/.claude/.env as CONVEX_DEPLOY_KEY=xxx"
230
+
231
+ youtube-api:
232
+ level: 2
233
+ requires:
234
+ - env: YOUTUBE_API_KEY
235
+ type: api_key
236
+ service: Google Cloud Console
237
+ setup_url: https://console.cloud.google.com/apis/credentials
238
+ setup_time: "3 minutes (shared with GCP project)"
239
+ notes: "YouTube Data API v3. Optional - many operations work without key via yt-dlp."
240
+
241
+ skool-api:
242
+ level: 2
243
+ requires:
244
+ - env: SKOOL_COOKIES
245
+ type: cookie_auth
246
+ service: Skool.com
247
+ setup_url: https://www.skool.com
248
+ setup_time: "5 minutes (browser login)"
249
+ notes: "Cookie-based auth persisted at ~/.skool/cookies.json. No API key - uses browser login."
250
+
251
+ # ============================================================================
252
+ # LEVEL 3: Service Accounts
253
+ # Require KYC verification, usage-based billing, or special configuration.
254
+ # ============================================================================
255
+
256
+ twilio:
257
+ level: 3
258
+ requires:
259
+ - env: TWILIO_ACCOUNT_SID
260
+ type: service_account
261
+ service: Twilio
262
+ setup_url: https://console.twilio.com
263
+ setup_time: "10 minutes"
264
+ - env: TWILIO_AUTH_TOKEN
265
+ type: service_account
266
+ service: Twilio
267
+ setup_url: https://console.twilio.com
268
+ setup_time: "included above"
269
+ - env: TWILIO_PHONE_NUMBER
270
+ type: service_account
271
+ service: Twilio
272
+ setup_url: https://console.twilio.com
273
+ setup_time: "included above"
274
+ notes: "Three env vars required. KYC may be needed for full access."
275
+
276
+ bright-data:
277
+ level: 3
278
+ requires:
279
+ - env: API_TOKEN
280
+ type: service_account
281
+ service: Bright Data
282
+ setup_url: https://brightdata.com/cp/setting
283
+ setup_time: "10 minutes"
284
+ notes: "Usage-based billing. Set in ~/.claude/.env as API_TOKEN=xxx"
285
+
286
+ google-maps:
287
+ level: 3
288
+ requires:
289
+ - env: GOOGLE_MAPS_API_KEY
290
+ type: api_key
291
+ service: Google Cloud Console
292
+ setup_url: https://console.cloud.google.com/apis/credentials
293
+ setup_time: "5 minutes"
294
+ notes: "Requires billing enabled on GCP project. Set as GOOGLE_MAPS_API_KEY=AIza..."
295
+
296
+ weather:
297
+ level: 3
298
+ requires:
299
+ - env: OPENWEATHERMAP_API_KEY
300
+ type: api_key
301
+ service: OpenWeatherMap
302
+ setup_url: https://home.openweathermap.org/api_keys
303
+ setup_time: "3 minutes"
304
+ notes: "Free tier available. One Call 3.0 requires paid subscription."
305
+
306
+ flight-tracker:
307
+ level: 3
308
+ requires:
309
+ - env: AVIATIONSTACK_API_KEY
310
+ type: api_key
311
+ service: AviationStack
312
+ setup_url: https://aviationstack.com/signup/free
313
+ setup_time: "3 minutes"
314
+ notes: "Free tier available with limited requests."
315
+
316
+ claude-gateway:
317
+ level: 3
318
+ requires:
319
+ - env: DISCORD_BOT_TOKEN
320
+ type: api_key
321
+ service: Discord
322
+ setup_url: https://discord.com/developers/applications
323
+ setup_time: "10 minutes"
324
+ - env: DISCORD_CHANNEL_ID
325
+ type: config
326
+ service: Discord
327
+ setup_time: "included above"
328
+ - env: DISCORD_GUILD_ID
329
+ type: config
330
+ service: Discord
331
+ setup_time: "included above"
332
+ notes: "Three env vars required. Create Discord bot application and invite to server."
333
+
334
+ voice-agent-v2:
335
+ level: 3
336
+ requires:
337
+ - env: LIVEKIT_API_KEY
338
+ type: api_key
339
+ service: LiveKit
340
+ setup_url: https://cloud.livekit.io
341
+ setup_time: "5 minutes"
342
+ - env: LIVEKIT_API_SECRET
343
+ type: api_key
344
+ service: LiveKit
345
+ setup_time: "included above"
346
+ - env: LIVEKIT_URL
347
+ type: config
348
+ service: LiveKit
349
+ setup_time: "included above"
350
+ notes: "Three env vars required. LiveKit Cloud or self-hosted."
351
+
352
+ # ============================================================================
353
+ # LEVEL 4: Applications
354
+ # Requires desktop software installed on the user's machine.
355
+ # ============================================================================
356
+
357
+ vault-manager:
358
+ level: 4
359
+ requires:
360
+ - env: OBSIDIAN_INSTALLED
361
+ type: application
362
+ service: Obsidian
363
+ setup_url: https://obsidian.md
364
+ setup_time: "30 minutes (install + vault setup)"
365
+ notes: "Free app. Requires an Obsidian vault configured with PARA structure."
366
+
367
+ life-os:
368
+ level: 4
369
+ requires:
370
+ - env: OBSIDIAN_INSTALLED
371
+ type: application
372
+ service: Obsidian
373
+ setup_url: https://obsidian.md
374
+ setup_time: "30 minutes (install + vault setup)"
375
+ notes: "Requires vault-manager configured first. Life Operating System orchestrator."
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env python3
2
+ """pushREC Skills diagnostic: checks system readiness for Claude Code skills.
3
+
4
+ Standalone Python 3.8+, zero external dependencies.
5
+ Output: JSON to stdout (parseable by Claude Code).
6
+ Exit codes: 0 = all good, 1 = missing critical prereqs, 2 = warnings only.
7
+ """
8
+
9
+ import json
10
+ import os
11
+ import platform
12
+ import subprocess
13
+ import sys
14
+ from datetime import datetime, timezone
15
+ from pathlib import Path
16
+
17
+ VERSION = "1.0.0"
18
+ SKILLS_DIR = Path.home() / ".claude" / "skills"
19
+ CONFIG_PATH = Path.home() / ".pushrec" / "config.json"
20
+ ENV_PATH = Path.home() / ".claude" / ".env"
21
+
22
+ KNOWN_KEY_PREFIXES = [
23
+ "ELEVENLABS_API_KEY",
24
+ "OPENAI_API_KEY",
25
+ "ANTHROPIC_API_KEY",
26
+ "FAL_KEY",
27
+ "GOOGLE_API_KEY",
28
+ "GOOGLE_MAPS_API_KEY",
29
+ "YOUTUBE_API_KEY",
30
+ "RAPIDAPI_KEY",
31
+ "TWILIO_ACCOUNT_SID",
32
+ "TWILIO_AUTH_TOKEN",
33
+ "RETELL_API_KEY",
34
+ "API_TOKEN",
35
+ "AIRTABLE_API_KEY",
36
+ "VERCEL_TOKEN",
37
+ "OPENWEATHERMAP_API_KEY",
38
+ "AVIATIONSTACK_API_KEY",
39
+ "DISCORD_BOT_TOKEN",
40
+ "MISTRAL_API_KEY",
41
+ ]
42
+
43
+
44
+ def run_command(args):
45
+ """Run a shell command and return (success, stdout_stripped)."""
46
+ try:
47
+ result = subprocess.run(
48
+ args,
49
+ capture_output=True,
50
+ text=True,
51
+ timeout=10,
52
+ )
53
+ return result.returncode == 0, result.stdout.strip()
54
+ except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
55
+ return False, ""
56
+
57
+
58
+ def parse_version(version_string):
59
+ """Extract numeric version tuple from a version string like 'v22.1.0' or '2.1.45'."""
60
+ cleaned = version_string.lstrip("v").strip()
61
+ parts = []
62
+ for segment in cleaned.split("."):
63
+ digits = ""
64
+ for char in segment:
65
+ if char.isdigit():
66
+ digits += char
67
+ else:
68
+ break
69
+ if digits:
70
+ parts.append(int(digits))
71
+ return tuple(parts) if parts else (0,)
72
+
73
+
74
+ def version_gte(current, minimum):
75
+ """Check if current version >= minimum version."""
76
+ current_tuple = parse_version(current)
77
+ minimum_tuple = parse_version(minimum)
78
+ return current_tuple >= minimum_tuple
79
+
80
+
81
+ def check_claude_code():
82
+ """Check Claude Code installation and version."""
83
+ success, output = run_command(["claude", "--version"])
84
+ if not success:
85
+ return {"status": "fail", "version": None, "minimum": "2.1.0"}
86
+ version = output.strip()
87
+ if version_gte(version, "2.1.0"):
88
+ return {"status": "pass", "version": version, "minimum": "2.1.0"}
89
+ return {"status": "fail", "version": version, "minimum": "2.1.0"}
90
+
91
+
92
+ def check_node():
93
+ """Check Node.js installation and version."""
94
+ success, output = run_command(["node", "--version"])
95
+ if not success:
96
+ return {"status": "fail", "version": None, "minimum": "20.0.0"}
97
+ version = output.strip()
98
+ if version_gte(version, "20.0.0"):
99
+ return {"status": "pass", "version": version, "minimum": "20.0.0"}
100
+ return {"status": "fail", "version": version, "minimum": "20.0.0"}
101
+
102
+
103
+ def check_npm():
104
+ """Check npm installation."""
105
+ success, output = run_command(["npm", "--version"])
106
+ if not success:
107
+ return {"status": "fail", "version": None}
108
+ return {"status": "pass", "version": output.strip()}
109
+
110
+
111
+ def check_skills_installed():
112
+ """Count installed skills by looking for SKILL.md files."""
113
+ if not SKILLS_DIR.is_dir():
114
+ return {"status": "fail", "count": 0}
115
+ count = 0
116
+ for child in SKILLS_DIR.iterdir():
117
+ if child.is_dir() and (child / "SKILL.md").is_file():
118
+ count += 1
119
+ if count == 0:
120
+ return {"status": "fail", "count": 0}
121
+ return {"status": "pass", "count": count}
122
+
123
+
124
+ def check_license():
125
+ """Check pushREC license status via config.json."""
126
+ if not CONFIG_PATH.is_file():
127
+ return {"status": "fail", "installed_skills": 0}
128
+ try:
129
+ with open(CONFIG_PATH, "r") as f:
130
+ config = json.load(f)
131
+ installed = config.get("installedSkills", {})
132
+ count = len(installed) if isinstance(installed, dict) else 0
133
+ if count > 0:
134
+ return {"status": "pass", "installed_skills": count}
135
+ return {"status": "fail", "installed_skills": 0}
136
+ except (json.JSONDecodeError, OSError):
137
+ return {"status": "fail", "installed_skills": 0}
138
+
139
+
140
+ def check_api_keys():
141
+ """Detect configured API keys from ~/.claude/.env."""
142
+ detected = []
143
+ if not ENV_PATH.is_file():
144
+ return {"status": "info", "detected": 0, "keys": []}
145
+ try:
146
+ with open(ENV_PATH, "r") as f:
147
+ for line in f:
148
+ line = line.strip()
149
+ if not line or line.startswith("#"):
150
+ continue
151
+ for prefix in KNOWN_KEY_PREFIXES:
152
+ if line.startswith(prefix + "="):
153
+ value = line.split("=", 1)[1].strip().strip('"').strip("'")
154
+ if value:
155
+ detected.append(prefix)
156
+ break
157
+ except OSError:
158
+ pass
159
+ return {"status": "info", "detected": len(detected), "keys": detected}
160
+
161
+
162
+ def check_obsidian():
163
+ """Check if Obsidian is installed (platform-specific)."""
164
+ system = platform.system()
165
+ if system == "Darwin":
166
+ installed = Path("/Applications/Obsidian.app").exists()
167
+ elif system == "Linux":
168
+ success, _ = run_command(["which", "obsidian"])
169
+ installed = success
170
+ elif system == "Windows":
171
+ success, _ = run_command(["where", "obsidian"])
172
+ installed = success
173
+ else:
174
+ installed = False
175
+ return {"status": "info", "installed": installed}
176
+
177
+
178
+ def main():
179
+ if os.environ.get("CLAUDE_HEADLESS"):
180
+ sys.exit(0)
181
+
182
+ checks = {
183
+ "claude_code": check_claude_code(),
184
+ "node": check_node(),
185
+ "npm": check_npm(),
186
+ "skills_installed": check_skills_installed(),
187
+ "license": check_license(),
188
+ "api_keys": check_api_keys(),
189
+ "obsidian": check_obsidian(),
190
+ }
191
+
192
+ critical_failures = []
193
+ warnings = []
194
+
195
+ if checks["claude_code"]["status"] == "fail":
196
+ critical_failures.append("Claude Code")
197
+ if checks["node"]["status"] == "fail":
198
+ critical_failures.append("Node.js v20+")
199
+ if checks["npm"]["status"] == "fail":
200
+ critical_failures.append("npm")
201
+ if checks["skills_installed"]["status"] == "fail":
202
+ warnings.append("No skills installed")
203
+ if checks["license"]["status"] == "fail":
204
+ warnings.append("No active license")
205
+
206
+ if critical_failures:
207
+ exit_code = 1
208
+ summary = f"Missing critical prerequisites: {', '.join(critical_failures)}."
209
+ elif warnings:
210
+ exit_code = 2
211
+ summary = f"Warnings: {', '.join(warnings)}."
212
+ else:
213
+ skills_count = checks["skills_installed"].get("count", 0)
214
+ api_count = checks["api_keys"].get("detected", 0)
215
+ summary = f"All systems ready. {skills_count} skills installed, {api_count} API keys detected."
216
+ exit_code = 0
217
+
218
+ report = {
219
+ "version": VERSION,
220
+ "timestamp": datetime.now(timezone.utc).isoformat(),
221
+ "platform": platform.system().lower(),
222
+ "checks": checks,
223
+ "exit_code": exit_code,
224
+ "summary": summary,
225
+ }
226
+
227
+ print(json.dumps(report, indent=2))
228
+ sys.exit(exit_code)
229
+
230
+
231
+ if __name__ == "__main__":
232
+ main()