minimal-vibe-coding-kit 0.3.0 → 0.4.1
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/.agents/skills/agentshield-security-review/SKILL.md +6 -6
- package/.agents/skills/agentshield-security-review/references/native-install.md +10 -10
- package/.agents/skills/agentshield-security-review/references/report-template.md +1 -1
- package/.agents/skills/agentshield-security-review/scripts/agentshield_repo_probe.py +3 -3
- package/.agents/skills/autoresearch-coding/README.md +1 -1
- package/.agents/skills/autoresearch-coding/SKILL.md +4 -4
- package/.agents/skills/coding-level/SKILL.md +8 -1
- package/.agents/skills/daily-workflow-curator/SKILL.md +3 -3
- package/.agents/skills/parallel-analysis/SKILL.md +160 -0
- package/.agents/skills/path-sensitive-shell-safety/SKILL.md +69 -0
- package/.agents/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
- package/.agents/skills/vibekit-init/SKILL.md +6 -6
- package/.claude/commands/vibe-finalize.md +1 -1
- package/.claude/rules/safe-delete.md +11 -0
- package/.claude/rules/security.md +2 -0
- package/.claude/rules/tooling.md +1 -1
- package/.claude/skills/agentshield-security-review/SKILL.md +6 -6
- package/.claude/skills/agentshield-security-review/references/native-install.md +10 -10
- package/.claude/skills/agentshield-security-review/references/report-template.md +1 -1
- package/.claude/skills/agentshield-security-review/scripts/agentshield_repo_probe.py +3 -3
- package/.claude/skills/autoresearch-coding/README.md +1 -1
- package/.claude/skills/autoresearch-coding/SKILL.md +4 -4
- package/.claude/skills/coding-level/SKILL.md +8 -1
- package/.claude/skills/daily-workflow-curator/SKILL.md +3 -3
- package/.claude/skills/parallel-analysis/SKILL.md +160 -0
- package/.claude/skills/path-sensitive-shell-safety/SKILL.md +69 -0
- package/.claude/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
- package/.claude/skills/vibekit-init/SKILL.md +6 -6
- package/.codex-plugin/plugin.json +2 -2
- package/.cursor/commands/vibe-finalize.md +1 -1
- package/.cursor/rules/001-vibe-core.mdc +1 -1
- package/.cursor/rules/010-init.mdc +1 -1
- package/.cursor/rules/020-security-agentshield.mdc +2 -2
- package/.cursor/rules/030-autoresearch-loop.mdc +1 -1
- package/.cursor/rules/040-safe-delete.mdc +16 -0
- package/.cursor/skills/coding-level/SKILL.md +8 -1
- package/.cursor/skills/parallel-analysis/SKILL.md +160 -0
- package/.cursor/skills/path-sensitive-shell-safety/SKILL.md +69 -0
- package/.cursor/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
- package/.vibekit/commands/vibe-finalize.md +3 -0
- package/{.vbkit-docs → .vibekit/docs}/AUTORESEARCH_LEDGER.md +3 -3
- package/{.vbkit-docs → .vibekit/docs}/BACKBONE_REFERENCE.md +1 -1
- package/{.vbkit-docs → .vibekit/docs}/INSTALL.md +28 -16
- package/{.vbkit-docs → .vibekit/docs}/RESEARCH_NOTES.md +1 -1
- package/{.vbkit-docs → .vibekit/docs}/SECURITY_MODEL.md +2 -2
- package/{.vbkit-docs → .vibekit/docs}/TOOLING_GUIDE.md +2 -2
- package/{.vbkit-docs → .vibekit/docs}/templates/CONTEXT_TEMPLATE.md +1 -1
- package/{.vbkit-docs → .vibekit/docs}/templates/PRD_TEMPLATE.md +1 -1
- package/{CLAUDE-template.md → .vibekit/init/CLAUDE-template.md} +3 -1
- package/{FIRST_PROMPT.md → .vibekit/init/FIRST_PROMPT.md} +6 -6
- package/{FIRST_TIME_INIT.md → .vibekit/init/FIRST_TIME_INIT.md} +46 -14
- package/{.vbkit-scripts → .vibekit/scripts}/agentshield-probe.mjs +1 -1
- package/{.vbkit-scripts → .vibekit/scripts}/daily-enhance.mjs +3 -3
- package/{.vbkit-scripts → .vibekit/scripts}/doctor.mjs +22 -7
- package/{.vbkit-scripts → .vibekit/scripts}/init-backbone.mjs +31 -22
- package/{.vbkit-scripts → .vibekit/scripts}/mvck.mjs +61 -25
- package/{.vbkit-scripts → .vibekit/scripts}/test-install.mjs +32 -18
- package/{.vbkit-scripts → .vibekit/scripts}/validate-kit.mjs +47 -31
- package/{.vbkit-scripts → .vibekit/scripts}/vibekit-finalize.mjs +7 -7
- package/{skills → .vibekit/skills}/agentshield-security-review/SKILL.md +6 -6
- package/{skills → .vibekit/skills}/agentshield-security-review/references/native-install.md +10 -10
- package/{skills → .vibekit/skills}/agentshield-security-review/references/report-template.md +1 -1
- package/{skills → .vibekit/skills}/agentshield-security-review/scripts/agentshield_repo_probe.py +3 -3
- package/{skills → .vibekit/skills}/autoresearch-coding/README.md +1 -1
- package/{skills → .vibekit/skills}/autoresearch-coding/SKILL.md +4 -4
- package/{skills → .vibekit/skills}/coding-level/SKILL.md +8 -1
- package/{skills → .vibekit/skills}/daily-workflow-curator/SKILL.md +3 -3
- package/.vibekit/skills/parallel-analysis/SKILL.md +160 -0
- package/.vibekit/skills/path-sensitive-shell-safety/SKILL.md +69 -0
- package/.vibekit/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
- package/{skills → .vibekit/skills}/vibekit-init/SKILL.md +6 -6
- package/AGENTS.md +6 -2
- package/CHANGELOG.md +24 -2
- package/CONTRIBUTING.md +3 -3
- package/README.md +147 -372
- package/backbone.yml +8 -7
- package/bin/mvck.js +1 -1
- package/bin/vibe-kit.js +1 -1
- package/docs/README.vi.md +268 -0
- package/install.ps1 +1 -1
- package/install.sh +5 -3
- package/package.json +23 -19
- package/.vbkit-commands/vibe-finalize.md +0 -3
- package/README.vi.md +0 -431
- /package/{.vbkit-commands → .vibekit/commands}/autoresearch-coding.md +0 -0
- /package/{.vbkit-commands → .vibekit/commands}/council.md +0 -0
- /package/{.vbkit-commands → .vibekit/commands}/daily-enhance.md +0 -0
- /package/{.vbkit-commands → .vibekit/commands}/init-vibe.md +0 -0
- /package/{.vbkit-commands → .vibekit/commands}/security-scan.md +0 -0
- /package/{.vbkit-docs → .vibekit/docs}/backbone.schema.json +0 -0
- /package/{.vbkit-scripts → .vibekit/scripts}/pack-dry-run.mjs +0 -0
- /package/{skills → .vibekit/skills}/agentshield-security-review/agents/openai.yaml +0 -0
- /package/{skills → .vibekit/skills}/agentshield-security-review/references/review-checklist.md +0 -0
- /package/{skills → .vibekit/skills}/autoresearch-coding/references/experiment-contract.md +0 -0
- /package/{skills → .vibekit/skills}/autoresearch-coding/references/metric-extraction.md +0 -0
- /package/{skills → .vibekit/skills}/autoresearch-coding/references/result-ledger.md +0 -0
- /package/{skills → .vibekit/skills}/autoresearch-coding/scripts/log_result.py +0 -0
- /package/{skills → .vibekit/skills}/autoresearch-coding/scripts/run_logged.py +0 -0
- /package/{skills → .vibekit/skills}/clearthought/SKILL.md +0 -0
- /package/{skills → .vibekit/skills}/clearthought/examples/decision-framework.md +0 -0
- /package/{skills → .vibekit/skills}/clearthought/examples/metagame-examples.md +0 -0
- /package/{skills → .vibekit/skills}/clearthought/examples/sequential-thinking.md +0 -0
- /package/{skills → .vibekit/skills}/clearthought/references/output-schemas.md +0 -0
- /package/{skills → .vibekit/skills}/clearthought/references/parameter-reference.md +0 -0
- /package/{skills → .vibekit/skills}/coding-level/references/level-0.md +0 -0
- /package/{skills → .vibekit/skills}/coding-level/references/level-1.md +0 -0
- /package/{skills → .vibekit/skills}/coding-level/references/level-2.md +0 -0
- /package/{skills → .vibekit/skills}/coding-level/references/level-3.md +0 -0
- /package/{skills → .vibekit/skills}/coding-level/references/level-4.md +0 -0
- /package/{skills → .vibekit/skills}/coding-level/references/level-5.md +0 -0
- /package/{skills → .vibekit/skills}/memento/SKILL.md +0 -0
- /package/{skills → .vibekit/skills}/reviewing-4p-priorities/SKILL.md +0 -0
- /package/{skills → .vibekit/skills}/reviewing-4p-priorities/examples.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/SKILL.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/examples/adaptive-depth.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/examples/branching-exploration.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/examples/linear-reasoning.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/examples/revision-pattern.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/references/output-schema.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/references/parameters.md +0 -0
- /package/{skills → .vibekit/skills}/sequential-thinking/references/patterns.md +0 -0
- /package/{skills → .vibekit/skills}/visual-design-loop/SKILL.md +0 -0
- /package/{skills → .vibekit/skills}/visual-design-loop/agents/openai.yaml +0 -0
|
@@ -5,7 +5,7 @@ Use one of these after installing the kit into a project.
|
|
|
5
5
|
## Universal first prompt
|
|
6
6
|
|
|
7
7
|
```text
|
|
8
|
-
Read FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit.
|
|
8
|
+
Read .vibekit/init/FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit.
|
|
9
9
|
First print the requirements you will check. Then run detection, propose one diff for backbone.yml and managed instruction blocks, and wait for my yes before writing.
|
|
10
10
|
Include inferred project conventions for naming, architecture, resources, localization, generated definitions, and per-app/package differences.
|
|
11
11
|
After approval, write the files, run validation, and summarize what changed.
|
|
@@ -20,13 +20,13 @@ Use /init-vibe. Keep CLAUDE.md short. Import shared AGENTS.md. Do not overwrite
|
|
|
20
20
|
## Cursor
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
|
-
Read FIRST_TIME_INIT.md and .cursor/rules. Initialize backbone.yml. Do not replace existing Cursor rules; add missing Minimal Vibe Coding Kit rules only.
|
|
23
|
+
Read .vibekit/init/FIRST_TIME_INIT.md and .cursor/rules. Initialize backbone.yml. Do not replace existing Cursor rules; add missing Minimal Vibe Coding Kit rules only.
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Codex
|
|
27
27
|
|
|
28
28
|
```text
|
|
29
|
-
Read AGENTS.md and FIRST_TIME_INIT.md. Use the vibekit-init skill if available. Initialize backbone.yml, include inferred project conventions, keep AGENTS.md concise, and wait for approval before writing.
|
|
29
|
+
Read AGENTS.md and .vibekit/init/FIRST_TIME_INIT.md. Use the vibekit-init skill if available. Initialize backbone.yml, include inferred project conventions, keep AGENTS.md concise, and wait for approval before writing.
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## Autoresearch improvement loop for this kit
|
|
@@ -34,9 +34,9 @@ Read AGENTS.md and FIRST_TIME_INIT.md. Use the vibekit-init skill if available.
|
|
|
34
34
|
```text
|
|
35
35
|
Use the autoresearch-coding skill.
|
|
36
36
|
Goal: improve this Minimal Vibe Coding Kit for existing projects in any language.
|
|
37
|
-
Metric command: node .
|
|
37
|
+
Metric command: node .vibekit/scripts/validate-kit.mjs .
|
|
38
38
|
Direction: higher.
|
|
39
|
-
Editable paths: README.md .
|
|
39
|
+
Editable paths: README.md .vibekit/docs .vibekit/scripts skills .vibekit/commands .claude .cursor .agents .codex-plugin .github backbone.yml AGENTS.md .vibekit/init/CLAUDE-template.md .vibekit/init/FIRST_TIME_INIT.md package.json install.sh install.ps1.
|
|
40
40
|
Protected paths: .git .env* node_modules vendor secrets lockfiles.
|
|
41
41
|
Budget: 3.
|
|
42
42
|
```
|
|
@@ -50,5 +50,5 @@ Use the agentshield-security-review skill. Run the read-only probe first. Then,
|
|
|
50
50
|
## Daily improvement prompt
|
|
51
51
|
|
|
52
52
|
```text
|
|
53
|
-
Use the daily-workflow-curator skill. Run node .
|
|
53
|
+
Use the daily-workflow-curator skill. Run node .vibekit/scripts/daily-enhance.mjs . --write-report and node .vibekit/scripts/validate-kit.mjs . Then propose updates to skills, rules, workflows, and backbone.yml. Do not write any change until I approve a diff.
|
|
54
54
|
```
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# FIRST_TIME_INIT.md - bootstrap runbook
|
|
1
|
+
# .vibekit/init/FIRST_TIME_INIT.md - bootstrap runbook
|
|
2
2
|
|
|
3
3
|
Audience: Claude, Cursor, Codex, or any AI coding agent in a repo that just received Minimal Vibe Coding Kit.
|
|
4
4
|
|
|
5
|
-
Keep this flow short. Detailed schema notes live in `.
|
|
5
|
+
Keep this flow short. Detailed schema notes live in `.vibekit/docs/BACKBONE_REFERENCE.md`.
|
|
6
6
|
|
|
7
7
|
## Requirements to print before starting
|
|
8
8
|
|
|
@@ -10,17 +10,17 @@ Before writing anything, print this checklist and mark each item as found, missi
|
|
|
10
10
|
|
|
11
11
|
1. `backbone.yml` exists.
|
|
12
12
|
2. `AGENTS.md` exists or will be created/merged.
|
|
13
|
-
3. `CLAUDE.md` exists or will be created from
|
|
13
|
+
3. `CLAUDE.md` exists or will be created from `.vibekit/init/CLAUDE-template.md` when Claude support is installed.
|
|
14
14
|
4. At least one harness folder exists: `.claude/`, `.cursor/`, `.agents/`, or `.codex-plugin/`.
|
|
15
15
|
5. Git status is known. If user changes exist, do not overwrite them.
|
|
16
|
-
6. A validation command is inferred or set to `node .
|
|
16
|
+
6. A validation command is inferred or set to `node .vibekit/scripts/validate-kit.mjs .` for the kit itself.
|
|
17
17
|
7. Protected paths include `.env*`, secrets, lockfiles, generated files, build output, migrations, and infra unless the user says otherwise.
|
|
18
18
|
8. Existing naming, architecture, resource, and localization conventions are scanned or marked missing.
|
|
19
19
|
|
|
20
20
|
## Canonical prompt
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
|
-
Read FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit.
|
|
23
|
+
Read .vibekit/init/FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit.
|
|
24
24
|
First print the requirements you will check. Then run detection, propose one diff for backbone.yml and managed instruction blocks, and wait for my yes before writing.
|
|
25
25
|
Include inferred project conventions for naming, architecture, resources, localization, generated definitions, and per-app/package differences.
|
|
26
26
|
After approval, write the files, run validation, and summarize what changed.
|
|
@@ -64,11 +64,43 @@ Ask (keep it short):
|
|
|
64
64
|
|
|
65
65
|
Then:
|
|
66
66
|
|
|
67
|
-
- If `project.prd` is `none`, propose creating `.
|
|
67
|
+
- If `project.prd` is `none`, propose creating `.vibekit/docs/PRD.md` from `.vibekit/docs/templates/PRD_TEMPLATE.md` using the answers, and set `project.prd` to that path in the same diff.
|
|
68
68
|
- If a PRD already exists, read it, link it in `project.prd`, and offer to refresh it without overwriting unapproved content.
|
|
69
|
-
- Record domain terms and acronyms in `.
|
|
69
|
+
- Record domain terms and acronyms in `.vibekit/docs/CONTEXT.md` (scaffold from `.vibekit/docs/templates/CONTEXT_TEMPLATE.md`) and link it in `project.context`, so future agents stay concise.
|
|
70
70
|
- Keep the PRD short: it captures intent and focus, not a full specification.
|
|
71
71
|
|
|
72
|
+
## Setup preferences
|
|
73
|
+
|
|
74
|
+
Ask these two questions right after the PRD interview. Persist both answers as `backbone.yml` `conventions.custom_rules` entries in the same proposed diff.
|
|
75
|
+
|
|
76
|
+
### 1. Safe delete (trash instead of rm)
|
|
77
|
+
|
|
78
|
+
1. Detect first: run `command -v trash` (read-only).
|
|
79
|
+
2. If `trash` is available, ask: "Use `trash` instead of `rm` for deletions so they are recoverable? (recommended: yes)"
|
|
80
|
+
3. If `trash` is missing, recommend installing it, then ask the same question:
|
|
81
|
+
- macOS 14 or newer: already built in at `/usr/bin/trash`, nothing to install.
|
|
82
|
+
- Older macOS: `brew install trash` (https://formulae.brew.sh/formula/trash)
|
|
83
|
+
- Linux: `sudo apt install trash-cli` or `pip install trash-cli` (https://github.com/andreafrancia/trash-cli)
|
|
84
|
+
- Any OS with Node.js: `npm install --global trash-cli` (https://github.com/sindresorhus/trash-cli)
|
|
85
|
+
4. Record the answer as a custom rule:
|
|
86
|
+
- yes: `Deletion safety: use trash instead of rm; permanent deletes require explicit approval of the exact paths.`
|
|
87
|
+
- no: `Deletion safety: user declined trash; list the exact paths and wait for approval before any rm.`
|
|
88
|
+
|
|
89
|
+
### 2. Default coding level
|
|
90
|
+
|
|
91
|
+
Show this table exactly and ask: "Which explanation level should I use by default? Reply 0-5. You can change it anytime with `/coding-level N`."
|
|
92
|
+
|
|
93
|
+
| N | Level | Short description |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| 0 | ELI5 | New to code. Everything in plain words, no jargon. |
|
|
96
|
+
| 1 | Junior | Knows the basics. Explains the why behind every step. |
|
|
97
|
+
| 2 | Mid-level | Comfortable coder. Patterns, architecture, trade-offs. |
|
|
98
|
+
| 3 | Senior | Concise. Trade-offs, edge cases, operational concerns. |
|
|
99
|
+
| 4 | Tech Lead | Strategic. Risk, ROI, team and organizational impact. |
|
|
100
|
+
| 5 | God | Expert peer. Minimal explanation, maximum signal. |
|
|
101
|
+
|
|
102
|
+
Record the answer as a custom rule: `Default coding level: N (<Level>) - apply this explanation depth every session; change with /coding-level N.`
|
|
103
|
+
|
|
72
104
|
## FIRST_TIME_INIT_RULES
|
|
73
105
|
|
|
74
106
|
Create project rules from evidence in the existing repo, not from a fixed language or framework template.
|
|
@@ -85,7 +117,7 @@ Create project rules from evidence in the existing repo, not from a fixed langua
|
|
|
85
117
|
Optional helper:
|
|
86
118
|
|
|
87
119
|
```bash
|
|
88
|
-
node .
|
|
120
|
+
node .vibekit/scripts/init-backbone.mjs . --propose
|
|
89
121
|
```
|
|
90
122
|
|
|
91
123
|
## Propose before writing
|
|
@@ -117,14 +149,14 @@ Apply this proposed backbone and convention rules? Reply yes, edit, or abort.
|
|
|
117
149
|
CLI helper after approval:
|
|
118
150
|
|
|
119
151
|
```bash
|
|
120
|
-
node .
|
|
152
|
+
node .vibekit/scripts/init-backbone.mjs . --write --yes
|
|
121
153
|
```
|
|
122
154
|
|
|
123
155
|
## Merge rules
|
|
124
156
|
|
|
125
157
|
### CLAUDE.md
|
|
126
158
|
|
|
127
|
-
- If no `CLAUDE.md` exists, copy
|
|
159
|
+
- If no `CLAUDE.md` exists, copy `.vibekit/init/CLAUDE-template.md` to `CLAUDE.md`.
|
|
128
160
|
- If `CLAUDE.md` exists, append or replace only this managed block:
|
|
129
161
|
|
|
130
162
|
```markdown
|
|
@@ -134,7 +166,7 @@ node .vbkit-scripts/init-backbone.mjs . --write --yes
|
|
|
134
166
|
## Minimal Vibe Coding Kit
|
|
135
167
|
|
|
136
168
|
- Read `backbone.yml` before changing code.
|
|
137
|
-
- If `meta.template_status` is `uninitialized`, follow
|
|
169
|
+
- If `meta.template_status` is `uninitialized`, follow `.vibekit/init/FIRST_TIME_INIT.md` and wait for approval before writing.
|
|
138
170
|
- After init, follow `backbone.yml` `conventions` before adding new project patterns.
|
|
139
171
|
- Prefer project skills for multi-step workflows: `/autoresearch-coding`, `/security-scan`, `/daily-enhance`.
|
|
140
172
|
<!-- END: minimal-vibe-coding-kit -->
|
|
@@ -150,10 +182,10 @@ node .vbkit-scripts/init-backbone.mjs . --write --yes
|
|
|
150
182
|
|
|
151
183
|
Once init is `initialized` and the first prompt is complete, the bootstrap files are no longer needed in the project. Offer to graduate them so the repo stays clean.
|
|
152
184
|
|
|
153
|
-
- Preview: `node .
|
|
154
|
-
- Apply after the user agrees: `node .
|
|
185
|
+
- Preview: `node .vibekit/scripts/vibekit-finalize.mjs . --propose`
|
|
186
|
+
- Apply after the user agrees: `node .vibekit/scripts/vibekit-finalize.mjs . --write --yes`
|
|
155
187
|
|
|
156
|
-
This moves one-time files (
|
|
188
|
+
This moves one-time files (`.vibekit/init/FIRST_TIME_INIT.md`, `.vibekit/init/FIRST_PROMPT.md`, `.vibekit/init/PUSH_TO_GITHUB.md`, `.vibekit/init/CLAUDE-template.md` once `CLAUDE.md` exists) into the folder named by `automation.finalize.cleanup_dir` (default `_vibekit-cleanup/`), writes a `RESTORE.md`, and sets `automation.finalize.marker`. It is idempotent, reversible with `--restore --write`, and refuses to run on the kit source repo. The durable project map is `backbone.yml`; none of the graduated files are needed to keep working. Delete the cleanup folder when satisfied.
|
|
157
189
|
|
|
158
190
|
## Guardrails
|
|
159
191
|
|
|
@@ -5,7 +5,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
5
5
|
|
|
6
6
|
const target = path.resolve(process.argv[2] || process.cwd());
|
|
7
7
|
const extra = process.argv.slice(3);
|
|
8
|
-
const probe = path.join(target, 'skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
|
|
8
|
+
const probe = path.join(target, '.vibekit/skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
|
|
9
9
|
|
|
10
10
|
if (!fs.existsSync(probe)) {
|
|
11
11
|
console.error(`AgentShield probe not found: ${path.relative(target, probe)}`);
|
|
@@ -25,17 +25,17 @@ function list(dir) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const checks = [];
|
|
28
|
-
for (const rel of ['backbone.yml', 'AGENTS.md', 'FIRST_TIME_INIT.md', 'skills/autoresearch-coding/SKILL.md', 'skills/agentshield-security-review/SKILL.md']) {
|
|
28
|
+
for (const rel of ['backbone.yml', 'AGENTS.md', '.vibekit/init/FIRST_TIME_INIT.md', '.vibekit/skills/autoresearch-coding/SKILL.md', '.vibekit/skills/agentshield-security-review/SKILL.md']) {
|
|
29
29
|
checks.push(`- ${rel}: ${exists(rel) ? 'found' : 'missing'}`);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const skills = list('skills').filter((f) => f.endsWith('SKILL.md'));
|
|
32
|
+
const skills = list('.vibekit/skills').filter((f) => f.endsWith('SKILL.md'));
|
|
33
33
|
const claudeSkills = list('.claude/skills').filter((f) => f.endsWith('SKILL.md'));
|
|
34
34
|
const codexSkills = list('.agents/skills').filter((f) => f.endsWith('SKILL.md'));
|
|
35
35
|
const cursorRules = list('.cursor/rules').filter((f) => f.endsWith('.mdc'));
|
|
36
36
|
|
|
37
37
|
let validation = 'not run';
|
|
38
|
-
const validator = path.join(target, '.
|
|
38
|
+
const validator = path.join(target, '.vibekit/scripts/validate-kit.mjs');
|
|
39
39
|
if (fs.existsSync(validator)) {
|
|
40
40
|
const result = spawnSync(process.execPath, [validator, target], { encoding: 'utf8' });
|
|
41
41
|
validation = result.stdout.trim() || result.stderr.trim() || `exit ${result.status}`;
|
|
@@ -122,7 +122,7 @@ function runNodeScript(rel, extra = []) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
function runProbe() {
|
|
125
|
-
const nodeProbeRel = '.
|
|
125
|
+
const nodeProbeRel = '.vibekit/scripts/agentshield-probe.mjs';
|
|
126
126
|
const nodeProbe = path.join(target, nodeProbeRel);
|
|
127
127
|
if (fs.existsSync(nodeProbe)) {
|
|
128
128
|
const result = spawnSync(process.execPath, [nodeProbe, target, '--json'], { encoding: 'utf8' });
|
|
@@ -134,7 +134,7 @@ function runProbe() {
|
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
const probe = path.join(target, 'skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
|
|
137
|
+
const probe = path.join(target, '.vibekit/skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
|
|
138
138
|
if (!fs.existsSync(probe)) return { found: false, status: null, output: 'missing' };
|
|
139
139
|
for (const python of ['python', 'python3']) {
|
|
140
140
|
const result = spawnSync(python, [probe, target, '--json'], { encoding: 'utf8' });
|
|
@@ -153,6 +153,13 @@ function statusLine(ok, label, detail) {
|
|
|
153
153
|
return `${ok ? 'PASS' : 'WARN'} ${label}${detail ? ` - ${detail}` : ''}`;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
const TRASH_INSTALL_HINT = 'macOS 14+ has it built in; older macOS: brew install trash; Linux: sudo apt install trash-cli; any OS with Node: npm i -g trash-cli';
|
|
157
|
+
|
|
158
|
+
function trashAvailable() {
|
|
159
|
+
const result = spawnSync('trash', ['--help'], { encoding: 'utf8' });
|
|
160
|
+
return !(result.error && result.error.code === 'ENOENT');
|
|
161
|
+
}
|
|
162
|
+
|
|
156
163
|
const backbone = parseBackbone();
|
|
157
164
|
const packageJson = readJson('package.json');
|
|
158
165
|
const isKitTemplate = packageJson?.name === 'minimal-vibe-coding-kit';
|
|
@@ -161,7 +168,7 @@ const kitVersion = isKitTemplate
|
|
|
161
168
|
: exists('.vibekit/KIT_VERSION') ? read('.vibekit/KIT_VERSION').trim() : 'unknown';
|
|
162
169
|
const surfaces = {
|
|
163
170
|
agents: exists('AGENTS.md'),
|
|
164
|
-
claude: exists('CLAUDE.md') || exists('CLAUDE-template.md') || exists('.claude'),
|
|
171
|
+
claude: exists('CLAUDE.md') || exists('.vibekit/init/CLAUDE-template.md') || exists('.claude'),
|
|
165
172
|
cursor: exists('.cursor/rules'),
|
|
166
173
|
codex: exists('.agents') || exists('.codex-plugin/plugin.json')
|
|
167
174
|
};
|
|
@@ -180,7 +187,7 @@ const legacySurfaces = [
|
|
|
180
187
|
].filter(exists);
|
|
181
188
|
const nativeReasoningSkills = ['clearthought', 'sequential-thinking', 'reviewing-4p-priorities'];
|
|
182
189
|
const nativeSkillSurfaces = {
|
|
183
|
-
shared: 'skills',
|
|
190
|
+
shared: '.vibekit/skills',
|
|
184
191
|
claude: '.claude/skills',
|
|
185
192
|
codex: '.agents/skills',
|
|
186
193
|
cursor: '.cursor/skills'
|
|
@@ -192,10 +199,13 @@ for (const [surface, dir] of Object.entries(nativeSkillSurfaces)) {
|
|
|
192
199
|
}
|
|
193
200
|
}
|
|
194
201
|
const commands = commandMap();
|
|
195
|
-
const validation = runNodeScript('.
|
|
202
|
+
const validation = runNodeScript('.vibekit/scripts/validate-kit.mjs');
|
|
196
203
|
const probe = runProbe();
|
|
204
|
+
const hasTrash = trashAvailable();
|
|
197
205
|
const risks = [];
|
|
198
206
|
|
|
207
|
+
if (!hasTrash) risks.push(`trash command not found; agents fall back to asking before rm. Install it for recoverable deletes (${TRASH_INSTALL_HINT}).`);
|
|
208
|
+
|
|
199
209
|
if (!backbone) risks.push('backbone.yml is missing.');
|
|
200
210
|
else if (backbone.templateStatus !== 'initialized' && !isKitTemplate) risks.push(`backbone.yml is ${backbone.templateStatus || 'unknown'}; run init before relying on it.`);
|
|
201
211
|
if (!Object.values(surfaces).some(Boolean)) risks.push('No AI agent surfaces were detected.');
|
|
@@ -238,8 +248,12 @@ const report = {
|
|
|
238
248
|
command: probe.command,
|
|
239
249
|
status: probe.status
|
|
240
250
|
},
|
|
251
|
+
safeDelete: {
|
|
252
|
+
trashAvailable: hasTrash,
|
|
253
|
+
installHint: hasTrash ? null : TRASH_INSTALL_HINT
|
|
254
|
+
},
|
|
241
255
|
aiRulesLoaded: {
|
|
242
|
-
sharedSkills: listFiles('skills').filter((f) => f.endsWith('SKILL.md')).length,
|
|
256
|
+
sharedSkills: listFiles('.vibekit/skills').filter((f) => f.endsWith('SKILL.md')).length,
|
|
243
257
|
claudeSkills: listFiles('.claude/skills').filter((f) => f.endsWith('SKILL.md')).length,
|
|
244
258
|
codexSkills: listFiles('.agents/skills').filter((f) => f.endsWith('SKILL.md')).length,
|
|
245
259
|
cursorSkills: listFiles('.cursor/skills').filter((f) => f.endsWith('SKILL.md')).length,
|
|
@@ -256,7 +270,8 @@ function renderMarkdown(data) {
|
|
|
256
270
|
statusLine(Boolean(commands.validate), 'validation command detected', commands.validate || 'missing'),
|
|
257
271
|
statusLine(protectedSane, 'protected paths are sane', `${data.protectedPaths.length} entries`),
|
|
258
272
|
statusLine(validation.found && validation.status === 0, 'validation runs', validation.found ? `exit ${validation.status}` : 'missing'),
|
|
259
|
-
statusLine(probe.found && probe.status === 0, 'AgentShield probe runs', probe.found ? `exit ${probe.status}` : 'missing')
|
|
273
|
+
statusLine(probe.found && probe.status === 0, 'AgentShield probe runs', probe.found ? `exit ${probe.status}` : 'missing'),
|
|
274
|
+
statusLine(hasTrash, 'trash command available for safe deletes', hasTrash ? 'deletions are recoverable' : TRASH_INSTALL_HINT)
|
|
260
275
|
];
|
|
261
276
|
|
|
262
277
|
return `# Vibe Report
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
4
5
|
|
|
5
6
|
const args = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
function trashAvailable() {
|
|
9
|
+
const result = spawnSync('trash', ['--help'], { encoding: 'utf8' });
|
|
10
|
+
return !(result.error && result.error.code === 'ENOENT');
|
|
11
|
+
}
|
|
6
12
|
const shouldWrite = args.includes('--write');
|
|
7
13
|
const yes = args.includes('--yes');
|
|
8
14
|
|
|
@@ -92,22 +98,22 @@ function cleanName(name) {
|
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
function isKitManagedPath(file) {
|
|
95
|
-
const managedRoots = new Set(['.claude', '.cursor', '.agents', '.codex', '.codex-plugin', '
|
|
101
|
+
const managedRoots = new Set(['.claude', '.cursor', '.agents', '.codex', '.codex-plugin', '.vibekit']);
|
|
96
102
|
const managedFiles = new Set([
|
|
97
103
|
'AGENTS.md',
|
|
98
|
-
'CLAUDE-template.md',
|
|
99
|
-
'FIRST_PROMPT.md',
|
|
100
|
-
'FIRST_TIME_INIT.md',
|
|
104
|
+
'.vibekit/init/CLAUDE-template.md',
|
|
105
|
+
'.vibekit/init/FIRST_PROMPT.md',
|
|
106
|
+
'.vibekit/init/FIRST_TIME_INIT.md',
|
|
101
107
|
'backbone.yml',
|
|
102
|
-
'.
|
|
103
|
-
'.
|
|
104
|
-
'.
|
|
105
|
-
'.
|
|
106
|
-
'.
|
|
107
|
-
'.
|
|
108
|
-
'.
|
|
109
|
-
'.
|
|
110
|
-
'.
|
|
108
|
+
'.vibekit/scripts/mvck.mjs',
|
|
109
|
+
'.vibekit/scripts/init-backbone.mjs',
|
|
110
|
+
'.vibekit/scripts/daily-enhance.mjs',
|
|
111
|
+
'.vibekit/scripts/validate-kit.mjs',
|
|
112
|
+
'.vibekit/scripts/doctor.mjs',
|
|
113
|
+
'.vibekit/scripts/test-install.mjs',
|
|
114
|
+
'.vibekit/scripts/agentshield-probe.mjs',
|
|
115
|
+
'.vibekit/scripts/pack-dry-run.mjs',
|
|
116
|
+
'.vibekit/scripts/vibekit-finalize.mjs'
|
|
111
117
|
]);
|
|
112
118
|
const root = file.split('/')[0];
|
|
113
119
|
return managedRoots.has(root) || managedFiles.has(file);
|
|
@@ -514,10 +520,10 @@ function detectConventions(files, type) {
|
|
|
514
520
|
}
|
|
515
521
|
|
|
516
522
|
const PRD_CANDIDATES = [
|
|
517
|
-
'PRD.md', '.
|
|
518
|
-
'REQUIREMENTS.md', '.
|
|
519
|
-
'SPEC.md', '.
|
|
520
|
-
'PRODUCT.md', '.
|
|
523
|
+
'PRD.md', '.vibekit/docs/PRD.md', 'prd.md', '.vibekit/docs/prd.md',
|
|
524
|
+
'REQUIREMENTS.md', '.vibekit/docs/REQUIREMENTS.md',
|
|
525
|
+
'SPEC.md', '.vibekit/docs/SPEC.md', '.vibekit/docs/spec.md',
|
|
526
|
+
'PRODUCT.md', '.vibekit/docs/PRODUCT.md'
|
|
521
527
|
];
|
|
522
528
|
|
|
523
529
|
function countCodeFiles(files) {
|
|
@@ -538,7 +544,7 @@ function detectPrd(files) {
|
|
|
538
544
|
}
|
|
539
545
|
|
|
540
546
|
function detectContext() {
|
|
541
|
-
for (const candidate of ['.
|
|
547
|
+
for (const candidate of ['.vibekit/docs/CONTEXT.md', 'CONTEXT.md', '.vibekit/docs/context.md']) {
|
|
542
548
|
if (fileExists(candidate)) return candidate;
|
|
543
549
|
}
|
|
544
550
|
return 'none';
|
|
@@ -547,7 +553,7 @@ function detectContext() {
|
|
|
547
553
|
function render(data) {
|
|
548
554
|
const cmd = data.commands;
|
|
549
555
|
const rules = data.conventions;
|
|
550
|
-
return `# Minimal Vibe Coding Kit backbone. See .
|
|
556
|
+
return `# Minimal Vibe Coding Kit backbone. See .vibekit/docs/BACKBONE_REFERENCE.md for details.\nversion: 2\nmeta:\n template_status: initialized\n initialized_at: ${yamlString(data.initializedAt)}\n template_source: minimal-vibe-coding-kit\n schema_version: 3\n init_runbook: .vibekit/init/FIRST_TIME_INIT.md\n init_done_marker: .vibekit/INIT_DONE\n\nproject:\n name: ${yamlString(data.name)}\n description: ${yamlString(data.description)}\n type: ${data.type}\n primary_language: ${data.language}\n package_manager: ${data.packageManager}\n mode: ${data.mode}\n prd: ${yamlString(data.prd)}\n context: ${yamlString(data.context)}\n\npaths:\n root: .\n apps:${yamlList(data.appPaths, 4)}\n source: ${JSON.stringify(data.sourcePaths)}\n tests: ${JSON.stringify(data.testPaths)}\n docs: [README.md, .vibekit/docs/]\n generated: [node_modules/, dist/, build/, coverage/]\n\nconventions:\n review_required_before_write: true\n scope: ${yamlString(rules.scope)}\n naming:\n files: ${yamlString(rules.naming.files)}\n directories: ${yamlString(rules.naming.directories)}\n symbols: follow existing language and framework conventions in nearby code\n evidence:${yamlList(rules.naming.evidence, 6)}\n architecture:\n detected:${yamlList(rules.architecture.detected, 6)}\n rule: ${yamlString(rules.architecture.rule)}\n resources:\n detected_asset_roots:${yamlList(rules.resources.assetRoots, 6)}\n detected_registries:${yamlList(rules.resources.registries, 6)}\n rule: ${yamlString(rules.resources.rule)}\n localization:\n detected_catalogs:${yamlList(rules.localization.catalogs, 6)}\n detected_accessors:${yamlList(rules.localization.accessors, 6)}\n rule: ${yamlString(rules.localization.rule)}\n custom_rules:\n - Add team-specific rules here during init review; future agents must follow them.\n\ncommands:\n install: ${yamlString(cmd.install)}\n test: ${yamlString(cmd.test)}\n lint: ${yamlString(cmd.lint)}\n typecheck: ${yamlString(cmd.typecheck)}\n build: ${yamlString(cmd.build)}\n validate: ${yamlString(cmd.validate)}\n\npolicy:\n default_branch: main\n branch_naming: "feat/<short-topic>"\n commit_style: conventional\n editable_paths: [.]\n protected_paths:\n - .git/\n - .env*\n - "**/*secret*"\n - "**/*token*"\n - "**/migrations/**"\n - "**/node_modules/**"\n - "**/dist/**"\n - "**/build/**"\n - "**/coverage/**"\n - "**/*lock*"\n\nagent_surfaces:\n claude: .claude/\n cursor: .cursor/\n codex: .agents/\n codex_plugin: .codex-plugin/plugin.json\n shared_skills: .vibekit/skills/\n shared_commands: .vibekit/commands/\n\nautomation:\n autoresearch:\n results_file: results.tsv\n logs_dir: .autoresearch/logs\n default_budget: 3\n default_timeout_seconds: 600\n daily_enhance:\n report_dir: .vibekit/reports\n write_mode: propose_only\n finalize:\n cleanup_dir: _vibekit-cleanup\n marker: .vibekit/FINALIZE_DONE\n one_time_files: [.vibekit/init/FIRST_TIME_INIT.md, .vibekit/init/FIRST_PROMPT.md, .vibekit/init/PUSH_TO_GITHUB.md, .vibekit/init/CLAUDE-template.md]\n security:\n probe: node .vibekit/scripts/agentshield-probe.mjs .\n scan: npx ecc-agentshield scan --path . --format text --min-severity medium\n`;
|
|
551
557
|
}
|
|
552
558
|
|
|
553
559
|
function inferPaths(files) {
|
|
@@ -614,15 +620,18 @@ if (shouldWrite) {
|
|
|
614
620
|
console.log('- What are the key constraints or non-goals?');
|
|
615
621
|
if (inferred.mode === 'brownfield') console.log('- Which existing area should we focus on improving first?');
|
|
616
622
|
console.log(inferred.prd === 'none'
|
|
617
|
-
? '- Offer to create .
|
|
623
|
+
? '- Offer to create .vibekit/docs/PRD.md from .vibekit/docs/templates/PRD_TEMPLATE.md using the answers.'
|
|
618
624
|
: `- Offer to refresh ${inferred.prd} with the answers; do not overwrite without approval.`);
|
|
619
625
|
console.log(inferred.context === 'none'
|
|
620
|
-
? '- Offer to create .
|
|
626
|
+
? '- Offer to create .vibekit/docs/CONTEXT.md (glossary) from .vibekit/docs/templates/CONTEXT_TEMPLATE.md.'
|
|
621
627
|
: `- CONTEXT glossary found at ${inferred.context}; keep it current.`);
|
|
628
|
+
console.log('\nSetup preferences (record answers in conventions.custom_rules; see FIRST_TIME_INIT.md "Setup preferences"):');
|
|
629
|
+
console.log(`- Safe delete: trash command ${trashAvailable() ? 'available' : 'NOT found (recommend: macOS 14+ built-in; older macOS `brew install trash`; Linux `sudo apt install trash-cli`; any OS `npm i -g trash-cli`)'} - ask: use trash instead of rm? (recommended: yes)`);
|
|
630
|
+
console.log('- Default coding level: ask 0-5 (0 ELI5, 1 Junior, 2 Mid-level, 3 Senior, 4 Tech Lead, 5 God); changeable later with /coding-level N.');
|
|
622
631
|
console.log('\nConvention review questions:');
|
|
623
632
|
for (const question of inferred.conventions.reviewQuestions) console.log(`- ${question}`);
|
|
624
633
|
console.log('\nProposed backbone.yml:\n');
|
|
625
634
|
console.log(out);
|
|
626
635
|
console.log('Apply this proposed backbone and convention rules? Reply yes, edit, or abort.');
|
|
627
|
-
console.log('To write it after approval, run: node .
|
|
636
|
+
console.log('To write it after approval, run: node .vibekit/scripts/init-backbone.mjs . --write --yes');
|
|
628
637
|
}
|
|
@@ -6,7 +6,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
9
|
-
const kitRoot = path.resolve(__dirname, '..');
|
|
9
|
+
const kitRoot = path.resolve(__dirname, '..', '..');
|
|
10
10
|
const args = process.argv.slice(2);
|
|
11
11
|
|
|
12
12
|
function usage() {
|
|
@@ -22,12 +22,12 @@ Usage:
|
|
|
22
22
|
mvck finalize [target] [--write --yes] [--restore] [--json]
|
|
23
23
|
|
|
24
24
|
Examples:
|
|
25
|
-
node .
|
|
25
|
+
node .vibekit/scripts/mvck.mjs install ~/work/my-repo --profile all
|
|
26
26
|
npx --yes minimal-vibe-coding-kit@latest update .
|
|
27
|
-
node .
|
|
28
|
-
node .
|
|
29
|
-
node .
|
|
30
|
-
node .
|
|
27
|
+
node .vibekit/scripts/mvck.mjs init . --propose
|
|
28
|
+
node .vibekit/scripts/mvck.mjs doctor .
|
|
29
|
+
node .vibekit/scripts/mvck.mjs validate .
|
|
30
|
+
node .vibekit/scripts/mvck.mjs finalize .
|
|
31
31
|
|
|
32
32
|
update refreshes kit-owned files (skills, commands, rules, scripts, docs, agent
|
|
33
33
|
mirrors) to the running kit version. It never overwrites user-owned files
|
|
@@ -98,13 +98,14 @@ function copyFileSafe(srcRel, destRel, target, { force = false, dryRun = false }
|
|
|
98
98
|
return { action: fs.existsSync(dest) && force ? 'replace' : 'copy', path: destRel ?? srcRel };
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function copyDirSafe(srcRel, destRel, target, { force = false, dryRun = false } = {}) {
|
|
101
|
+
function copyDirSafe(srcRel, destRel, target, { force = false, dryRun = false, exclude = [] } = {}) {
|
|
102
102
|
const src = path.join(kitRoot, srcRel);
|
|
103
103
|
const destRoot = path.join(target, destRel ?? srcRel);
|
|
104
104
|
if (!fs.existsSync(src)) throw new Error(`Missing source dir: ${srcRel}`);
|
|
105
105
|
let copied = 0;
|
|
106
106
|
let skipped = 0;
|
|
107
107
|
function copyRecursive(from, to) {
|
|
108
|
+
if (exclude.includes(path.relative(src, from).replaceAll(path.sep, '/'))) return;
|
|
108
109
|
const stat = fs.statSync(from);
|
|
109
110
|
if (stat.isDirectory()) {
|
|
110
111
|
if (!dryRun) fs.mkdirSync(to, { recursive: true });
|
|
@@ -149,19 +150,30 @@ function managedBlockFromTemplate(block, begin, end) {
|
|
|
149
150
|
return `${begin}\n${block.trim()}\n${end}`;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
const KIT_SEED_FILES = ['FIRST_TIME_INIT.md', 'FIRST_PROMPT.md', 'CLAUDE-template.md', 'backbone.yml'];
|
|
153
|
-
const KIT_SHARED_DIRS = ['skills', '.
|
|
153
|
+
const KIT_SEED_FILES = ['.vibekit/init/FIRST_TIME_INIT.md', '.vibekit/init/FIRST_PROMPT.md', '.vibekit/init/CLAUDE-template.md', 'backbone.yml'];
|
|
154
|
+
const KIT_SHARED_DIRS = ['.vibekit/skills', '.vibekit/commands', '.vibekit/docs'];
|
|
155
|
+
// Kit-maintainer files that end-user repos do not need; never copied by install/update.
|
|
156
|
+
const KIT_DOC_EXCLUDES = ['RESEARCH_NOTES.md', 'AUTORESEARCH_LEDGER.md'];
|
|
154
157
|
const KIT_SCRIPTS = [
|
|
155
|
-
'.
|
|
156
|
-
'.
|
|
158
|
+
'.vibekit/scripts/mvck.mjs', '.vibekit/scripts/init-backbone.mjs', '.vibekit/scripts/daily-enhance.mjs', '.vibekit/scripts/validate-kit.mjs',
|
|
159
|
+
'.vibekit/scripts/doctor.mjs', '.vibekit/scripts/agentshield-probe.mjs', '.vibekit/scripts/vibekit-finalize.mjs'
|
|
157
160
|
];
|
|
161
|
+
const VALID_PROFILES = new Set(['claude', 'cursor', 'codex']);
|
|
162
|
+
|
|
163
|
+
function parseProfiles(profileRaw) {
|
|
164
|
+
const profiles = new Set(profileRaw === 'all' ? ['claude', 'cursor', 'codex'] : profileRaw.split(',').map((x) => x.trim()).filter(Boolean));
|
|
165
|
+
for (const p of profiles) {
|
|
166
|
+
if (!VALID_PROFILES.has(p)) throw new Error(`Unknown profile: ${p}. Valid values: all, claude, cursor, codex (comma-separated).`);
|
|
167
|
+
}
|
|
168
|
+
return profiles;
|
|
169
|
+
}
|
|
158
170
|
const CLAUDE_DIRS = ['.claude/agents', '.claude/commands', '.claude/rules'];
|
|
159
171
|
const CLAUDE_SKILLS = [
|
|
160
172
|
'autoresearch-coding', 'agentshield-security-review', 'daily-workflow-curator', 'vibekit-init', 'visual-design-loop',
|
|
161
|
-
'clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'memento', 'coding-level'
|
|
173
|
+
'clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'path-sensitive-shell-safety', 'memento', 'coding-level', 'parallel-analysis'
|
|
162
174
|
];
|
|
163
175
|
const CURSOR_DIRS = ['.cursor/rules', '.cursor/commands'];
|
|
164
|
-
const CURSOR_SKILLS = ['clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'memento', 'coding-level'];
|
|
176
|
+
const CURSOR_SKILLS = ['clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'path-sensitive-shell-safety', 'memento', 'coding-level', 'parallel-analysis'];
|
|
165
177
|
const CODEX_DIRS = ['.agents', '.codex', '.codex-plugin'];
|
|
166
178
|
const GITIGNORE_BLOCK = `# BEGIN: minimal-vibe-coding-kit\n.autoresearch/\nresults.tsv\n.vibekit/INIT_DONE\n.vibekit/FINALIZE_DONE\n.vibekit/reports/\n.vibekit/update-backup/\n_vibekit-cleanup/\nCLAUDE.local.md\n# END: minimal-vibe-coding-kit`;
|
|
167
179
|
|
|
@@ -187,9 +199,9 @@ function applyManagedBlocks(target, profiles, actions, { dryRun = false } = {})
|
|
|
187
199
|
if (profiles.has('claude')) {
|
|
188
200
|
const claudeTarget = path.join(target, 'CLAUDE.md');
|
|
189
201
|
if (!fs.existsSync(claudeTarget)) {
|
|
190
|
-
actions.push(copyFileSafe('CLAUDE-template.md', 'CLAUDE.md', target, { force: false, dryRun }));
|
|
202
|
+
actions.push(copyFileSafe('.vibekit/init/CLAUDE-template.md', 'CLAUDE.md', target, { force: false, dryRun }));
|
|
191
203
|
} else {
|
|
192
|
-
const block = `<!-- BEGIN: minimal-vibe-coding-kit -->\n@AGENTS.md\n\n## Minimal Vibe Coding Kit\n\n- Read \`backbone.yml\` before changing code.\n- If \`meta.template_status\` is \`uninitialized\`, follow
|
|
204
|
+
const block = `<!-- BEGIN: minimal-vibe-coding-kit -->\n@AGENTS.md\n\n## Minimal Vibe Coding Kit\n\n- Read \`backbone.yml\` before changing code.\n- If \`meta.template_status\` is \`uninitialized\`, follow \`.vibekit/init/FIRST_TIME_INIT.md\` and wait for approval before writing.\n- After init, follow \`backbone.yml\` \`conventions\` before adding new project patterns.\n- Prefer project skills for multi-step workflows: \`/autoresearch-coding\`, \`/security-scan\`, \`/daily-enhance\`.\n<!-- END: minimal-vibe-coding-kit -->`;
|
|
193
205
|
appendManagedBlock(claudeTarget, block, '<!-- BEGIN: minimal-vibe-coding-kit -->', '<!-- END: minimal-vibe-coding-kit -->', { dryRun });
|
|
194
206
|
actions.push({ action: 'managed-block', path: 'CLAUDE.md' });
|
|
195
207
|
}
|
|
@@ -213,8 +225,7 @@ function install() {
|
|
|
213
225
|
const dryRun = hasFlag('--dry-run');
|
|
214
226
|
const json = hasFlag('--json');
|
|
215
227
|
const target = parseTargetAndFlags('install', { valueFlags: ['--profile'] }).target;
|
|
216
|
-
const
|
|
217
|
-
const profiles = new Set(profileRaw === 'all' ? ['claude', 'cursor', 'codex'] : profileRaw.split(',').map((x) => x.trim()).filter(Boolean));
|
|
228
|
+
const profiles = parseProfiles(optionValue('--profile', 'all'));
|
|
218
229
|
|
|
219
230
|
if (!fs.existsSync(target)) throw new Error(`Target does not exist: ${target}`);
|
|
220
231
|
const actions = [];
|
|
@@ -224,7 +235,7 @@ function install() {
|
|
|
224
235
|
actions.push(copyFileSafe(file, file, target, opts));
|
|
225
236
|
}
|
|
226
237
|
for (const dir of KIT_SHARED_DIRS) {
|
|
227
|
-
actions.push(copyDirSafe(dir, dir, target, opts));
|
|
238
|
+
actions.push(copyDirSafe(dir, dir, target, dir === '.vibekit/docs' ? { ...opts, exclude: KIT_DOC_EXCLUDES } : opts));
|
|
228
239
|
}
|
|
229
240
|
for (const file of KIT_SCRIPTS) {
|
|
230
241
|
actions.push(copyFileSafe(file, file, target, opts));
|
|
@@ -258,7 +269,8 @@ function install() {
|
|
|
258
269
|
writeKitVersion(target, dryRun);
|
|
259
270
|
actions.push({ action: 'version-marker', path: '.vibekit/KIT_VERSION' });
|
|
260
271
|
|
|
261
|
-
const nextPrompt = 'Read FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit. Print requirements first, infer project conventions, propose a diff, and wait for my yes before writing.';
|
|
272
|
+
const nextPrompt = 'Read .vibekit/init/FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit. Print requirements first, infer project conventions, propose a diff, and wait for my yes before writing.';
|
|
273
|
+
const legacyPaths = detectLegacyLayout(target);
|
|
262
274
|
if (json) {
|
|
263
275
|
console.log(JSON.stringify({
|
|
264
276
|
status: dryRun ? 'dry-run' : 'installed',
|
|
@@ -267,6 +279,7 @@ function install() {
|
|
|
267
279
|
force,
|
|
268
280
|
dryRun,
|
|
269
281
|
actions,
|
|
282
|
+
legacyPaths,
|
|
270
283
|
nextPrompt
|
|
271
284
|
}, null, 2));
|
|
272
285
|
return;
|
|
@@ -274,10 +287,29 @@ function install() {
|
|
|
274
287
|
|
|
275
288
|
console.log(dryRun ? 'Dry-run install plan:' : 'Install complete:');
|
|
276
289
|
for (const a of actions) console.log(`- ${a.action}: ${a.path}`);
|
|
290
|
+
printLegacyLayoutNote(legacyPaths);
|
|
277
291
|
console.log('\nNext prompt:');
|
|
278
292
|
console.log(nextPrompt);
|
|
279
293
|
}
|
|
280
294
|
|
|
295
|
+
// Pre-0.4 installs placed kit dirs at the target root. Detection is advisory
|
|
296
|
+
// only: nothing is deleted automatically, and a root `skills/` dir is flagged
|
|
297
|
+
// only when it contains a known kit skill (it may be the user's own folder).
|
|
298
|
+
function detectLegacyLayout(target) {
|
|
299
|
+
const legacy = ['.vbkit-scripts', '.vbkit-commands', '.vbkit-docs',
|
|
300
|
+
'FIRST_TIME_INIT.md', 'FIRST_PROMPT.md', 'CLAUDE-template.md', 'PUSH_TO_GITHUB.md']
|
|
301
|
+
.filter((rel) => fs.existsSync(path.join(target, rel)));
|
|
302
|
+
if (fs.existsSync(path.join(target, 'skills', 'vibekit-init', 'SKILL.md'))) legacy.push('skills');
|
|
303
|
+
return legacy;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function printLegacyLayoutNote(legacy) {
|
|
307
|
+
if (!legacy.length) return;
|
|
308
|
+
console.log('\nLegacy kit layout detected (pre-0.4). Kit files now live under .vibekit/.');
|
|
309
|
+
console.log('After verifying the new .vibekit/ copies, remove or `git mv` these leftovers:');
|
|
310
|
+
for (const rel of legacy) console.log(`- ${rel}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
281
313
|
function updateFileSafe(srcRel, destRel, target, { dryRun = false, backup = null } = {}) {
|
|
282
314
|
const src = path.join(kitRoot, srcRel);
|
|
283
315
|
const dest = path.join(target, destRel ?? srcRel);
|
|
@@ -312,10 +344,12 @@ function updateFileSafe(srcRel, destRel, target, { dryRun = false, backup = null
|
|
|
312
344
|
function updateDirSafe(srcRel, target, opts) {
|
|
313
345
|
const src = path.join(kitRoot, srcRel);
|
|
314
346
|
if (!fs.existsSync(src)) throw new Error(`Missing source dir: ${srcRel}`);
|
|
347
|
+
const exclude = opts.exclude ?? [];
|
|
315
348
|
const results = [];
|
|
316
349
|
function walk(current) {
|
|
317
350
|
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
318
351
|
const child = path.join(current, entry.name);
|
|
352
|
+
if (exclude.includes(path.relative(src, child).replaceAll(path.sep, '/'))) continue;
|
|
319
353
|
if (entry.isDirectory()) walk(child);
|
|
320
354
|
else {
|
|
321
355
|
const rel = path.join(srcRel, path.relative(src, child)).replaceAll(path.sep, '/');
|
|
@@ -332,15 +366,14 @@ function update() {
|
|
|
332
366
|
const json = hasFlag('--json');
|
|
333
367
|
const noBackup = hasFlag('--no-backup');
|
|
334
368
|
const target = parseTargetAndFlags('update', { valueFlags: ['--profile'] }).target;
|
|
335
|
-
const
|
|
336
|
-
const profiles = new Set(profileRaw === 'all' ? ['claude', 'cursor', 'codex'] : profileRaw.split(',').map((x) => x.trim()).filter(Boolean));
|
|
369
|
+
const profiles = parseProfiles(optionValue('--profile', 'all'));
|
|
337
370
|
|
|
338
371
|
if (!fs.existsSync(target)) throw new Error(`Target does not exist: ${target}`);
|
|
339
372
|
if (fs.realpathSync(kitRoot) === fs.realpathSync(target)) {
|
|
340
373
|
throw new Error('Update source and target are the same directory. Run the update from a newer kit, e.g.: npx --yes minimal-vibe-coding-kit@latest update .');
|
|
341
374
|
}
|
|
342
|
-
if (!fs.existsSync(path.join(target, 'backbone.yml')) && !fs.existsSync(path.join(target, '.
|
|
343
|
-
throw new Error('Kit not detected in target (no backbone.yml or .
|
|
375
|
+
if (!fs.existsSync(path.join(target, 'backbone.yml')) && !fs.existsSync(path.join(target, '.vibekit/scripts'))) {
|
|
376
|
+
throw new Error('Kit not detected in target (no backbone.yml or .vibekit/scripts). Run mvck install first.');
|
|
344
377
|
}
|
|
345
378
|
|
|
346
379
|
const previousVersionFile = path.join(target, '.vibekit', 'KIT_VERSION');
|
|
@@ -352,7 +385,7 @@ function update() {
|
|
|
352
385
|
const actions = [];
|
|
353
386
|
|
|
354
387
|
// Kit-owned surfaces: refresh to the running kit version, never delete extras.
|
|
355
|
-
for (const dir of KIT_SHARED_DIRS) actions.push(...updateDirSafe(dir, target, opts));
|
|
388
|
+
for (const dir of KIT_SHARED_DIRS) actions.push(...updateDirSafe(dir, target, dir === '.vibekit/docs' ? { ...opts, exclude: KIT_DOC_EXCLUDES } : opts));
|
|
356
389
|
for (const file of KIT_SCRIPTS) actions.push(updateFileSafe(file, file, target, opts));
|
|
357
390
|
if (profiles.has('claude')) {
|
|
358
391
|
for (const dir of CLAUDE_DIRS) actions.push(...updateDirSafe(dir, target, opts));
|
|
@@ -381,6 +414,7 @@ function update() {
|
|
|
381
414
|
const backupInfo = backup && backup.count > 0 ? path.relative(target, backup.dir) : null;
|
|
382
415
|
const preserved = ['backbone.yml', 'CLAUDE.md', 'AGENTS.md content outside the managed block', '.claude/settings.json', '.cursor/settings.json'];
|
|
383
416
|
|
|
417
|
+
const legacyPaths = detectLegacyLayout(target);
|
|
384
418
|
if (json) {
|
|
385
419
|
console.log(JSON.stringify({
|
|
386
420
|
status: dryRun ? 'dry-run' : 'updated',
|
|
@@ -391,6 +425,7 @@ function update() {
|
|
|
391
425
|
summary,
|
|
392
426
|
backupDir: backupInfo,
|
|
393
427
|
preserved,
|
|
428
|
+
legacyPaths,
|
|
394
429
|
actions: actions.filter((a) => a.action !== 'unchanged')
|
|
395
430
|
}, null, 2));
|
|
396
431
|
return;
|
|
@@ -405,11 +440,12 @@ function update() {
|
|
|
405
440
|
console.log(`\nSummary: ${summary.add} added, ${summary.update} updated, ${summary.unchanged} unchanged.`);
|
|
406
441
|
if (backupInfo) console.log(`Backups of replaced files: ${backupInfo}/`);
|
|
407
442
|
console.log(`Preserved (never overwritten by update): ${preserved.join(', ')}.`);
|
|
443
|
+
printLegacyLayoutNote(legacyPaths);
|
|
408
444
|
}
|
|
409
445
|
|
|
410
446
|
function delegate(scriptName, { valueFlags = [] } = {}) {
|
|
411
447
|
const { target, flags } = parseTargetAndFlags(args[0], { valueFlags });
|
|
412
|
-
const script = path.join(kitRoot, '.
|
|
448
|
+
const script = path.join(kitRoot, '.vibekit/scripts', scriptName);
|
|
413
449
|
const childArgs = [script, target, ...flags];
|
|
414
450
|
const result = spawnSync(process.execPath, childArgs, { stdio: 'inherit' });
|
|
415
451
|
process.exit(result.status ?? 1);
|