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.
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/bin/cli.js +138 -0
- package/lib/discover.js +86 -0
- package/lib/install.js +25 -0
- package/lib/ui.js +68 -0
- package/package.json +24 -0
- package/skills/brand-guidelines/SKILL.md +74 -0
- package/skills/competitive-ads-extractor/SKILL.md +293 -0
- package/skills/editor/SKILL.md +212 -0
- package/skills/frontend-design/SKILL.md +80 -0
- package/skills/investor-materials/SKILL.md +146 -0
- package/skills/investor-materials/agents/openai.yaml +7 -0
- package/skills/lead-research-assistant/SKILL.md +121 -0
- package/skills/market-research-reports/SKILL.md +901 -0
- package/skills/market-research-reports/assets/FORMATTING_GUIDE.md +428 -0
- package/skills/market-research-reports/assets/market_report_template.tex +1380 -0
- package/skills/market-research-reports/assets/market_research.sty +564 -0
- package/skills/market-research-reports/references/data_analysis_patterns.md +548 -0
- package/skills/market-research-reports/references/report_structure_guide.md +999 -0
- package/skills/market-research-reports/references/visual_generation_guide.md +1077 -0
- package/skills/market-research-reports/scripts/generate_market_visuals.py +529 -0
- package/skills/memory-management/SKILL.md +120 -0
- package/skills/memory-management/scripts/memory-backup.sh +16 -0
- package/skills/memory-management/scripts/memory-consolidate.sh +11 -0
- package/skills/neobank-lifecycle-sequence-generator/SKILL.md +179 -0
- package/skills/neobank-lifecycle-sequence-generator/references/activation-milestones.md +229 -0
- package/skills/neobank-lifecycle-sequence-generator/references/lifecycle-sequence-library.md +495 -0
- package/skills/neobank-lifecycle-sequence-generator/scripts/generate_sequence.py +1809 -0
- package/skills/neobank-seo-skills/README.md +48 -0
- package/skills/neobank-seo-skills/skills/ai-seo/SKILL.md +66 -0
- package/skills/neobank-seo-skills/skills/aso/SKILL.md +71 -0
- package/skills/neobank-seo-skills/skills/competitor-pages/SKILL.md +30 -0
- package/skills/neobank-seo-skills/skills/programmatic-seo/SKILL.md +54 -0
- package/skills/neobank-seo-skills/skills/schema/SKILL.md +27 -0
- package/skills/neobank-seo-skills/skills/seo-audit/SKILL.md +106 -0
- package/skills/neobank-seo-skills/skills/seo-audit/references/neobank-seo.md +70 -0
- package/skills/org-map/SKILL.md +175 -0
- package/skills/org-map/references/anti-patterns.md +69 -0
- package/skills/org-map/references/example-saas.yaml +465 -0
- package/skills/org-map/references/schema.yaml +164 -0
- package/skills/skill-creator/SKILL.md +357 -0
- package/skills/skill-creator/references/output-patterns.md +82 -0
- package/skills/skill-creator/references/workflows.md +28 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- 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
|
+
});
|
package/lib/discover.js
ADDED
|
@@ -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
|