@mobiman/vector 1.1.3 → 1.1.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/LICENSE +1 -1
- package/README.md +20 -2
- package/bin/install.cjs +38 -42
- package/bin/install.cjs.map +1 -1
- package/bin/install.cts +38 -42
- package/commands/vector/join-discord.md +1 -1
- package/core/bin/lib/init.cjs +4 -2
- package/core/bin/lib/init.cjs.map +1 -1
- package/core/bin/lib/init.cts +4 -2
- package/core/bin/lib/init.d.cts.map +1 -1
- package/core/references/checkpoints.md +12 -0
- package/core/references/git-integration.md +5 -5
- package/core/references/git-planning-commit.md +4 -4
- package/core/templates/milestone.md +1 -1
- package/core/templates/project.md +1 -1
- package/core/workflows/new-project.md +14 -4
- package/core/workflows/stats.md +1 -1
- package/package.json +18 -10
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
3
|
# Vector
|
|
4
|
-
**
|
|
4
|
+
**An open-source spec-driven system for building mobile apps with Claude**
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@mobiman/vector)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://discord.gg/rkU8UTu7dY)
|
|
9
|
+
|
|
10
|
+
---
|
|
5
11
|
|
|
6
12
|
## Getting Started
|
|
7
13
|
|
|
8
14
|
```bash
|
|
9
|
-
npx vector
|
|
15
|
+
npx @mobiman/vector
|
|
10
16
|
```
|
|
11
17
|
|
|
12
18
|
<br>
|
|
@@ -111,3 +117,15 @@ The orchestrator never does heavy lifting. It spawns agents, waits, integrates r
|
|
|
111
117
|
| `/vector:health [--repair]` | Validate `.planning/` directory integrity, auto-repair with `--repair` |
|
|
112
118
|
| `/vector:stats` | Display project statistics — phases, plans, requirements, git metrics |
|
|
113
119
|
|
|
120
|
+
## Community
|
|
121
|
+
|
|
122
|
+
- [Discord](https://discord.gg/rkU8UTu7dY) — get help, share what you're building, give feedback
|
|
123
|
+
- [Issues](https://github.com/mobiman1/vector/issues) — bug reports and feature requests
|
|
124
|
+
|
|
125
|
+
## Contributing
|
|
126
|
+
|
|
127
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on submitting bug reports, feature requests, and pull requests.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT — see [LICENSE](LICENSE) for details.
|
package/bin/install.cjs
CHANGED
|
@@ -16,11 +16,13 @@ const green = '\x1b[32m';
|
|
|
16
16
|
const yellow = '\x1b[33m';
|
|
17
17
|
const dim = '\x1b[2m';
|
|
18
18
|
const reset = '\x1b[0m';
|
|
19
|
+
const bold = '\x1b[1m';
|
|
20
|
+
const purple = '\x1b[38;5;135m';
|
|
19
21
|
// Codex config.toml constants
|
|
20
|
-
const
|
|
22
|
+
const VECTOR_CODEX_MARKER = '# Vector Agent Configuration \u2014 managed by core installer';
|
|
21
23
|
// Copilot instructions marker constants
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
+
const VECTOR_COPILOT_INSTRUCTIONS_MARKER = '<!-- Vector Configuration \u2014 managed by core installer -->';
|
|
25
|
+
const VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER = '<!-- /Vector Configuration -->';
|
|
24
26
|
const CODEX_AGENT_SANDBOX = {
|
|
25
27
|
'vector-executor': 'workspace-write',
|
|
26
28
|
'vector-planner': 'workspace-write',
|
|
@@ -248,16 +250,10 @@ function getGlobalDir(runtime, explicitDir = null) {
|
|
|
248
250
|
return path_1.default.join(os_1.default.homedir(), '.claude');
|
|
249
251
|
}
|
|
250
252
|
const banner = '\n' +
|
|
251
|
-
|
|
252
|
-
' \\ /\n' +
|
|
253
|
-
' \\ /\n' +
|
|
254
|
-
' \\ /\n' +
|
|
255
|
-
' \\ /\n' +
|
|
256
|
-
' \\/' + reset + '\n' +
|
|
253
|
+
bold + purple + ' VECTOR' + reset + dim + ' by Mobiman' + reset + '\n' +
|
|
257
254
|
'\n' +
|
|
258
|
-
|
|
259
|
-
'
|
|
260
|
-
' development system for iOS app creation by Mobiman\n';
|
|
255
|
+
dim + ' v' + package_json_1.default.version + reset + '\n' +
|
|
256
|
+
' An open-source spec-driven system for building mobile apps with Claude\n';
|
|
261
257
|
// Parse --config-dir argument
|
|
262
258
|
function parseConfigDirArg() {
|
|
263
259
|
const configDirIndex = args.findIndex(arg => arg === '--config-dir' || arg === '-c');
|
|
@@ -805,7 +801,7 @@ function generateCodexAgentToml(agentName, agentContent) {
|
|
|
805
801
|
*/
|
|
806
802
|
function generateCodexConfigBlock(agents) {
|
|
807
803
|
const lines = [
|
|
808
|
-
|
|
804
|
+
VECTOR_CODEX_MARKER,
|
|
809
805
|
'',
|
|
810
806
|
];
|
|
811
807
|
for (const { name, description } of agents) {
|
|
@@ -820,8 +816,8 @@ function generateCodexConfigBlock(agents) {
|
|
|
820
816
|
* Strip Vector sections from Codex config.toml content.
|
|
821
817
|
* Returns cleaned content, or null if file would be empty.
|
|
822
818
|
*/
|
|
823
|
-
function
|
|
824
|
-
const markerIndex = content.indexOf(
|
|
819
|
+
function stripVectorFromCodexConfig(content) {
|
|
820
|
+
const markerIndex = content.indexOf(VECTOR_CODEX_MARKER);
|
|
825
821
|
if (markerIndex !== -1) {
|
|
826
822
|
// Has Vector marker — remove everything from marker to EOF
|
|
827
823
|
let before = content.substring(0, markerIndex).trimEnd();
|
|
@@ -861,7 +857,7 @@ function mergeCodexConfig(configPath, vectorBlock) {
|
|
|
861
857
|
return;
|
|
862
858
|
}
|
|
863
859
|
const existing = fs_1.default.readFileSync(configPath, 'utf8');
|
|
864
|
-
const markerIndex = existing.indexOf(
|
|
860
|
+
const markerIndex = existing.indexOf(VECTOR_CODEX_MARKER);
|
|
865
861
|
// Case 2: Has Vector marker — truncate and re-append
|
|
866
862
|
if (markerIndex !== -1) {
|
|
867
863
|
let before = existing.substring(0, markerIndex).trimEnd();
|
|
@@ -889,21 +885,21 @@ function mergeCodexConfig(configPath, vectorBlock) {
|
|
|
889
885
|
* @param {string} vectorContent - Template content (without markers)
|
|
890
886
|
*/
|
|
891
887
|
function mergeCopilotInstructions(filePath, vectorContent) {
|
|
892
|
-
const vectorBlock =
|
|
888
|
+
const vectorBlock = VECTOR_COPILOT_INSTRUCTIONS_MARKER + '\n' +
|
|
893
889
|
vectorContent.trim() + '\n' +
|
|
894
|
-
|
|
890
|
+
VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER;
|
|
895
891
|
// Case 1: No file — create fresh
|
|
896
892
|
if (!fs_1.default.existsSync(filePath)) {
|
|
897
893
|
fs_1.default.writeFileSync(filePath, vectorBlock + '\n');
|
|
898
894
|
return;
|
|
899
895
|
}
|
|
900
896
|
const existing = fs_1.default.readFileSync(filePath, 'utf8');
|
|
901
|
-
const openIndex = existing.indexOf(
|
|
902
|
-
const closeIndex = existing.indexOf(
|
|
897
|
+
const openIndex = existing.indexOf(VECTOR_COPILOT_INSTRUCTIONS_MARKER);
|
|
898
|
+
const closeIndex = existing.indexOf(VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER);
|
|
903
899
|
// Case 2: Has Vector markers — replace between markers
|
|
904
900
|
if (openIndex !== -1 && closeIndex !== -1) {
|
|
905
901
|
const before = existing.substring(0, openIndex).trimEnd();
|
|
906
|
-
const after = existing.substring(closeIndex +
|
|
902
|
+
const after = existing.substring(closeIndex + VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER.length).trimStart();
|
|
907
903
|
let newContent = '';
|
|
908
904
|
if (before)
|
|
909
905
|
newContent += before + '\n\n';
|
|
@@ -924,12 +920,12 @@ function mergeCopilotInstructions(filePath, vectorContent) {
|
|
|
924
920
|
* @param {string} content - File content
|
|
925
921
|
* @returns {string|null} - Cleaned content or null if empty
|
|
926
922
|
*/
|
|
927
|
-
function
|
|
928
|
-
const openIndex = content.indexOf(
|
|
929
|
-
const closeIndex = content.indexOf(
|
|
923
|
+
function stripVectorFromCopilotInstructions(content) {
|
|
924
|
+
const openIndex = content.indexOf(VECTOR_COPILOT_INSTRUCTIONS_MARKER);
|
|
925
|
+
const closeIndex = content.indexOf(VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER);
|
|
930
926
|
if (openIndex !== -1 && closeIndex !== -1) {
|
|
931
927
|
const before = content.substring(0, openIndex).trimEnd();
|
|
932
|
-
const after = content.substring(closeIndex +
|
|
928
|
+
const after = content.substring(closeIndex + VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER.length).trimStart();
|
|
933
929
|
const cleaned = (before + (before && after ? '\n\n' : '') + after).trim();
|
|
934
930
|
if (!cleaned)
|
|
935
931
|
return null;
|
|
@@ -949,12 +945,12 @@ function installCodexConfig(targetDir, agentsSrc) {
|
|
|
949
945
|
const agentEntries = fs_1.default.readdirSync(agentsSrc).filter(f => f.startsWith('vector-') && f.endsWith('.md'));
|
|
950
946
|
const agents = [];
|
|
951
947
|
// Compute the Codex Vector install path (absolute, so subagents with empty $HOME work — #820)
|
|
952
|
-
const
|
|
948
|
+
const codexVectorPath = `${path_1.default.resolve(targetDir, 'core').replace(/\\/g, '/')}/`;
|
|
953
949
|
for (const file of agentEntries) {
|
|
954
950
|
let content = fs_1.default.readFileSync(path_1.default.join(agentsSrc, file), 'utf8');
|
|
955
951
|
// Replace full .claude/core prefix so path resolves to codex Vector install
|
|
956
|
-
content = content.replace(/~\/\.claude\/core\//g,
|
|
957
|
-
content = content.replace(/\$HOME\/\.claude\/core\//g,
|
|
952
|
+
content = content.replace(/~\/\.claude\/core\//g, codexVectorPath);
|
|
953
|
+
content = content.replace(/\$HOME\/\.claude\/core\//g, codexVectorPath);
|
|
958
954
|
const { frontmatter } = extractFrontmatterAndBody(content);
|
|
959
955
|
const name = (frontmatter ? extractFrontmatterField(frontmatter, 'name') : null) || file.replace('.md', '');
|
|
960
956
|
const description = (frontmatter ? extractFrontmatterField(frontmatter, 'description') : null) || '';
|
|
@@ -1662,7 +1658,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
1662
1658
|
const configPath = path_1.default.join(targetDir, 'config.toml');
|
|
1663
1659
|
if (fs_1.default.existsSync(configPath)) {
|
|
1664
1660
|
const content = fs_1.default.readFileSync(configPath, 'utf8');
|
|
1665
|
-
const cleaned =
|
|
1661
|
+
const cleaned = stripVectorFromCodexConfig(content);
|
|
1666
1662
|
if (cleaned === null) {
|
|
1667
1663
|
// File is empty after stripping — delete it
|
|
1668
1664
|
fs_1.default.unlinkSync(configPath);
|
|
@@ -1697,7 +1693,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
1697
1693
|
const instructionsPath = path_1.default.join(targetDir, 'copilot-instructions.md');
|
|
1698
1694
|
if (fs_1.default.existsSync(instructionsPath)) {
|
|
1699
1695
|
const content = fs_1.default.readFileSync(instructionsPath, 'utf8');
|
|
1700
|
-
const cleaned =
|
|
1696
|
+
const cleaned = stripVectorFromCopilotInstructions(content);
|
|
1701
1697
|
if (cleaned === null) {
|
|
1702
1698
|
fs_1.default.unlinkSync(instructionsPath);
|
|
1703
1699
|
removedCount++;
|
|
@@ -1813,8 +1809,8 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
1813
1809
|
const e = entry;
|
|
1814
1810
|
if (e.hooks && Array.isArray(e.hooks)) {
|
|
1815
1811
|
// Filter out Vector hooks
|
|
1816
|
-
const
|
|
1817
|
-
return !
|
|
1812
|
+
const hasVectorHook = e.hooks.some((h) => h.command && (h.command.includes('vector-check-update') || h.command.includes('vector-statusline')));
|
|
1813
|
+
return !hasVectorHook;
|
|
1818
1814
|
}
|
|
1819
1815
|
return true;
|
|
1820
1816
|
});
|
|
@@ -1834,8 +1830,8 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
1834
1830
|
settingsHooks[eventName] = settingsHooks[eventName].filter(entry => {
|
|
1835
1831
|
const e = entry;
|
|
1836
1832
|
if (e.hooks && Array.isArray(e.hooks)) {
|
|
1837
|
-
const
|
|
1838
|
-
return !
|
|
1833
|
+
const hasVectorHook = e.hooks.some((h) => h.command && h.command.includes('vector-context-monitor'));
|
|
1834
|
+
return !hasVectorHook;
|
|
1839
1835
|
}
|
|
1840
1836
|
return true;
|
|
1841
1837
|
});
|
|
@@ -2582,11 +2578,11 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
2582
2578
|
if (!hooksMap.SessionStart) {
|
|
2583
2579
|
hooksMap.SessionStart = [];
|
|
2584
2580
|
}
|
|
2585
|
-
const
|
|
2581
|
+
const hasVectorUpdateHook = hooksMap.SessionStart.some((entry) => {
|
|
2586
2582
|
const e = entry;
|
|
2587
2583
|
return e.hooks && Array.isArray(e.hooks) && e.hooks.some((h) => h.command && h.command.includes('vector-check-update'));
|
|
2588
2584
|
});
|
|
2589
|
-
if (!
|
|
2585
|
+
if (!hasVectorUpdateHook) {
|
|
2590
2586
|
hooksMap.SessionStart.push({
|
|
2591
2587
|
hooks: [
|
|
2592
2588
|
{
|
|
@@ -2664,7 +2660,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
2664
2660
|
console.log(`
|
|
2665
2661
|
${green}Done!${reset} Open a blank directory in ${program} and run ${cyan}${command}${reset}.
|
|
2666
2662
|
|
|
2667
|
-
${cyan}Join the community:${reset} https://discord.gg/
|
|
2663
|
+
${cyan}Join the community:${reset} https://discord.gg/rkU8UTu7dY
|
|
2668
2664
|
`);
|
|
2669
2665
|
}
|
|
2670
2666
|
/**
|
|
@@ -2831,12 +2827,12 @@ if (process.env.VECTOR_TEST_MODE) {
|
|
|
2831
2827
|
convertClaudeAgentToCodexAgent,
|
|
2832
2828
|
generateCodexAgentToml,
|
|
2833
2829
|
generateCodexConfigBlock,
|
|
2834
|
-
|
|
2830
|
+
stripVectorFromCodexConfig,
|
|
2835
2831
|
mergeCodexConfig,
|
|
2836
2832
|
installCodexConfig,
|
|
2837
2833
|
convertClaudeCommandToCodexSkill,
|
|
2838
2834
|
convertClaudeToOpencodeFrontmatter,
|
|
2839
|
-
|
|
2835
|
+
VECTOR_CODEX_MARKER,
|
|
2840
2836
|
CODEX_AGENT_SANDBOX,
|
|
2841
2837
|
getDirName,
|
|
2842
2838
|
getGlobalDir,
|
|
@@ -2847,10 +2843,10 @@ if (process.env.VECTOR_TEST_MODE) {
|
|
|
2847
2843
|
convertClaudeCommandToCopilotSkill,
|
|
2848
2844
|
convertClaudeAgentToCopilotAgent,
|
|
2849
2845
|
copyCommandsAsCopilotSkills,
|
|
2850
|
-
|
|
2851
|
-
|
|
2846
|
+
VECTOR_COPILOT_INSTRUCTIONS_MARKER,
|
|
2847
|
+
VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER,
|
|
2852
2848
|
mergeCopilotInstructions,
|
|
2853
|
-
|
|
2849
|
+
stripVectorFromCopilotInstructions,
|
|
2854
2850
|
convertClaudeToAntigravityContent,
|
|
2855
2851
|
convertClaudeCommandToAntigravitySkill,
|
|
2856
2852
|
convertClaudeAgentToAntigravityAgent,
|