opengstack 0.13.4 → 0.13.5
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 +43 -64
- package/bin/opengstack.js +160 -0
- package/package.json +7 -2
- package/scripts/filter_skills.py +91 -67
- package/scripts/install-skills.js +65 -0
package/README.md
CHANGED
|
@@ -1,80 +1,59 @@
|
|
|
1
1
|
# OpenGStack
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Forked from [garrytan/gstack](https://github.com/garrytan/gstack) with telemetry and YC references removed.
|
|
6
|
-
|
|
7
|
-
## What is this?
|
|
8
|
-
|
|
9
|
-
Skills that give AI agents structured roles for software development. Each skill is a specialist: CEO reviewer, eng manager, designer, QA lead, release engineer, debugger, and more.
|
|
10
|
-
|
|
11
|
-
## Available Skills
|
|
12
|
-
|
|
13
|
-
| Skill | What it does |
|
|
14
|
-
|-------|--------------|
|
|
15
|
-
| `/office-hours` | Brainstorm your product idea before you write code. |
|
|
16
|
-
| `/plan-ceo-review` | CEO-level review: find the 10-star product in the request. |
|
|
17
|
-
| `/plan-eng-review` | Lock architecture, data flow, edge cases, and tests. |
|
|
18
|
-
| `/plan-design-review` | Rate each design dimension 0-10, explain what a 10 looks like. |
|
|
19
|
-
| `/design-consultation` | Build a complete design system from scratch. |
|
|
20
|
-
| `/design-review` | Design audit + fix loop with atomic commits. |
|
|
21
|
-
| `/review` | Pre-landing PR review. Finds bugs that pass CI but break in prod. |
|
|
22
|
-
| `/investigate` | Systematic root-cause debugging. |
|
|
23
|
-
| `/qa` | Open a real browser, find bugs, fix them, re-verify. |
|
|
24
|
-
| `/qa-only` | Same as /qa but report only — no code changes. |
|
|
25
|
-
| `/ship` | Run tests, review, push, open PR. One command. |
|
|
26
|
-
| `/land-and-deploy` | Merge PR, deploy, verify health. |
|
|
27
|
-
| `/document-release` | Update all docs to match what you just shipped. |
|
|
28
|
-
| `/retro` | Weekly retro with per-person breakdowns and shipping streaks. |
|
|
29
|
-
| `/browse` | Headless browser — real Chromium, real clicks, ~100ms/command. |
|
|
30
|
-
| `/setup-browser-cookies` | Import cookies from your real browser for authenticated testing. |
|
|
31
|
-
| `/careful` | Warn before destructive commands (rm -rf, DROP TABLE, force-push). |
|
|
32
|
-
| `/freeze` | Lock edits to one directory. Hard block, not just a warning. |
|
|
33
|
-
| `/guard` | Activate both careful + freeze at once. |
|
|
34
|
-
| `/unfreeze` | Remove directory edit restrictions. |
|
|
35
|
-
| `/autoplan` | Run all reviews sequentially with auto-decisions. |
|
|
36
|
-
| `/codex` | OpenAI Codex CLI wrapper for code review. |
|
|
37
|
-
| `/canary` | Post-deploy monitoring. |
|
|
38
|
-
| `/benchmark` | Performance regression detection. |
|
|
39
|
-
| `/cso` | Security audit. |
|
|
3
|
+
AI engineering workflow skills for Claude/opencode. No telemetry. No tracking.
|
|
40
4
|
|
|
41
5
|
## Installation
|
|
42
6
|
|
|
43
|
-
### For Claude Code / OpenCode
|
|
44
|
-
|
|
45
7
|
```bash
|
|
46
|
-
|
|
47
|
-
git clone https://github.com/Ambisphaeric/opengstack.git ~/.claude/skills/opengstack
|
|
8
|
+
npm install -g opengstack
|
|
48
9
|
```
|
|
49
10
|
|
|
50
|
-
|
|
11
|
+
Skills auto-install to `~/.claude/skills/` via symlink.
|
|
51
12
|
|
|
52
|
-
|
|
53
|
-
cd ~/.claude/skills/opengstack/browse
|
|
54
|
-
./setup
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Requires `bun`: `curl -fsSL https://bun.sh/install | bash`
|
|
58
|
-
|
|
59
|
-
## No Telemetry
|
|
60
|
-
|
|
61
|
-
This fork removes all telemetry, analytics, and tracking from the original gstack. Your usage data stays on your machine.
|
|
62
|
-
|
|
63
|
-
## Syncing from Upstream
|
|
64
|
-
|
|
65
|
-
This repo auto-syncs daily from `garrytan/gstack` via GitHub Actions. Filters are applied to remove telemetry and YC references.
|
|
66
|
-
|
|
67
|
-
To sync manually:
|
|
13
|
+
## CLI
|
|
68
14
|
|
|
69
15
|
```bash
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
./scripts/filter_skills.py .
|
|
74
|
-
./scripts/cleanup.py .
|
|
75
|
-
git commit -m "chore: sync from upstream"
|
|
16
|
+
opengstack --help # Show all commands
|
|
17
|
+
opengstack --list # List available skills
|
|
18
|
+
opengstack --install # Re-install skills (if needed)
|
|
76
19
|
```
|
|
77
20
|
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
In opencode/Claude, type any skill name with `/`:
|
|
24
|
+
|
|
25
|
+
| Command | What it does |
|
|
26
|
+
|---------|--------------|
|
|
27
|
+
| `/office-hours` | Brainstorm before building |
|
|
28
|
+
| `/plan-ceo-review` | CEO-level strategic review |
|
|
29
|
+
| `/plan-eng-review` | Lock architecture & edge cases |
|
|
30
|
+
| `/plan-design-review` | Rate design decisions 0-10 |
|
|
31
|
+
| `/design-consultation` | Build a design system from scratch |
|
|
32
|
+
| `/design-review` | Design audit + fix loop |
|
|
33
|
+
| `/review` | Pre-landing PR review |
|
|
34
|
+
| `/investigate` | Root-cause debugging |
|
|
35
|
+
| `/qa` | Open browser, find bugs, fix, verify |
|
|
36
|
+
| `/qa-only` | QA report only — no code changes |
|
|
37
|
+
| `/ship` | Run tests, review, push, open PR |
|
|
38
|
+
| `/land-and-deploy` | Merge PR, deploy, verify health |
|
|
39
|
+
| `/document-release` | Update docs post-ship |
|
|
40
|
+
| `/retro` | Weekly engineering retrospective |
|
|
41
|
+
| `/browse` | Headless browser (real Chromium) |
|
|
42
|
+
| `/setup-browser-cookies` | Import cookies for auth testing |
|
|
43
|
+
| `/careful` | Warn before destructive ops |
|
|
44
|
+
| `/freeze` | Lock edits to one directory |
|
|
45
|
+
| `/guard` | Activate careful + freeze |
|
|
46
|
+
| `/unfreeze` | Remove directory restrictions |
|
|
47
|
+
| `/autoplan` | Run all reviews auto-decisioned |
|
|
48
|
+
| `/codex` | OpenAI Codex CLI wrapper |
|
|
49
|
+
| `/canary` | Post-deploy monitoring |
|
|
50
|
+
| `/benchmark` | Performance regression detection |
|
|
51
|
+
| `/cso` | Security audit |
|
|
52
|
+
|
|
53
|
+
## Why OpenGStack?
|
|
54
|
+
|
|
55
|
+
Forked from [garrytan/gstack](https://github.com/garrytan/gstack) with telemetry and vendor references removed. Your usage stays local.
|
|
56
|
+
|
|
78
57
|
## License
|
|
79
58
|
|
|
80
59
|
MIT
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OpenGStack CLI - Run skills directly from command line
|
|
5
|
+
* Usage: opengstack <skill-name> [args...]
|
|
6
|
+
* Example: opengstack ship
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const PKG_DIR = path.dirname(__dirname);
|
|
13
|
+
const SKILLS_DIR = path.join(process.env.HOME || process.env.USERPROFILE, '.claude', 'skills');
|
|
14
|
+
|
|
15
|
+
// Map of skill names to their directories
|
|
16
|
+
const skillMap = {
|
|
17
|
+
'ship': 'ship',
|
|
18
|
+
'qa': 'qa',
|
|
19
|
+
'qa-only': 'qa-only',
|
|
20
|
+
'review': 'review',
|
|
21
|
+
'investigate': 'investigate',
|
|
22
|
+
'design-review': 'design-review',
|
|
23
|
+
'plan-ceo-review': 'plan-ceo-review',
|
|
24
|
+
'plan-eng-review': 'plan-eng-review',
|
|
25
|
+
'plan-design-review': 'plan-design-review',
|
|
26
|
+
'office-hours': 'office-hours',
|
|
27
|
+
'design-consultation': 'design-consultation',
|
|
28
|
+
'design-shotgun': 'design-shotgun',
|
|
29
|
+
'document-release': 'document-release',
|
|
30
|
+
'retro': 'retro',
|
|
31
|
+
'browse': 'browse',
|
|
32
|
+
'setup-browser-cookies': 'setup-browser-cookies',
|
|
33
|
+
'setup-deploy': 'setup-deploy',
|
|
34
|
+
'careful': 'careful',
|
|
35
|
+
'freeze': 'freeze',
|
|
36
|
+
'guard': 'guard',
|
|
37
|
+
'unfreeze': 'unfreeze',
|
|
38
|
+
'autoplan': 'autoplan',
|
|
39
|
+
'codex': 'codex',
|
|
40
|
+
'canary': 'canary',
|
|
41
|
+
'benchmark': 'benchmark',
|
|
42
|
+
'cso': 'cso',
|
|
43
|
+
'connect-chrome': 'connect-chrome',
|
|
44
|
+
'land-and-deploy': 'land-and-deploy',
|
|
45
|
+
'gstack-upgrade': 'gstack-upgrade'
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
function showHelp() {
|
|
49
|
+
console.log(`
|
|
50
|
+
OpenGStack - AI Engineering Workflow Skills
|
|
51
|
+
|
|
52
|
+
Usage: opengstack <command> [options]
|
|
53
|
+
|
|
54
|
+
Commands:
|
|
55
|
+
ship Ship workflow: test, review, push, PR
|
|
56
|
+
qa Open browser, find bugs, fix, verify
|
|
57
|
+
qa-only QA report only — no code changes
|
|
58
|
+
review Pre-landing PR review
|
|
59
|
+
investigate Root-cause debugging
|
|
60
|
+
design-review Design audit + fix loop
|
|
61
|
+
plan-ceo-review CEO-level strategic review
|
|
62
|
+
plan-eng-review Lock architecture & edge cases
|
|
63
|
+
plan-design-review Rate design decisions 0-10
|
|
64
|
+
office-hours Brainstorm before building
|
|
65
|
+
design-consultation Build a design system from scratch
|
|
66
|
+
design-shotgun Generate multiple AI design variants
|
|
67
|
+
document-release Update docs post-ship
|
|
68
|
+
retro Weekly engineering retrospective
|
|
69
|
+
browse Headless browser (real Chromium)
|
|
70
|
+
setup-browser-cookies Import cookies for auth testing
|
|
71
|
+
setup-deploy Configure deployment settings
|
|
72
|
+
careful Warn before destructive ops
|
|
73
|
+
freeze Lock edits to one directory
|
|
74
|
+
guard Activate careful + freeze
|
|
75
|
+
unfreeze Remove directory restrictions
|
|
76
|
+
autoplan Run all reviews auto-decisioned
|
|
77
|
+
codex OpenAI Codex CLI wrapper
|
|
78
|
+
canary Post-deploy monitoring
|
|
79
|
+
benchmark Performance regression detection
|
|
80
|
+
cso Security audit
|
|
81
|
+
connect-chrome Launch Chrome with Side Panel
|
|
82
|
+
land-and-deploy Merge PR, deploy, verify health
|
|
83
|
+
gstack-upgrade Upgrade gstack to latest version
|
|
84
|
+
|
|
85
|
+
Options:
|
|
86
|
+
-h, --help Show this help message
|
|
87
|
+
-l, --list List all available skills
|
|
88
|
+
-i, --install Install skills to ~/.claude/skills/
|
|
89
|
+
|
|
90
|
+
In opencode/Claude, use /slash commands:
|
|
91
|
+
/ship, /qa, /review, etc.
|
|
92
|
+
`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function listSkills() {
|
|
96
|
+
console.log('\nAvailable skills:\n');
|
|
97
|
+
Object.entries(skillMap).forEach(([cmd, dir]) => {
|
|
98
|
+
const skillPath = path.join(SKILLS_DIR, dir, 'SKILL.md');
|
|
99
|
+
let description = '';
|
|
100
|
+
if (fs.existsSync(skillPath)) {
|
|
101
|
+
const content = fs.readFileSync(skillPath, 'utf8');
|
|
102
|
+
const match = content.match(/description:\s*\|?\s*([^\n]+)/);
|
|
103
|
+
if (match) {
|
|
104
|
+
description = match[1].trim().substring(0, 60);
|
|
105
|
+
if (description.length === 60) description += '...';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
console.log(` ${cmd.padEnd(20)} ${description}`);
|
|
109
|
+
});
|
|
110
|
+
console.log('');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function installSkills() {
|
|
114
|
+
console.log('Installing skills...');
|
|
115
|
+
require('../scripts/install-skills.js');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function main() {
|
|
119
|
+
const args = process.argv.slice(2);
|
|
120
|
+
const command = args[0];
|
|
121
|
+
|
|
122
|
+
if (!command || command === '-h' || command === '--help') {
|
|
123
|
+
showHelp();
|
|
124
|
+
process.exit(0);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (command === '-l' || command === '--list') {
|
|
128
|
+
listSkills();
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (command === '-i' || command === '--install') {
|
|
133
|
+
installSkills();
|
|
134
|
+
process.exit(0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const skillDir = skillMap[command];
|
|
138
|
+
if (!skillDir) {
|
|
139
|
+
console.error(`Unknown command: ${command}`);
|
|
140
|
+
console.error('Run "opengstack --help" for available commands');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check if skill is installed
|
|
145
|
+
const skillPath = path.join(SKILLS_DIR, skillDir, 'SKILL.md');
|
|
146
|
+
if (!fs.existsSync(skillPath)) {
|
|
147
|
+
console.error(`Skill "${command}" not installed.`);
|
|
148
|
+
console.error('Run: opengstack --install');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Print instructions for using the skill
|
|
153
|
+
console.log(`\n🎯 Skill: ${command}`);
|
|
154
|
+
console.log(`📍 Location: ${skillPath}`);
|
|
155
|
+
console.log(`\nTo use this skill in opencode/Claude, type:`);
|
|
156
|
+
console.log(` /${command}\n`);
|
|
157
|
+
console.log('The skill instructions will be loaded automatically.\n');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opengstack",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "AI Engineering Workflow - SKILL.md files that give AI agents structured roles for software development. Forked from gstack but scrubbed clean of all the YC/Garry Tan cruft and telemetry.",
|
|
6
6
|
"keywords": [
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
"author": "Ambisphaeric",
|
|
25
25
|
"type": "commonjs",
|
|
26
26
|
"main": "SKILL.md",
|
|
27
|
+
"bin": {
|
|
28
|
+
"opengstack": "./bin/opengstack.js"
|
|
29
|
+
},
|
|
27
30
|
"directories": {
|
|
28
31
|
"doc": "docs"
|
|
29
32
|
},
|
|
@@ -35,9 +38,11 @@
|
|
|
35
38
|
"**/SKILL.md",
|
|
36
39
|
"**/SKILL.md.tmpl",
|
|
37
40
|
"scripts/",
|
|
38
|
-
"docs/"
|
|
41
|
+
"docs/",
|
|
42
|
+
"bin/"
|
|
39
43
|
],
|
|
40
44
|
"scripts": {
|
|
45
|
+
"postinstall": "node scripts/install-skills.js",
|
|
41
46
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
42
47
|
}
|
|
43
48
|
}
|
package/scripts/filter_skills.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
opengstack filter script
|
|
4
|
-
Removes telemetry, YC references,
|
|
3
|
+
opengstack filter script - NUKE MODE
|
|
4
|
+
Removes ALL telemetry, YC references, Garry Tan content, and gstack branding
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import re
|
|
@@ -10,95 +10,119 @@ from pathlib import Path
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def filter_skill_content(content: str) -> str:
|
|
13
|
-
"""
|
|
13
|
+
"""NUKE all gstack slop from skills"""
|
|
14
14
|
|
|
15
|
-
# Remove telemetry preamble
|
|
16
|
-
|
|
17
|
-
content = re.sub(
|
|
15
|
+
# STEP 1: Remove entire telemetry preamble blocks
|
|
16
|
+
# Match from ```bash to next ```, containing telemetry variables
|
|
17
|
+
content = re.sub(r"```bash\s*\n_UPD=.*?```\s*\n", "", content, flags=re.DOTALL)
|
|
18
18
|
|
|
19
|
-
# Remove
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
# Remove any remaining bash blocks with .gstack/ references
|
|
20
|
+
content = re.sub(
|
|
21
|
+
r"```bash\s*\n.*?\.gstack/.*?(?=```)", "", content, flags=re.DOTALL
|
|
22
|
+
)
|
|
22
23
|
|
|
23
|
-
# Remove
|
|
24
|
-
|
|
25
|
-
r"If `TEL_PROMPTED` is
|
|
24
|
+
# STEP 2: Remove entire sections about telemetry/config
|
|
25
|
+
content = re.sub(
|
|
26
|
+
r"If `TEL_PROMPTED` is.*?touch ~/.gstack/\.telemetry-prompted.*?```\s*\n?",
|
|
27
|
+
"",
|
|
28
|
+
content,
|
|
29
|
+
flags=re.DOTALL,
|
|
26
30
|
)
|
|
27
|
-
content = re.sub(tel_pattern, "", content, flags=re.DOTALL)
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
content = re.sub(
|
|
33
|
+
r"If `PROACTIVE_PROMPTED` is.*?touch ~/.gstack/\.proactive-prompted.*?```\s*\n?",
|
|
34
|
+
"",
|
|
35
|
+
content,
|
|
36
|
+
flags=re.DOTALL,
|
|
37
|
+
)
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
content = re.sub(
|
|
40
|
+
r"If `LAKE_INTRO` is.*?touch ~/.gstack/\.completeness-intro-seen.*?```\s*\n?",
|
|
41
|
+
"",
|
|
42
|
+
content,
|
|
43
|
+
flags=re.DOTALL,
|
|
44
|
+
)
|
|
36
45
|
|
|
37
|
-
# Remove
|
|
38
|
-
|
|
39
|
-
r"##
|
|
46
|
+
# STEP 3: Remove ## Contributor Mode section
|
|
47
|
+
content = re.sub(
|
|
48
|
+
r"## Contributor Mode.*?## (Voice|Telemetry|Completion)",
|
|
49
|
+
r"## \1",
|
|
50
|
+
content,
|
|
51
|
+
flags=re.DOTALL,
|
|
40
52
|
)
|
|
41
|
-
content = re.sub(tel_trailer_pattern, "", content, flags=re.DOTALL)
|
|
42
53
|
|
|
43
|
-
# Remove
|
|
44
|
-
content = re.sub(r"
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
# STEP 4: Remove ## Telemetry section entirely
|
|
55
|
+
content = re.sub(r"## Telemetry.*?```.*?```\s*\n", "", content, flags=re.DOTALL)
|
|
56
|
+
|
|
57
|
+
# STEP 5: NUKE all gstack binary references
|
|
58
|
+
content = re.sub(r"`?~/.claude/skills/gstack/bin/[^\s`]+`?", "", content)
|
|
47
59
|
|
|
48
|
-
#
|
|
60
|
+
# STEP 6: Replace gstack paths with opengstack
|
|
49
61
|
content = re.sub(
|
|
50
62
|
r"~/.claude/skills/gstack/", "~/.claude/skills/opengstack/", content
|
|
51
63
|
)
|
|
52
64
|
|
|
53
|
-
#
|
|
54
|
-
|
|
55
|
-
r"> A personal note from me, Garry Tan, the creator of GStack:.*?(?=\n\n|\n>)"
|
|
56
|
-
)
|
|
57
|
-
content = re.sub(garry_note_pattern, "", content, flags=re.DOTALL)
|
|
58
|
-
|
|
59
|
-
# Remove YC apply links with ref tracking
|
|
60
|
-
content = re.sub(r"ycombinator\.com/apply\?ref=gstack.*", "", content)
|
|
65
|
+
# STEP 7: Remove all .gstack/ directory references
|
|
66
|
+
content = re.sub(r"~?/?\.gstack/[^\s`\n]*", "", content)
|
|
61
67
|
|
|
62
|
-
# Remove
|
|
63
|
-
content = re.sub(r"
|
|
68
|
+
# STEP 8: Remove mkdir/touch commands for .gstack
|
|
69
|
+
content = re.sub(r"mkdir -p[^\n]*\.gstack[^\n]*\n?", "", content)
|
|
70
|
+
content = re.sub(r"touch[^\n]*\.gstack[^\n]*\n?", "", content)
|
|
64
71
|
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
# STEP 9: NUKE Garry Tan completely
|
|
73
|
+
content = re.sub(
|
|
74
|
+
r"> A personal note from me, Garry Tan.*?(?=\n\n|## )",
|
|
75
|
+
"",
|
|
76
|
+
content,
|
|
77
|
+
flags=re.DOTALL,
|
|
78
|
+
)
|
|
79
|
+
content = re.sub(r"shaped by Garry Tan\'s[^.]*\.", "", content)
|
|
80
|
+
content = re.sub(r"Garry Tan", "", content)
|
|
81
|
+
content = re.sub(r"YC partner energy for strategy[^.]*\.", "", content)
|
|
72
82
|
|
|
73
|
-
#
|
|
83
|
+
# STEP 10: NUKE YC references
|
|
74
84
|
content = re.sub(r"YC Office Hours", "Office Hours", content)
|
|
85
|
+
content = re.sub(r"ycombinator\.com/apply\?ref=[^\s]*", "", content)
|
|
86
|
+
content = re.sub(r"consider applying to YC[^.]*\.", "", content)
|
|
75
87
|
|
|
76
|
-
#
|
|
77
|
-
content = re.sub(r"
|
|
78
|
-
content = re.sub(r"
|
|
79
|
-
content = re.sub(r"Gar[r]?y.*Tan", "", content)
|
|
88
|
+
# STEP 11: NUKE garryslist
|
|
89
|
+
content = re.sub(r"https?://garryslist\.org[^\s]*", "", content)
|
|
90
|
+
content = re.sub(r"Boil the (Lake|Ocean)[^.]*\.?", "", content)
|
|
80
91
|
|
|
81
|
-
#
|
|
92
|
+
# STEP 12: Replace GStack with OpenGStack (product name)
|
|
82
93
|
content = re.sub(r"\bGStack\b", "OpenGStack", content)
|
|
83
94
|
|
|
84
|
-
# Remove
|
|
95
|
+
# STEP 13: Remove standalone gstack references in prose
|
|
96
|
+
# But keep it in contexts like "skill system" or "framework"
|
|
97
|
+
content = re.sub(r"\bgstack skills?\b", "skills", content, flags=re.IGNORECASE)
|
|
98
|
+
content = re.sub(
|
|
99
|
+
r"\bgstack[- ]?telemetry\b", "telemetry", content, flags=re.IGNORECASE
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# STEP 14: Remove ref=gstack from URLs
|
|
85
103
|
content = re.sub(r"\?ref=gstack", "", content)
|
|
86
104
|
|
|
87
|
-
#
|
|
88
|
-
content = re.sub(
|
|
89
|
-
|
|
105
|
+
# STEP 15: Remove broken sentence fragments
|
|
106
|
+
content = re.sub(
|
|
107
|
+
r"gstack follows the \*\*[^*]+\*\* principle.*?Read more:",
|
|
108
|
+
"",
|
|
109
|
+
content,
|
|
110
|
+
flags=re.DOTALL,
|
|
111
|
+
)
|
|
90
112
|
|
|
91
|
-
#
|
|
92
|
-
content = re.sub(r"
|
|
113
|
+
# STEP 16: Fix "You are GStack" -> "You are using OpenGStack"
|
|
114
|
+
content = re.sub(r"You are GStack,", "You are using OpenGStack,", content)
|
|
115
|
+
content = re.sub(r"You are OpenGStack,", "You are using OpenGStack,", content)
|
|
93
116
|
|
|
94
|
-
#
|
|
95
|
-
|
|
96
|
-
content = "\
|
|
117
|
+
# STEP 17: Remove orphaned code fences and clean up
|
|
118
|
+
content = re.sub(r"\n{3,}", "\n\n", content)
|
|
119
|
+
content = re.sub(r"```\s*\n\s*```", "", content)
|
|
120
|
+
content = re.sub(r"^\s*```\s*$", "", content, flags=re.MULTILINE)
|
|
97
121
|
|
|
98
|
-
#
|
|
99
|
-
content = content.
|
|
122
|
+
# STEP 18: Clean empty lines at start/end
|
|
123
|
+
content = content.strip()
|
|
100
124
|
|
|
101
|
-
return content
|
|
125
|
+
return content + "\n"
|
|
102
126
|
|
|
103
127
|
|
|
104
128
|
def filter_file(filepath: Path) -> bool:
|
|
@@ -120,20 +144,20 @@ def main():
|
|
|
120
144
|
Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).parent.parent
|
|
121
145
|
)
|
|
122
146
|
|
|
123
|
-
print(f"
|
|
147
|
+
print(f"NUKING gstack slop from: {skills_dir}")
|
|
124
148
|
|
|
125
149
|
modified = 0
|
|
126
150
|
for skill_file in skills_dir.rglob("SKILL.md"):
|
|
127
151
|
if filter_file(skill_file):
|
|
128
|
-
print(f"
|
|
152
|
+
print(f" NUKED: {skill_file.relative_to(skills_dir)}")
|
|
129
153
|
modified += 1
|
|
130
154
|
|
|
131
155
|
for tmpl_file in skills_dir.rglob("SKILL.md.tmpl"):
|
|
132
156
|
if filter_file(tmpl_file):
|
|
133
|
-
print(f"
|
|
157
|
+
print(f" NUKED: {tmpl_file.relative_to(skills_dir)}")
|
|
134
158
|
modified += 1
|
|
135
159
|
|
|
136
|
-
print(f"\nDone!
|
|
160
|
+
print(f"\nDone! Cleansed {modified} files of gstack slop.")
|
|
137
161
|
|
|
138
162
|
|
|
139
163
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const SKILLS_DIR = path.join(process.env.HOME || process.env.USERPROFILE, '.claude', 'skills');
|
|
7
|
+
const PKG_DIR = path.dirname(__dirname);
|
|
8
|
+
|
|
9
|
+
// List of skill directories
|
|
10
|
+
const skills = [
|
|
11
|
+
'autoplan', 'benchmark', 'browse', 'canary', 'careful', 'codex',
|
|
12
|
+
'connect-chrome', 'cso', 'design-consultation', 'design-review',
|
|
13
|
+
'design-shotgun', 'document-release', 'freeze', 'gstack-upgrade',
|
|
14
|
+
'guard', 'investigate', 'land-and-deploy', 'office-hours',
|
|
15
|
+
'plan-ceo-review', 'plan-design-review', 'plan-eng-review',
|
|
16
|
+
'qa', 'qa-only', 'retro', 'review', 'setup-browser-cookies',
|
|
17
|
+
'setup-deploy', 'ship', 'unfreeze'
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
console.log('🔗 Installing OpenGStack skills to ~/.claude/skills/...');
|
|
21
|
+
|
|
22
|
+
// Ensure skills directory exists
|
|
23
|
+
if (!fs.existsSync(SKILLS_DIR)) {
|
|
24
|
+
fs.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Create symlinks for each skill
|
|
28
|
+
let installed = 0;
|
|
29
|
+
let skipped = 0;
|
|
30
|
+
|
|
31
|
+
for (const skill of skills) {
|
|
32
|
+
const srcPath = path.join(PKG_DIR, skill);
|
|
33
|
+
const destPath = path.join(SKILLS_DIR, skill);
|
|
34
|
+
|
|
35
|
+
if (!fs.existsSync(srcPath)) {
|
|
36
|
+
console.warn(`⚠️ Skill not found: ${skill}`);
|
|
37
|
+
skipped++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Remove existing if it's a symlink
|
|
43
|
+
if (fs.existsSync(destPath)) {
|
|
44
|
+
const stat = fs.lstatSync(destPath);
|
|
45
|
+
if (stat.isSymbolicLink()) {
|
|
46
|
+
fs.unlinkSync(destPath);
|
|
47
|
+
} else {
|
|
48
|
+
console.log(`⏭️ Skipping ${skill} (already exists)`);
|
|
49
|
+
skipped++;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create symlink
|
|
55
|
+
fs.symlinkSync(srcPath, destPath, 'dir');
|
|
56
|
+
console.log(`✓ ${skill}`);
|
|
57
|
+
installed++;
|
|
58
|
+
} catch (err) {
|
|
59
|
+
console.error(`✗ ${skill}: ${err.message}`);
|
|
60
|
+
skipped++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(`\n✅ Installed ${installed} skills, skipped ${skipped}`);
|
|
65
|
+
console.log('🎯 Skills are now available in opencode/Claude');
|