growgami-skills 0.1.3

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/bin/cli.js +138 -0
  4. package/lib/discover.js +86 -0
  5. package/lib/install.js +25 -0
  6. package/lib/ui.js +68 -0
  7. package/package.json +24 -0
  8. package/skills/brand-guidelines/SKILL.md +74 -0
  9. package/skills/competitive-ads-extractor/SKILL.md +293 -0
  10. package/skills/editor/SKILL.md +212 -0
  11. package/skills/frontend-design/SKILL.md +80 -0
  12. package/skills/investor-materials/SKILL.md +146 -0
  13. package/skills/investor-materials/agents/openai.yaml +7 -0
  14. package/skills/lead-research-assistant/SKILL.md +121 -0
  15. package/skills/market-research-reports/SKILL.md +901 -0
  16. package/skills/market-research-reports/assets/FORMATTING_GUIDE.md +428 -0
  17. package/skills/market-research-reports/assets/market_report_template.tex +1380 -0
  18. package/skills/market-research-reports/assets/market_research.sty +564 -0
  19. package/skills/market-research-reports/references/data_analysis_patterns.md +548 -0
  20. package/skills/market-research-reports/references/report_structure_guide.md +999 -0
  21. package/skills/market-research-reports/references/visual_generation_guide.md +1077 -0
  22. package/skills/market-research-reports/scripts/generate_market_visuals.py +529 -0
  23. package/skills/memory-management/SKILL.md +120 -0
  24. package/skills/memory-management/scripts/memory-backup.sh +16 -0
  25. package/skills/memory-management/scripts/memory-consolidate.sh +11 -0
  26. package/skills/neobank-lifecycle-sequence-generator/SKILL.md +179 -0
  27. package/skills/neobank-lifecycle-sequence-generator/references/activation-milestones.md +229 -0
  28. package/skills/neobank-lifecycle-sequence-generator/references/lifecycle-sequence-library.md +495 -0
  29. package/skills/neobank-lifecycle-sequence-generator/scripts/generate_sequence.py +1809 -0
  30. package/skills/neobank-seo-skills/README.md +48 -0
  31. package/skills/neobank-seo-skills/skills/ai-seo/SKILL.md +66 -0
  32. package/skills/neobank-seo-skills/skills/aso/SKILL.md +71 -0
  33. package/skills/neobank-seo-skills/skills/competitor-pages/SKILL.md +30 -0
  34. package/skills/neobank-seo-skills/skills/programmatic-seo/SKILL.md +54 -0
  35. package/skills/neobank-seo-skills/skills/schema/SKILL.md +27 -0
  36. package/skills/neobank-seo-skills/skills/seo-audit/SKILL.md +106 -0
  37. package/skills/neobank-seo-skills/skills/seo-audit/references/neobank-seo.md +70 -0
  38. package/skills/org-map/SKILL.md +175 -0
  39. package/skills/org-map/references/anti-patterns.md +69 -0
  40. package/skills/org-map/references/example-saas.yaml +465 -0
  41. package/skills/org-map/references/schema.yaml +164 -0
  42. package/skills/skill-creator/SKILL.md +357 -0
  43. package/skills/skill-creator/references/output-patterns.md +82 -0
  44. package/skills/skill-creator/references/workflows.md +28 -0
  45. package/skills/skill-creator/scripts/init_skill.py +303 -0
  46. package/skills/skill-creator/scripts/package_skill.py +110 -0
  47. package/skills/skill-creator/scripts/quick_validate.py +103 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Growgami
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Growgami Skills
2
+
3
+ Claude Code skills built from real operational experience.
4
+
5
+ ## Install
6
+
7
+ **With npx (quickest):**
8
+
9
+ ```bash
10
+ npx growgami-skills --all # everything
11
+ npx growgami-skills --list # list available skills (and bundles)
12
+ npx growgami-skills org-map # specific skill(s)
13
+ npx growgami-skills neobank-seo-skills # a whole bundle (all 6 SEO skills)
14
+ ```
15
+
16
+ Installing a bundle name (e.g. `neobank-seo-skills`) installs every skill inside
17
+ it, each under its own bare name.
18
+
19
+ Installs into `~/.claude/skills/` (override with `CLAUDE_SKILLS_DIR`).
20
+
21
+ **Alternative — git clone + install script:**
22
+
23
+ ```bash
24
+ git clone https://github.com/growgami/skills.git
25
+ cd skills
26
+ ./install.sh # interactive picker
27
+ ./install.sh org-map # specific skill
28
+ ./install.sh --all # everything
29
+ ```
30
+
31
+ **Alternative — git clone + manual copy:**
32
+
33
+ ```bash
34
+ git clone https://github.com/growgami/skills.git
35
+ cp -r skills/skills/org-map ~/.claude/skills/ # one skill
36
+ cp -r skills/skills/* ~/.claude/skills/ # all flat skills
37
+ ```
38
+
39
+ ## Skills
40
+
41
+ | Skill | What it does |
42
+ |---|---|
43
+ | [org-map](skills/org-map/) | Map your org's real operating model into a structured YAML ontology |
44
+ | [brand-guidelines](skills/brand-guidelines/) | Brand color and typography standards |
45
+ | [competitive-ads-extractor](skills/competitive-ads-extractor/) | Competitive ad intelligence extraction |
46
+ | [editor](skills/editor/) | Content editing |
47
+ | [frontend-design](skills/frontend-design/) | Frontend UI/UX design |
48
+ | [investor-materials](skills/investor-materials/) | Investor decks and materials |
49
+ | [lead-research-assistant](skills/lead-research-assistant/) | Lead research and qualification |
50
+ | [market-research-reports](skills/market-research-reports/) | Market research generation |
51
+ | [memory-management](skills/memory-management/) | Claude memory management |
52
+ | [neobank-lifecycle-sequence-generator](skills/neobank-lifecycle-sequence-generator/) | Neobank lifecycle sequences |
53
+ | [skill-creator](skills/skill-creator/) | Scaffold new Claude skills |
54
+ | [neobank-seo-skills](skills/neobank-seo-skills/) | Bundle of 6 nested SEO skills for neobank/fintech: seo-audit, ai-seo, programmatic-seo, competitor-pages, schema, aso |
55
+
56
+ ## Structure
57
+
58
+ ```
59
+ skills/
60
+ skill-name/
61
+ SKILL.md # skill definition (YAML frontmatter + prompt)
62
+ references/ # optional supporting files
63
+ bundle-name/ # a bundle groups related skills
64
+ skills/
65
+ skill-name/
66
+ SKILL.md
67
+ references/
68
+ ```
69
+
70
+ Both flat skills and nested bundle skills install under their bare name (e.g. `seo-audit`). Tooling discovers SKILL.md at both depths.
71
+
72
+ Compatible with vanilla Claude Code (`~/.claude/skills/`) and [skills.ws](https://skills.ws).
package/bin/cli.js ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { discover } = require('../lib/discover');
5
+ const { targetDir, installSkill } = require('../lib/install');
6
+ const { printList, interactivePick } = require('../lib/ui');
7
+
8
+ const dim = '\x1b[2m';
9
+ const green = '\x1b[32m';
10
+ const yellow = '\x1b[33m';
11
+ const red = '\x1b[31m';
12
+ const reset = '\x1b[0m';
13
+
14
+ function printHelp(target) {
15
+ process.stdout.write('Usage: growgami-skills [--all | skill1 skill2 ...]\n');
16
+ process.stdout.write('\n');
17
+ process.stdout.write(' --all Install all skills\n');
18
+ process.stdout.write(' --list List available skills\n');
19
+ process.stdout.write(' skill1 ... Install specific skills\n');
20
+ process.stdout.write(' (no args) Interactive picker\n');
21
+ process.stdout.write('\n');
22
+ process.stdout.write(
23
+ `Target: ${target} (override with CLAUDE_SKILLS_DIR)\n`
24
+ );
25
+ }
26
+
27
+ // Install one resolved skill, printing a "+ name" line on success.
28
+ // Returns 0 on success, 1 on failure.
29
+ function installOne(skill, target) {
30
+ try {
31
+ installSkill(skill.name, skill.srcPath, target);
32
+ process.stdout.write(` ${green}+${reset} ${skill.name}\n`);
33
+ return 0;
34
+ } catch (err) {
35
+ process.stdout.write(
36
+ ` ${red}skip${reset} ${skill.name} (${err.message})\n`
37
+ );
38
+ return 1;
39
+ }
40
+ }
41
+
42
+ // Install a set of bare names, resolving each against discovered skills and
43
+ // bundles. A bundle name installs all of its member skills.
44
+ // Returns a non-zero exit code if any name is missing or collides.
45
+ function installNames(names, skills, bundles, collisions, target) {
46
+ const byName = new Map(skills.map((s) => [s.name, s]));
47
+ const byBundle = new Map(bundles.map((b) => [b.name, b]));
48
+ const collisionNames = new Set(collisions.map((c) => c.name));
49
+ let status = 0;
50
+
51
+ for (const name of names) {
52
+ if (collisionNames.has(name)) {
53
+ process.stdout.write(
54
+ ` ${red}skip${reset} ${name} (name collision)\n`
55
+ );
56
+ status = 1;
57
+ continue;
58
+ }
59
+ const skill = byName.get(name);
60
+ const bundle = byBundle.get(name);
61
+ // Prefer an individual skill over a bundle if both somehow match.
62
+ if (skill) {
63
+ if (bundle) {
64
+ process.stdout.write(
65
+ ` ${yellow}note${reset} ${name} matches both a skill and a bundle; installing the skill\n`
66
+ );
67
+ }
68
+ status = installOne(skill, target) || status;
69
+ continue;
70
+ }
71
+ if (bundle) {
72
+ process.stdout.write(
73
+ ` ${dim}bundle ${bundle.name} -> ${bundle.members.length} skills${reset}\n`
74
+ );
75
+ for (const member of bundle.members) {
76
+ const memberSkill = byName.get(member);
77
+ if (!memberSkill) {
78
+ process.stdout.write(
79
+ ` ${yellow}skip${reset} ${member} (not found)\n`
80
+ );
81
+ status = 1;
82
+ continue;
83
+ }
84
+ status = installOne(memberSkill, target) || status;
85
+ }
86
+ continue;
87
+ }
88
+ process.stdout.write(` ${yellow}skip${reset} ${name} (not found)\n`);
89
+ status = 1;
90
+ }
91
+ return status;
92
+ }
93
+
94
+ async function main() {
95
+ const args = process.argv.slice(2);
96
+ const target = targetDir();
97
+ const { skills, bundles, collisions } = discover();
98
+
99
+ if (args[0] === '--help' || args[0] === '-h') {
100
+ printHelp(target);
101
+ return 0;
102
+ }
103
+
104
+ if (args[0] === '--list') {
105
+ for (const c of collisions) {
106
+ process.stderr.write(
107
+ ` ${red}skip${reset} ${c.name} (name collision)\n`
108
+ );
109
+ }
110
+ printList(skills, bundles);
111
+ return 0;
112
+ }
113
+
114
+ process.stdout.write(`\n ${dim}Installing to ${target}${reset}\n\n`);
115
+
116
+ let names;
117
+ if (args[0] === '--all') {
118
+ names = skills.map((s) => s.name);
119
+ } else if (args.length > 0) {
120
+ names = args;
121
+ } else if (process.stdin.isTTY) {
122
+ names = await interactivePick(skills, bundles);
123
+ } else {
124
+ printHelp(target);
125
+ return 0;
126
+ }
127
+
128
+ const status = installNames(names, skills, bundles, collisions, target);
129
+ process.stdout.write('\n');
130
+ return status;
131
+ }
132
+
133
+ main()
134
+ .then((code) => process.exit(code))
135
+ .catch((err) => {
136
+ process.stderr.write(`${err && err.stack ? err.stack : err}\n`);
137
+ process.exit(1);
138
+ });
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ // Root of this package (parent of lib/).
7
+ const PKG_ROOT = path.join(__dirname, '..');
8
+ const SKILLS_DIR = path.join(PKG_ROOT, 'skills');
9
+
10
+ function isSkillDir(dir) {
11
+ return fs.existsSync(path.join(dir, 'SKILL.md'));
12
+ }
13
+
14
+ function listSubdirs(dir) {
15
+ if (!fs.existsSync(dir)) return [];
16
+ return fs
17
+ .readdirSync(dir, { withFileTypes: true })
18
+ .filter((e) => e.isDirectory())
19
+ .map((e) => path.join(dir, e.name));
20
+ }
21
+
22
+ /**
23
+ * Walk skills/ for skills at two depths:
24
+ * - Flat: skills/<name>/SKILL.md
25
+ * - Nested: skills/<bundle>/skills/<name>/SKILL.md
26
+ *
27
+ * A directory counts as a skill only if it contains SKILL.md. A bundle's own
28
+ * top-level README.md (with no SKILL.md) is never treated as a skill.
29
+ *
30
+ * A bundle = a directory directly under skills/ with NO SKILL.md of its own
31
+ * that contains a skills/ subdirectory holding one or more <name>/SKILL.md.
32
+ * Its members are those nested skills.
33
+ *
34
+ * Returns an object:
35
+ * { skills: Array<{ name, srcPath }>,
36
+ * bundles: Array<{ name, members: [skillName, ...] }>,
37
+ * collisions: Array<{ name, paths }> }
38
+ * `skills` contains each bare name once (first source wins); any bare name
39
+ * resolving to more than one source is reported in `collisions`.
40
+ */
41
+ function discover() {
42
+ const found = []; // { name, srcPath }
43
+ const bundles = []; // { name, members: [skillName, ...] }
44
+
45
+ for (const top of listSubdirs(SKILLS_DIR)) {
46
+ if (isSkillDir(top)) {
47
+ found.push({ name: path.basename(top), srcPath: top });
48
+ continue;
49
+ }
50
+ const nestedSkillsDir = path.join(top, 'skills');
51
+ if (fs.existsSync(nestedSkillsDir)) {
52
+ const members = [];
53
+ for (const nested of listSubdirs(nestedSkillsDir)) {
54
+ if (isSkillDir(nested)) {
55
+ const memberName = path.basename(nested);
56
+ found.push({ name: memberName, srcPath: nested });
57
+ members.push(memberName);
58
+ }
59
+ }
60
+ if (members.length > 0) {
61
+ bundles.push({ name: path.basename(top), members });
62
+ }
63
+ }
64
+ }
65
+
66
+ const byName = new Map();
67
+ for (const item of found) {
68
+ if (!byName.has(item.name)) byName.set(item.name, []);
69
+ byName.get(item.name).push(item.srcPath);
70
+ }
71
+
72
+ const skills = [];
73
+ const collisions = [];
74
+ for (const [name, paths] of byName) {
75
+ if (paths.length > 1) {
76
+ collisions.push({ name, paths });
77
+ }
78
+ skills.push({ name, srcPath: paths[0] });
79
+ }
80
+
81
+ skills.sort((a, b) => a.name.localeCompare(b.name));
82
+ bundles.sort((a, b) => a.name.localeCompare(b.name));
83
+ return { skills, bundles, collisions };
84
+ }
85
+
86
+ module.exports = { discover, SKILLS_DIR };
package/lib/install.js ADDED
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+
7
+ function targetDir() {
8
+ return (
9
+ process.env.CLAUDE_SKILLS_DIR ||
10
+ path.join(os.homedir(), '.claude', 'skills')
11
+ );
12
+ }
13
+
14
+ /**
15
+ * Copy a single skill's entire source directory (including references/) into
16
+ * <target>/<name>/ recursively. Replaces any existing install of that name.
17
+ */
18
+ function installSkill(name, srcPath, target) {
19
+ const dest = path.join(target, name);
20
+ fs.rmSync(dest, { recursive: true, force: true });
21
+ fs.mkdirSync(dest, { recursive: true });
22
+ fs.cpSync(srcPath, dest, { recursive: true });
23
+ }
24
+
25
+ module.exports = { targetDir, installSkill };
package/lib/ui.js ADDED
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ const readline = require('readline');
4
+
5
+ function printList(skills, bundles) {
6
+ for (const s of skills) {
7
+ process.stdout.write(s.name + '\n');
8
+ }
9
+ if (bundles && bundles.length > 0) {
10
+ process.stdout.write('\nBundles (install the whole set by name):\n');
11
+ for (const b of bundles) {
12
+ process.stdout.write(` ${b.name} (${b.members.join(', ')})\n`);
13
+ }
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Interactive numbered picker. Resolves with an array of selected bare names
19
+ * (raw strings; the caller validates them against discovered skills).
20
+ * Accepts comma-separated numbers and/or names, or "all".
21
+ */
22
+ function interactivePick(skills, bundles) {
23
+ return new Promise((resolve) => {
24
+ process.stdout.write(' Available skills:\n\n');
25
+ skills.forEach((s, i) => {
26
+ const n = String(i + 1).padStart(2, ' ');
27
+ process.stdout.write(` ${n}) ${s.name}\n`);
28
+ });
29
+ if (bundles && bundles.length > 0) {
30
+ process.stdout.write('\n Bundles (install the whole set by name):\n');
31
+ for (const b of bundles) {
32
+ process.stdout.write(` ${b.name} (${b.members.join(', ')})\n`);
33
+ }
34
+ }
35
+ process.stdout.write('\n');
36
+
37
+ const rl = readline.createInterface({
38
+ input: process.stdin,
39
+ output: process.stdout,
40
+ });
41
+
42
+ rl.question(
43
+ " Enter numbers or names (comma-separated), or 'all': ",
44
+ (answer) => {
45
+ rl.close();
46
+ const choice = answer.trim();
47
+ if (choice === 'all') {
48
+ resolve(skills.map((s) => s.name));
49
+ return;
50
+ }
51
+ const picks = choice
52
+ .split(',')
53
+ .map((p) => p.trim())
54
+ .filter((p) => p.length > 0)
55
+ .map((p) => {
56
+ if (/^[0-9]+$/.test(p)) {
57
+ const idx = parseInt(p, 10) - 1;
58
+ if (idx >= 0 && idx < skills.length) return skills[idx].name;
59
+ }
60
+ return p;
61
+ });
62
+ resolve(picks);
63
+ }
64
+ );
65
+ });
66
+ }
67
+
68
+ module.exports = { printList, interactivePick };
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "growgami-skills",
3
+ "version": "0.1.3",
4
+ "description": "Claude Code skills built from real operational experience, installable via npx.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "github:growgami/skills"
9
+ },
10
+ "bin": {
11
+ "growgami-skills": "bin/cli.js"
12
+ },
13
+ "files": [
14
+ "bin/",
15
+ "lib/",
16
+ "skills/",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "type": "commonjs"
24
+ }
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: brand-guidelines
3
+ description: Applies Growgami's official brand colors and typography to any artifact that may benefit from having Growgami's look-and-feel. Use when brand colors or style guidelines, visual formatting, or company design standards apply.
4
+ ---
5
+
6
+ # Growgami Brand Styling
7
+
8
+ ## Overview
9
+
10
+ Use this skill to apply Growgami's official brand identity to any visual or written artifact.
11
+
12
+ **Keywords**: branding, corporate identity, visual identity, styling, brand colors, typography, Growgami brand, visual formatting, visual design
13
+
14
+ ## Brand Guidelines
15
+
16
+ ### Colors
17
+
18
+ Growgami uses a monochromatic grayscale palette with no accent colors.
19
+
20
+ **Dark Scale (Near Black):**
21
+
22
+ | Name | Hex | Use |
23
+ |------------|-----------|------------------------------|
24
+ | Near Black | `#080808` | Primary backgrounds, darkest |
25
+ | | `#141414` | Dark surfaces |
26
+ | | `#1F1F1F` | Elevated dark surfaces |
27
+ | | `#292929` | Borders on dark |
28
+ | | `#333333` | Subtle dark elements |
29
+
30
+ **Light Scale (White Smoke):**
31
+
32
+ | Name | Hex | Use |
33
+ |-------------|-----------|-------------------------------|
34
+ | | `#D6D6D6` | Subtle borders on light |
35
+ | | `#E0E0E0` | Muted backgrounds |
36
+ | | `#EBEBEB` | Light surfaces |
37
+ | | `#F5F5F5` | Near-white backgrounds |
38
+ | White Smoke | `#F9F9F9` | Primary light background |
39
+
40
+ ### Typography
41
+
42
+ - **Headlines**: Geist Mono, Medium weight
43
+ - **Sub Heads**: Geist Mono, Regular weight
44
+ - **Fallback**: Monospace system font
45
+
46
+ ## Application Rules
47
+
48
+ ### Text on Dark Backgrounds
49
+ - Use `#F9F9F9` or `#F5F5F5` for primary text
50
+ - Use `#D6D6D6` or `#E0E0E0` for secondary/muted text
51
+
52
+ ### Text on Light Backgrounds
53
+ - Use `#080808` or `#141414` for primary text
54
+ - Use `#292929` or `#333333` for secondary/muted text
55
+
56
+ ### Contrast & Accessibility
57
+ - Primary pairings: `#080808` on `#F9F9F9` or `#F9F9F9` on `#080808`
58
+ - Avoid mid-gray on mid-gray — maintain strong contrast at all times
59
+
60
+ ### Font Application
61
+ - Apply Geist Mono Medium to all headings
62
+ - Apply Geist Mono Regular to body and sub-headings
63
+ - Do not mix other font families — Growgami's identity is defined by Geist Mono exclusively
64
+
65
+ ## Technical Details
66
+
67
+ ### Color Application
68
+ - Use hex values directly for web/CSS
69
+ - For print, refer to CMYK equivalents from the Graphic Standard Manual
70
+ - White Smoke (`#F9F9F9`) CMYK: 00/00/00/2.35
71
+
72
+ ### Font Management
73
+ - Geist Mono is available via [Google Fonts](https://fonts.google.com/specimen/Geist+Mono) or as a system install
74
+ - If unavailable, fall back to the system monospace font