@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Lex Christopherson
3
+ Copyright (c) 2025 Steven Becerra
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,12 +1,18 @@
1
1
  <div align="center">
2
2
 
3
3
  # Vector
4
- **A meta-prompting, context engineering, and spec-driven development system for iOS app creation**
4
+ **An open-source spec-driven system for building mobile apps with Claude**
5
+
6
+ [![npm](https://img.shields.io/npm/v/@mobiman/vector)](https://www.npmjs.com/package/@mobiman/vector)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
+ [![Discord](https://img.shields.io/discord/rkU8UTu7dY?label=Discord&logo=discord&logoColor=white)](https://discord.gg/rkU8UTu7dY)
9
+
10
+ ---
5
11
 
6
12
  ## Getting Started
7
13
 
8
14
  ```bash
9
- npx vector@latest
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 GSD_CODEX_MARKER = '# Vector Agent Configuration \u2014 managed by core installer';
22
+ const VECTOR_CODEX_MARKER = '# Vector Agent Configuration \u2014 managed by core installer';
21
23
  // Copilot instructions marker constants
22
- const GSD_COPILOT_INSTRUCTIONS_MARKER = '<!-- Vector Configuration \u2014 managed by core installer -->';
23
- const GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER = '<!-- /Vector Configuration -->';
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
- cyan + ' \\ /────▶\n' +
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
- ' Vector ' + dim + 'v' + package_json_1.default.version + reset + '\n' +
259
- ' A meta-prompting, context engineering, and spec-driven\n' +
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
- GSD_CODEX_MARKER,
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 stripGsdFromCodexConfig(content) {
824
- const markerIndex = content.indexOf(GSD_CODEX_MARKER);
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(GSD_CODEX_MARKER);
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 = GSD_COPILOT_INSTRUCTIONS_MARKER + '\n' +
888
+ const vectorBlock = VECTOR_COPILOT_INSTRUCTIONS_MARKER + '\n' +
893
889
  vectorContent.trim() + '\n' +
894
- GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER;
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(GSD_COPILOT_INSTRUCTIONS_MARKER);
902
- const closeIndex = existing.indexOf(GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER);
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 + GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER.length).trimStart();
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 stripGsdFromCopilotInstructions(content) {
928
- const openIndex = content.indexOf(GSD_COPILOT_INSTRUCTIONS_MARKER);
929
- const closeIndex = content.indexOf(GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER);
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 + GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER.length).trimStart();
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 codexGsdPath = `${path_1.default.resolve(targetDir, 'core').replace(/\\/g, '/')}/`;
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, codexGsdPath);
957
- content = content.replace(/\$HOME\/\.claude\/core\//g, codexGsdPath);
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 = stripGsdFromCodexConfig(content);
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 = stripGsdFromCopilotInstructions(content);
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 hasGsdHook = e.hooks.some((h) => h.command && (h.command.includes('vector-check-update') || h.command.includes('vector-statusline')));
1817
- return !hasGsdHook;
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 hasGsdHook = e.hooks.some((h) => h.command && h.command.includes('vector-context-monitor'));
1838
- return !hasGsdHook;
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 hasGsdUpdateHook = hooksMap.SessionStart.some((entry) => {
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 (!hasGsdUpdateHook) {
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/gsd
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
- stripGsdFromCodexConfig,
2830
+ stripVectorFromCodexConfig,
2835
2831
  mergeCodexConfig,
2836
2832
  installCodexConfig,
2837
2833
  convertClaudeCommandToCodexSkill,
2838
2834
  convertClaudeToOpencodeFrontmatter,
2839
- GSD_CODEX_MARKER,
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
- GSD_COPILOT_INSTRUCTIONS_MARKER,
2851
- GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER,
2846
+ VECTOR_COPILOT_INSTRUCTIONS_MARKER,
2847
+ VECTOR_COPILOT_INSTRUCTIONS_CLOSE_MARKER,
2852
2848
  mergeCopilotInstructions,
2853
- stripGsdFromCopilotInstructions,
2849
+ stripVectorFromCopilotInstructions,
2854
2850
  convertClaudeToAntigravityContent,
2855
2851
  convertClaudeCommandToAntigravitySkill,
2856
2852
  convertClaudeAgentToAntigravityAgent,