hero-vibe-kit 0.1.0
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/CHANGELOG.md +19 -0
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/bin/hero-vibe-kit.js +62 -0
- package/package.json +35 -0
- package/presets/enterprise.json +6 -0
- package/presets/small-team.json +6 -0
- package/presets/solo.json +6 -0
- package/skills.manifest.json +39 -0
- package/src/detect.cjs +42 -0
- package/src/doctor.cjs +74 -0
- package/src/init.cjs +95 -0
- package/src/integrations.cjs +89 -0
- package/src/links.cjs +37 -0
- package/src/merge.cjs +61 -0
- package/src/render.cjs +27 -0
- package/src/update.cjs +59 -0
- package/src/util.cjs +56 -0
- package/templates/AGENTS.md.tmpl +9 -0
- package/templates/CLAUDE.md.tmpl +11 -0
- package/templates/common/.claude/hooks/git-guard.cjs +55 -0
- package/templates/common/.claude/hooks/stop-reminder.cjs +34 -0
- package/templates/common/.claude/settings.json +25 -0
- package/templates/docs/en/ACTIVE_STATE.md +28 -0
- package/templates/docs/en/AGENCY_WORKFLOW.md +126 -0
- package/templates/docs/en/BRANCHING.md +44 -0
- package/templates/docs/en/COMMUNICATION_PROTOCOL.md +59 -0
- package/templates/docs/en/DEFINITION_OF_DONE.md +60 -0
- package/templates/docs/en/INTERACTION_PATTERNS.md +58 -0
- package/templates/docs/en/PERFORMANCE_STANDARDS.md +31 -0
- package/templates/docs/en/SECURITY_STANDARDS.md +37 -0
- package/templates/docs/en/TEAM_ROSTER.md +35 -0
- package/templates/docs/en/templates/PRD_AI_FEATURE.md +85 -0
- package/templates/docs/vi/ACTIVE_STATE.md +28 -0
- package/templates/docs/vi/AGENCY_WORKFLOW.md +126 -0
- package/templates/docs/vi/BRANCHING.md +44 -0
- package/templates/docs/vi/COMMUNICATION_PROTOCOL.md +59 -0
- package/templates/docs/vi/DEFINITION_OF_DONE.md +60 -0
- package/templates/docs/vi/INTERACTION_PATTERNS.md +58 -0
- package/templates/docs/vi/PERFORMANCE_STANDARDS.md +31 -0
- package/templates/docs/vi/SECURITY_STANDARDS.md +37 -0
- package/templates/docs/vi/TEAM_ROSTER.md +35 -0
- package/templates/docs/vi/templates/PRD_AI_FEATURE.md +85 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to hero-vibe-kit are documented here. Format based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/); versioning follows [SemVer](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [0.1.0] - Unreleased
|
|
7
|
+
### Added
|
|
8
|
+
- `npx hero-vibe-kit init` — installs the workflow into a project (new or brownfield), idempotent, with backups.
|
|
9
|
+
- `update` — re-renders framework-managed regions while preserving user edits and working files (ACTIVE_STATE).
|
|
10
|
+
- `doctor` — validates settings.json, hook self-tests, doc-link integrity, and tool presence.
|
|
11
|
+
- Bilingual docs (EN + VI): AGENCY_WORKFLOW (task-type router + 5 phases), DEFINITION_OF_DONE, BRANCHING,
|
|
12
|
+
TEAM_ROSTER, ACTIVE_STATE, COMMUNICATION_PROTOCOL, INTERACTION_PATTERNS, SECURITY_STANDARDS,
|
|
13
|
+
PERFORMANCE_STANDARDS, and a PRD_AI_FEATURE template.
|
|
14
|
+
- Enforcement hooks for Claude Code: `git-guard` (blocks force-push / `--no-verify` / `reset --hard` /
|
|
15
|
+
direct push to main; reminds on commit) and `stop-reminder`.
|
|
16
|
+
- Managed-region markers (`<!-- hero-vibe-kit:start/end -->`) for safe updates.
|
|
17
|
+
- Presets: solo, small-team, enterprise.
|
|
18
|
+
- Optional integrations (reference & auto-install, never bundled): superpowers/taste skills via the `skills`
|
|
19
|
+
CLI, GitNexus indexing, Serena pointer-memories. All degrade gracefully when absent.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hung Vi Manh
|
|
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,165 @@
|
|
|
1
|
+
# hero-vibe-kit
|
|
2
|
+
|
|
3
|
+
> An opinionated, AI-assisted software-development workflow for **Claude Code** — a task-type router, real gates, enforcement hooks, a human↔AI communication protocol, and security/performance standards. Works for **new** and **existing (brownfield)** projects.
|
|
4
|
+
|
|
5
|
+
*(English below · [Tiếng Việt ở dưới](#tiếng-việt))*
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What it is
|
|
10
|
+
|
|
11
|
+
`hero-vibe-kit` drops a complete, lightweight development process into your repo so any AI agent (Claude Code first) works the way a disciplined team would:
|
|
12
|
+
|
|
13
|
+
- **Task-type router** — every request is classified (Q&A · chore · bugfix · hotfix · change · refactor · feature · spike) and routed to the right *path* (Read-only / Fast / Standard / Full). No heavy ceremony for small tasks.
|
|
14
|
+
- **Real gates** — "wait for approval" is enforced via Claude Code **Plan Mode**, not prose.
|
|
15
|
+
- **Enforcement hooks** — `git-guard` blocks force-push, `--no-verify`, `reset --hard`, and direct pushes to `main`; `stop-reminder` nudges you to keep state updated.
|
|
16
|
+
- **Human↔AI communication protocol** — no silent assumptions, blocking vs non-blocking questions, decision/assumption logs — tuned for building AI products.
|
|
17
|
+
- **Standards** — a measurable Definition of Done, branching model, and **Security** (incl. OWASP LLM Top 10) + **Performance** (incl. prompt caching) baselines.
|
|
18
|
+
- **AI-feature PRD template** + **interaction patterns** for how your product talks to its end-users.
|
|
19
|
+
|
|
20
|
+
It is **documentation + hooks + a CLI** — it does not bundle third-party tools; it integrates with them and degrades gracefully when they're absent.
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# In your project root (new or existing):
|
|
26
|
+
npx hero-vibe-kit init
|
|
27
|
+
|
|
28
|
+
# Then restart Claude Code (or run /hooks) to activate the hooks, and:
|
|
29
|
+
npx hero-vibe-kit doctor
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Non-interactive / CI:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx hero-vibe-kit init --yes --preset small-team --lang en --skip-integrations
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## What `init` installs
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
your-project/
|
|
42
|
+
CLAUDE.md # hero-vibe-kit managed block (your other content preserved)
|
|
43
|
+
AGENTS.md # cross-agent entry pointer
|
|
44
|
+
docs/ # AGENCY_WORKFLOW (SSOT) + DEFINITION_OF_DONE, BRANCHING, TEAM_ROSTER,
|
|
45
|
+
# ACTIVE_STATE, COMMUNICATION_PROTOCOL, INTERACTION_PATTERNS,
|
|
46
|
+
# SECURITY_STANDARDS, PERFORMANCE_STANDARDS, templates/PRD_AI_FEATURE
|
|
47
|
+
.claude/
|
|
48
|
+
settings.json # hooks merged into your existing settings (not clobbered)
|
|
49
|
+
hooks/ # git-guard.cjs, stop-reminder.cjs
|
|
50
|
+
.hero-vibe-kit/
|
|
51
|
+
config.json # your choices (team size, branching, language, integrations)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- **New project**: scaffolds everything.
|
|
55
|
+
- **Brownfield**: never overwrites your `CLAUDE.md`/`AGENTS.md`/`settings.json` — it inserts a marked managed block and deep-merges hooks. Your `docs/ACTIVE_STATE.md` is never overwritten. Re-running is idempotent; touched files are backed up to `*.bak`.
|
|
56
|
+
|
|
57
|
+
## The task router (heart of it)
|
|
58
|
+
|
|
59
|
+
| Task | Path | Gate | Branch |
|
|
60
|
+
|------|------|------|--------|
|
|
61
|
+
| Q&A / explain / find code | Read-only | — | — |
|
|
62
|
+
| chore / docs / config | Fast | — | `chore/` `docs/` |
|
|
63
|
+
| small bugfix | Fast | — (repro test) | `fix/` |
|
|
64
|
+
| hotfix | Fast | — | `hotfix/` |
|
|
65
|
+
| change existing logic | Standard | ✅ | `change/` |
|
|
66
|
+
| refactor | Standard | ✅ | `refactor/` |
|
|
67
|
+
| new feature | Full (5-phase) | ✅✅ | `feat/` |
|
|
68
|
+
| spike / research | Timeboxed | — | `spike/` |
|
|
69
|
+
|
|
70
|
+
Full details in `docs/AGENCY_WORKFLOW.md` (the single source of truth).
|
|
71
|
+
|
|
72
|
+
## Integrations (optional — reference & auto-install)
|
|
73
|
+
|
|
74
|
+
hero-vibe-kit **does not redistribute** third-party tools. `init` offers to set them up from their original sources and degrades gracefully if they're missing.
|
|
75
|
+
|
|
76
|
+
| Tool | What it is | What init does | Tier |
|
|
77
|
+
|------|-----------|----------------|------|
|
|
78
|
+
| **superpowers** | process skills (brainstorming, TDD, debugging…) from `obra/superpowers` | offers `npx skills add obra/superpowers` | recommended |
|
|
79
|
+
| **taste-skill** | UI/design skills from `Leonxlnx/taste-skill` | offers to install; pick ONE direction | optional |
|
|
80
|
+
| **GitNexus** | code-intelligence CLI/MCP | offers `npx gitnexus analyze` | optional |
|
|
81
|
+
| **Serena** | MCP memory server | seeds pointer-memories if present | optional |
|
|
82
|
+
|
|
83
|
+
**Required:** Node ≥ 18 and Claude Code. Everything else is optional.
|
|
84
|
+
|
|
85
|
+
## Commands
|
|
86
|
+
|
|
87
|
+
| Command | Purpose |
|
|
88
|
+
|---------|---------|
|
|
89
|
+
| `init` | Install into the current project |
|
|
90
|
+
| `update` | Re-render managed regions, preserving your edits & working files |
|
|
91
|
+
| `doctor` | Validate hooks, settings.json, doc links, tool presence |
|
|
92
|
+
| `version` | Print version |
|
|
93
|
+
|
|
94
|
+
Flags: `--dir <path>` · `--preset solo|small-team|enterprise` · `--lang en|vi` · `--name <name>` · `--yes` · `--skip-integrations`.
|
|
95
|
+
|
|
96
|
+
## Update & customize
|
|
97
|
+
|
|
98
|
+
- Edit anything **outside** the `<!-- hero-vibe-kit:start/end -->` markers freely — `update` won't touch it.
|
|
99
|
+
- Fill the `<TBD>` placeholders in DEFINITION_OF_DONE / SECURITY / PERFORMANCE once you pick a stack.
|
|
100
|
+
- `npx hero-vibe-kit update` refreshes the managed docs/hooks to the latest version, backing up changes.
|
|
101
|
+
|
|
102
|
+
## Uninstall
|
|
103
|
+
|
|
104
|
+
Remove `docs/` framework files, the `.claude/hooks/*` + the hooks block in `settings.json`, the
|
|
105
|
+
`<!-- hero-vibe-kit:* -->` block in `CLAUDE.md`/`AGENTS.md`, and `.hero-vibe-kit/`.
|
|
106
|
+
|
|
107
|
+
## License & attribution
|
|
108
|
+
|
|
109
|
+
MIT (see [LICENSE](./LICENSE)). hero-vibe-kit references but does not redistribute
|
|
110
|
+
[obra/superpowers](https://github.com/obra/superpowers) and [Leonxlnx/taste-skill](https://github.com/Leonxlnx/taste-skill);
|
|
111
|
+
they are installed from source via the `skills` CLI under their own licenses.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
# Tiếng Việt
|
|
116
|
+
|
|
117
|
+
> Một quy trình phát triển phần mềm có AI hỗ trợ, dùng cho **Claude Code** — bảng phân loại task, gate thật, hook cưỡng chế, giao thức giao tiếp Human↔AI, và chuẩn bảo mật/hiệu năng. Chạy tốt cho **project mới** lẫn **code cũ (brownfield)**.
|
|
118
|
+
|
|
119
|
+
## Là gì
|
|
120
|
+
|
|
121
|
+
`hero-vibe-kit` cài một quy trình phát triển hoàn chỉnh, tinh gọn vào repo của bạn để mọi AI agent (Claude Code trước) làm việc kỷ luật như một team thực thụ:
|
|
122
|
+
|
|
123
|
+
- **Bảng phân loại task** → chọn đúng *path* (Read-only / Fast / Standard / Full). Việc nhỏ không phải chạy quy trình nặng.
|
|
124
|
+
- **Gate thật** qua **Plan Mode** của Claude Code, không phải lời hứa văn xuôi.
|
|
125
|
+
- **Hook cưỡng chế** — `git-guard` chặn force-push, `--no-verify`, `reset --hard`, push thẳng `main`; `stop-reminder` nhắc cập nhật trạng thái.
|
|
126
|
+
- **Giao thức giao tiếp Human↔AI** — no silent assumptions, câu hỏi blocking/non-blocking, decision/assumption log — thiết kế cho việc xây sản phẩm AI.
|
|
127
|
+
- **Chuẩn** — Definition of Done đo được, branching model, và baseline **Security** (gồm OWASP LLM Top 10) + **Performance** (gồm prompt caching).
|
|
128
|
+
- **Template PRD cho feature AI** + **interaction patterns** cho cách sản phẩm giao tiếp với end-user.
|
|
129
|
+
|
|
130
|
+
Đây là **tài liệu + hook + CLI** — không đóng gói tool bên thứ ba; chỉ tích hợp và degrade mượt khi thiếu.
|
|
131
|
+
|
|
132
|
+
## Bắt đầu nhanh
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Ở thư mục gốc project (mới hoặc đã có code):
|
|
136
|
+
npx hero-vibe-kit init
|
|
137
|
+
|
|
138
|
+
# Khởi động lại Claude Code (hoặc /hooks) để bật hook, rồi:
|
|
139
|
+
npx hero-vibe-kit doctor
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Không tương tác / CI:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx hero-vibe-kit init --yes --preset small-team --lang vi --skip-integrations
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## init cài gì
|
|
149
|
+
|
|
150
|
+
Như sơ đồ ở phần English: `docs/` (AGENCY_WORKFLOW là single source of truth + các chuẩn), `CLAUDE.md`/`AGENTS.md` (chèn **block có marker**, giữ nguyên nội dung của bạn), `.claude/` (hook + settings deep-merge), `.hero-vibe-kit/config.json`.
|
|
151
|
+
|
|
152
|
+
- **Project mới**: scaffold đầy đủ.
|
|
153
|
+
- **Brownfield**: KHÔNG đè `CLAUDE.md`/`AGENTS.md`/`settings.json` — chỉ chèn block + merge hook. `docs/ACTIVE_STATE.md` không bị ghi đè. Chạy lại idempotent; file bị đụng được sao lưu `*.bak`.
|
|
154
|
+
|
|
155
|
+
## Tích hợp (tùy chọn — reference & auto-install)
|
|
156
|
+
|
|
157
|
+
hero-vibe-kit **không redistribute** tool bên thứ ba. `init` mời cài từ nguồn gốc và degrade nếu thiếu: **superpowers** (`npx skills add obra/superpowers`, khuyến nghị), **taste-skill** (tùy chọn, chọn 1 hướng), **GitNexus** (`npx gitnexus analyze`, tùy chọn), **Serena** (seed pointer-memories, tùy chọn). **Bắt buộc:** Node ≥ 18 + Claude Code.
|
|
158
|
+
|
|
159
|
+
## Lệnh & cập nhật
|
|
160
|
+
|
|
161
|
+
`init` · `update` (giữ chỉnh sửa ngoài marker + file làm việc) · `doctor` · `version`. Sửa thoải mái phần **ngoài** marker `<!-- hero-vibe-kit:start/end -->`. Điền `<TBD>` khi chốt tech stack.
|
|
162
|
+
|
|
163
|
+
## Giấy phép
|
|
164
|
+
|
|
165
|
+
MIT (xem [LICENSE](./LICENSE)). Tham chiếu chứ không redistribute `obra/superpowers` và `Leonxlnx/taste-skill` — cài từ nguồn qua `skills` CLI theo license riêng của chúng.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
5
|
+
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
const flags = {};
|
|
8
|
+
const pos = [];
|
|
9
|
+
for (let i = 0; i < argv.length; i++) {
|
|
10
|
+
const a = argv[i];
|
|
11
|
+
if (a.startsWith('--')) {
|
|
12
|
+
const key = a.slice(2);
|
|
13
|
+
if (argv[i + 1] !== undefined && !argv[i + 1].startsWith('--')) flags[key] = argv[++i];
|
|
14
|
+
else flags[key] = true;
|
|
15
|
+
} else if (a.startsWith('-') && a.length === 2) {
|
|
16
|
+
flags[a.slice(1)] = true;
|
|
17
|
+
} else pos.push(a);
|
|
18
|
+
}
|
|
19
|
+
return { cmd: pos[0], pos, flags };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function printHelp() {
|
|
23
|
+
console.log(`hero-vibe-kit — AI-assisted development workflow for Claude Code
|
|
24
|
+
|
|
25
|
+
Usage: npx hero-vibe-kit <command> [flags]
|
|
26
|
+
|
|
27
|
+
Commands:
|
|
28
|
+
init Install the workflow into the current project (new or brownfield)
|
|
29
|
+
update Re-render managed regions, preserving your edits
|
|
30
|
+
doctor Validate the install (hooks, settings.json, doc links, tools)
|
|
31
|
+
version Print the version
|
|
32
|
+
help Show this help
|
|
33
|
+
|
|
34
|
+
Flags:
|
|
35
|
+
--dir <path> Target project dir (default: current dir)
|
|
36
|
+
--preset <name> solo | small-team | enterprise
|
|
37
|
+
--lang <en|vi> Docs language (default: en)
|
|
38
|
+
--name <name> Project name (default: dir name)
|
|
39
|
+
--yes Non-interactive; accept defaults
|
|
40
|
+
--skip-integrations Skip skills / gitnexus / serena prompts`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function main() {
|
|
44
|
+
const { cmd, flags } = parseArgs(process.argv.slice(2));
|
|
45
|
+
const target = flags.dir ? path.resolve(String(flags.dir)) : process.cwd();
|
|
46
|
+
const opts = { pkgRoot: PKG_ROOT, target, flags };
|
|
47
|
+
const version = () => console.log(require('../package.json').version);
|
|
48
|
+
|
|
49
|
+
if (flags.version || flags.v) { version(); return; }
|
|
50
|
+
|
|
51
|
+
switch (cmd) {
|
|
52
|
+
case 'init': await require('../src/init.cjs').init(opts); break;
|
|
53
|
+
case 'update': await require('../src/update.cjs').update(opts); break;
|
|
54
|
+
case 'doctor': await require('../src/doctor.cjs').doctor(opts); break;
|
|
55
|
+
case 'version': version(); break;
|
|
56
|
+
case 'help': case undefined: printHelp(); break;
|
|
57
|
+
default:
|
|
58
|
+
console.error('Unknown command: ' + cmd); printHelp(); process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
main().catch((e) => { console.error((e && e.stack) || e); process.exit(1); });
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hero-vibe-kit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An opinionated, AI-assisted software development workflow for Claude Code — task-type router, gates, enforcement hooks, human↔AI communication protocol, and security/performance standards. Works for new and existing (brownfield) projects.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code",
|
|
7
|
+
"ai-workflow",
|
|
8
|
+
"agentic-development",
|
|
9
|
+
"scaffolding",
|
|
10
|
+
"developer-workflow",
|
|
11
|
+
"ai-assistant"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"type": "commonjs",
|
|
15
|
+
"bin": {
|
|
16
|
+
"hero-vibe-kit": "bin/hero-vibe-kit.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin",
|
|
20
|
+
"src",
|
|
21
|
+
"templates",
|
|
22
|
+
"presets",
|
|
23
|
+
"skills.manifest.json",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"CHANGELOG.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"test": "node --test"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {}
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Skills the hero-vibe-kit workflow references. hero-vibe-kit does NOT bundle these — it records them here and (optionally, with consent) installs them via the `skills` CLI from their ORIGINAL sources. This avoids redistribution and keeps skills up to date. See docs: TEAM_ROSTER / AGENCY_WORKFLOW.",
|
|
3
|
+
"schema": 1,
|
|
4
|
+
"installer": "skills",
|
|
5
|
+
"groups": {
|
|
6
|
+
"process": {
|
|
7
|
+
"tier": "recommended",
|
|
8
|
+
"description": "Core process skills the workflow invokes by name. Without them the workflow still runs (gates/hooks/router intact) but loses skill-guided depth.",
|
|
9
|
+
"skills": [
|
|
10
|
+
{ "name": "using-superpowers", "source": "obra/superpowers" },
|
|
11
|
+
{ "name": "brainstorming", "source": "obra/superpowers" },
|
|
12
|
+
{ "name": "writing-plans", "source": "obra/superpowers" },
|
|
13
|
+
{ "name": "executing-plans", "source": "obra/superpowers" },
|
|
14
|
+
{ "name": "test-driven-development", "source": "obra/superpowers" },
|
|
15
|
+
{ "name": "systematic-debugging", "source": "obra/superpowers" },
|
|
16
|
+
{ "name": "verification-before-completion", "source": "obra/superpowers" },
|
|
17
|
+
{ "name": "requesting-code-review", "source": "obra/superpowers" },
|
|
18
|
+
{ "name": "receiving-code-review", "source": "obra/superpowers" },
|
|
19
|
+
{ "name": "dispatching-parallel-agents", "source": "obra/superpowers" },
|
|
20
|
+
{ "name": "subagent-driven-development", "source": "obra/superpowers" },
|
|
21
|
+
{ "name": "using-git-worktrees", "source": "obra/superpowers" },
|
|
22
|
+
{ "name": "finishing-a-development-branch", "source": "obra/superpowers" },
|
|
23
|
+
{ "name": "writing-skills", "source": "obra/superpowers" }
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"design": {
|
|
27
|
+
"tier": "optional",
|
|
28
|
+
"description": "Design/UI skills. Pick ONE design direction per project (see TEAM_ROSTER §design). init asks which to install; it does NOT install the whole set.",
|
|
29
|
+
"pickOne": true,
|
|
30
|
+
"skills": [
|
|
31
|
+
{ "name": "design-taste-frontend", "source": "Leonxlnx/taste-skill" },
|
|
32
|
+
{ "name": "minimalist-ui", "source": "Leonxlnx/taste-skill" },
|
|
33
|
+
{ "name": "industrial-brutalist-ui", "source": "Leonxlnx/taste-skill" },
|
|
34
|
+
{ "name": "high-end-visual-design", "source": "Leonxlnx/taste-skill" },
|
|
35
|
+
{ "name": "brandkit", "source": "Leonxlnx/taste-skill" }
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/detect.cjs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { exists } = require('./util.cjs');
|
|
5
|
+
|
|
6
|
+
const CODE_EXT = new Set(['.js', '.mjs', '.cjs', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs', '.java', '.rb', '.php', '.cs', '.cpp', '.c', '.h', '.vue', '.svelte', '.kt', '.swift', '.scala', '.dart']);
|
|
7
|
+
const SKIP = new Set(['.git', 'node_modules', '.gitnexus', '.agents', '.hero-vibe-kit', 'templates', 'dist', 'build', '.next', 'out', 'vendor', '__pycache__', '.serena', '.claude', 'coverage']);
|
|
8
|
+
|
|
9
|
+
function findCode(dir, depth) {
|
|
10
|
+
if (depth > 3) return false;
|
|
11
|
+
let entries;
|
|
12
|
+
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch (_) { return false; }
|
|
13
|
+
for (const e of entries) {
|
|
14
|
+
if (e.isDirectory()) {
|
|
15
|
+
if (SKIP.has(e.name) || e.name.startsWith('.')) continue;
|
|
16
|
+
if (findCode(path.join(dir, e.name), depth + 1)) return true;
|
|
17
|
+
} else if (CODE_EXT.has(path.extname(e.name))) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function detect(target) {
|
|
25
|
+
const r = {
|
|
26
|
+
target,
|
|
27
|
+
isGitRepo: exists(path.join(target, '.git')),
|
|
28
|
+
existingClaudeMd: exists(path.join(target, 'CLAUDE.md')),
|
|
29
|
+
existingAgentsMd: exists(path.join(target, 'AGENTS.md')),
|
|
30
|
+
existingSettings: exists(path.join(target, '.claude', 'settings.json')),
|
|
31
|
+
existingActiveState: exists(path.join(target, 'docs', 'ACTIVE_STATE.md')),
|
|
32
|
+
existingConfig: exists(path.join(target, '.hero-vibe-kit', 'config.json')),
|
|
33
|
+
hasSkillsLock: exists(path.join(target, 'skills-lock.json')),
|
|
34
|
+
hasSerena: exists(path.join(target, '.serena')),
|
|
35
|
+
hasGitnexus: exists(path.join(target, '.gitnexus')),
|
|
36
|
+
hasCode: findCode(target, 0),
|
|
37
|
+
};
|
|
38
|
+
r.brownfield = r.hasCode || r.existingClaudeMd || r.existingAgentsMd;
|
|
39
|
+
return r;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = { detect };
|
package/src/doctor.cjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { spawnSync } = require('child_process');
|
|
4
|
+
const { log, exists, readJSON } = require('./util.cjs');
|
|
5
|
+
const { checkLinks } = require('./links.cjs');
|
|
6
|
+
|
|
7
|
+
function hookCheck(hookFile, payload) {
|
|
8
|
+
const r = spawnSync('node', [hookFile], { input: JSON.stringify(payload), encoding: 'utf8' });
|
|
9
|
+
return { code: r.status, err: (r.stderr || '').trim() };
|
|
10
|
+
}
|
|
11
|
+
function which(cmd) {
|
|
12
|
+
const r = spawnSync(process.platform === 'win32' ? 'where' : 'which', [cmd], { encoding: 'utf8' });
|
|
13
|
+
return r.status === 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function doctor(opts) {
|
|
17
|
+
const { target } = opts;
|
|
18
|
+
log.title('hero-vibe-kit · doctor');
|
|
19
|
+
let pass = 0, warn = 0, fail = 0;
|
|
20
|
+
const ok = (m) => { log.ok(m); pass++; };
|
|
21
|
+
const wn = (m) => { log.warn(m); warn++; };
|
|
22
|
+
const er = (m) => { log.err(m); fail++; };
|
|
23
|
+
|
|
24
|
+
// config
|
|
25
|
+
const cfg = readJSON(path.join(target, '.hero-vibe-kit', 'config.json'), null);
|
|
26
|
+
if (cfg) ok(`config: v${cfg.version} · ${cfg.projectName} · lang=${cfg.lang} · ${cfg.brownfield ? 'brownfield' : 'new'}`);
|
|
27
|
+
else er('config missing (.hero-vibe-kit/config.json) — run `hero-vibe-kit init`');
|
|
28
|
+
|
|
29
|
+
// settings.json
|
|
30
|
+
const sp = path.join(target, '.claude', 'settings.json');
|
|
31
|
+
const settings = readJSON(sp, null);
|
|
32
|
+
if (!exists(sp)) er('.claude/settings.json missing');
|
|
33
|
+
else if (!settings) er('.claude/settings.json is invalid JSON');
|
|
34
|
+
else {
|
|
35
|
+
const cmds = JSON.stringify(settings.hooks || {});
|
|
36
|
+
cmds.includes('git-guard.cjs') ? ok('settings.json: git-guard hook wired') : wn('git-guard hook not wired in settings.json');
|
|
37
|
+
cmds.includes('stop-reminder.cjs') ? ok('settings.json: stop-reminder hook wired') : wn('stop-reminder hook not wired');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// hook self-tests
|
|
41
|
+
const gg = path.join(target, '.claude', 'hooks', 'git-guard.cjs');
|
|
42
|
+
if (exists(gg)) {
|
|
43
|
+
const block = hookCheck(gg, { tool_name: 'Bash', tool_input: { command: 'git push -f origin main' } });
|
|
44
|
+
const allow = hookCheck(gg, { tool_name: 'Bash', tool_input: { command: 'git status' } });
|
|
45
|
+
if (block.code === 2 && allow.code === 0) ok('git-guard self-test: blocks force-push, allows safe git');
|
|
46
|
+
else er(`git-guard self-test failed (force-push exit=${block.code}, status exit=${allow.code})`);
|
|
47
|
+
} else er('.claude/hooks/git-guard.cjs missing');
|
|
48
|
+
|
|
49
|
+
const sr = path.join(target, '.claude', 'hooks', 'stop-reminder.cjs');
|
|
50
|
+
if (exists(sr)) {
|
|
51
|
+
const r = hookCheck(sr, { hook_event_name: 'Stop', stop_hook_active: true, cwd: target });
|
|
52
|
+
r.code === 0 ? ok('stop-reminder self-test: ok') : er('stop-reminder self-test failed');
|
|
53
|
+
} else er('.claude/hooks/stop-reminder.cjs missing');
|
|
54
|
+
|
|
55
|
+
// doc links
|
|
56
|
+
const { broken, checked } = checkLinks([path.join(target, 'docs'), path.join(target, 'CLAUDE.md'), path.join(target, 'AGENTS.md')]);
|
|
57
|
+
if (broken.length === 0) ok(`doc links: ${checked} checked, 0 broken`);
|
|
58
|
+
else { er(`doc links: ${broken.length} broken`); broken.slice(0, 8).forEach((b) => console.log(' - ' + path.relative(target, b.file) + ' -> ' + b.link)); }
|
|
59
|
+
|
|
60
|
+
// tools
|
|
61
|
+
log.title('Tools');
|
|
62
|
+
ok(`node: ${process.version} (required)`);
|
|
63
|
+
status('git', which('git'), 'recommended');
|
|
64
|
+
status('superpowers skills (skills-lock.json)', exists(path.join(target, 'skills-lock.json')), 'recommended');
|
|
65
|
+
status('GitNexus index (.gitnexus)', exists(path.join(target, '.gitnexus')), 'optional');
|
|
66
|
+
status('Serena (.serena)', exists(path.join(target, '.serena')), 'optional');
|
|
67
|
+
|
|
68
|
+
function status(name, present, tier) { present ? ok(`${name}: present (${tier})`) : wn(`${name}: absent (${tier})`); }
|
|
69
|
+
|
|
70
|
+
log.title(`Result: ${pass} ok · ${warn} warn · ${fail} fail`);
|
|
71
|
+
process.exit(fail > 0 ? 1 : 0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { doctor };
|
package/src/init.cjs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { log, ensureDir, exists, backup, writeJSON, makeAsker } = require('./util.cjs');
|
|
5
|
+
const { detect } = require('./detect.cjs');
|
|
6
|
+
const { renderTree, renderString } = require('./render.cjs');
|
|
7
|
+
const { mergeManagedBlock, mergeSettings } = require('./merge.cjs');
|
|
8
|
+
|
|
9
|
+
const TEAM_LABELS = { solo: 'solo (you + AI)', 'small-team': 'small team (2–5)', enterprise: 'larger team (6+)' };
|
|
10
|
+
const BRANCH_LABELS = { 'gitlab-flow': 'GitLab flow', 'github-flow': 'GitHub flow', trunk: 'trunk-based' };
|
|
11
|
+
|
|
12
|
+
async function init(opts) {
|
|
13
|
+
const { pkgRoot, target, flags } = opts;
|
|
14
|
+
const templates = path.join(pkgRoot, 'templates');
|
|
15
|
+
const auto = !!flags.yes;
|
|
16
|
+
const ask = makeAsker(auto);
|
|
17
|
+
|
|
18
|
+
log.title('hero-vibe-kit · init');
|
|
19
|
+
const d = detect(target);
|
|
20
|
+
log.step(`Target : ${target}`);
|
|
21
|
+
log.step(`Mode : ${d.brownfield ? 'brownfield (existing project)' : 'new project'}`);
|
|
22
|
+
|
|
23
|
+
// ---- config ----
|
|
24
|
+
let cfg = {};
|
|
25
|
+
if (flags.preset) {
|
|
26
|
+
const pf = path.join(pkgRoot, 'presets', String(flags.preset) + '.json');
|
|
27
|
+
if (!exists(pf)) { log.err(`Unknown preset: ${flags.preset}`); ask.close(); process.exit(1); }
|
|
28
|
+
cfg = JSON.parse(fs.readFileSync(pf, 'utf8'));
|
|
29
|
+
log.ok(`Preset : ${flags.preset}`);
|
|
30
|
+
}
|
|
31
|
+
cfg.projectName = flags.name || cfg.projectName || (auto ? path.basename(target) : await ask.text('Project name', path.basename(target)));
|
|
32
|
+
cfg.lang = flags.lang || cfg.lang || (auto ? 'en' : await ask.choice('Docs language:', ['en', 'vi'], 0));
|
|
33
|
+
if (!cfg.teamSize) cfg.teamSize = auto ? 'small-team' : await ask.choice('Team size:', ['solo', 'small-team', 'enterprise'], 1);
|
|
34
|
+
if (!cfg.branchingModel) cfg.branchingModel = auto ? 'github-flow' : await ask.choice('Branching model:', ['github-flow', 'gitlab-flow', 'trunk'], 0);
|
|
35
|
+
if (!cfg.enforceLevel) cfg.enforceLevel = 'mixed';
|
|
36
|
+
cfg.version = JSON.parse(fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf8')).version;
|
|
37
|
+
cfg.brownfield = d.brownfield;
|
|
38
|
+
|
|
39
|
+
if (cfg.lang !== 'en' && cfg.lang !== 'vi') { log.err(`Unsupported lang: ${cfg.lang} (use en|vi)`); ask.close(); process.exit(1); }
|
|
40
|
+
|
|
41
|
+
const vars = {
|
|
42
|
+
PROJECT_NAME: cfg.projectName,
|
|
43
|
+
DATE: new Date().toISOString().slice(0, 10),
|
|
44
|
+
TEAM_SIZE: TEAM_LABELS[cfg.teamSize] || cfg.teamSize,
|
|
45
|
+
BRANCHING_MODEL: BRANCH_LABELS[cfg.branchingModel] || cfg.branchingModel,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// ---- 1. docs ----
|
|
49
|
+
const srcDocs = path.join(templates, 'docs', cfg.lang);
|
|
50
|
+
let docCount = 0, keptActiveState = false;
|
|
51
|
+
for (const f of renderTree(srcDocs, vars)) {
|
|
52
|
+
const dest = path.join(target, 'docs', f.rel);
|
|
53
|
+
if (path.basename(f.rel) === 'ACTIVE_STATE.md' && exists(dest)) { keptActiveState = true; continue; }
|
|
54
|
+
ensureDir(path.dirname(dest));
|
|
55
|
+
if (exists(dest)) backup(dest);
|
|
56
|
+
fs.writeFileSync(dest, f.content);
|
|
57
|
+
docCount++;
|
|
58
|
+
}
|
|
59
|
+
log.ok(`Docs : ${docCount} file(s) [${cfg.lang}]` + (keptActiveState ? ' · kept existing ACTIVE_STATE.md' : ''));
|
|
60
|
+
|
|
61
|
+
// ---- 2. CLAUDE.md / AGENTS.md managed block ----
|
|
62
|
+
const claudeInner = renderString(fs.readFileSync(path.join(templates, 'CLAUDE.md.tmpl'), 'utf8'), vars);
|
|
63
|
+
const agentsInner = renderString(fs.readFileSync(path.join(templates, 'AGENTS.md.tmpl'), 'utf8'), vars);
|
|
64
|
+
log.ok(`CLAUDE.md: ${mergeManagedBlock(path.join(target, 'CLAUDE.md'), claudeInner, cfg.projectName)}`);
|
|
65
|
+
log.ok(`AGENTS.md: ${mergeManagedBlock(path.join(target, 'AGENTS.md'), agentsInner, null)}`);
|
|
66
|
+
|
|
67
|
+
// ---- 3. hooks + settings ----
|
|
68
|
+
ensureDir(path.join(target, '.claude', 'hooks'));
|
|
69
|
+
for (const h of ['git-guard.cjs', 'stop-reminder.cjs']) {
|
|
70
|
+
fs.copyFileSync(path.join(templates, 'common', '.claude', 'hooks', h), path.join(target, '.claude', 'hooks', h));
|
|
71
|
+
}
|
|
72
|
+
mergeSettings(path.join(target, '.claude', 'settings.json'), path.join(templates, 'common', '.claude', 'settings.json'));
|
|
73
|
+
log.ok('Hooks : git-guard + stop-reminder installed; settings.json merged');
|
|
74
|
+
|
|
75
|
+
// ---- 4. config ----
|
|
76
|
+
writeJSON(path.join(target, '.hero-vibe-kit', 'config.json'), cfg);
|
|
77
|
+
log.ok('Config : .hero-vibe-kit/config.json');
|
|
78
|
+
|
|
79
|
+
// ---- 5. optional integrations ----
|
|
80
|
+
if (!flags['skip-integrations']) {
|
|
81
|
+
await require('./integrations.cjs').run({ target, cfg, detect: d, ask, pkgRoot });
|
|
82
|
+
} else {
|
|
83
|
+
log.warn('Skipped integrations (skills / gitnexus / serena).');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ask.close();
|
|
87
|
+
|
|
88
|
+
log.title('Next steps');
|
|
89
|
+
console.log(' 1. Review docs/AGENCY_WORKFLOW.md (single source of truth).');
|
|
90
|
+
console.log(' 2. Restart Claude Code (or run /hooks) to activate the git-guard + stop-reminder hooks.');
|
|
91
|
+
console.log(' 3. Fill <TBD> in DEFINITION_OF_DONE / SECURITY_STANDARDS / PERFORMANCE_STANDARDS when you pick a stack.');
|
|
92
|
+
console.log(' 4. Run: npx hero-vibe-kit doctor');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { init };
|