@nexus-framework/cli 0.2.0 → 0.3.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.
Files changed (84) hide show
  1. package/README.md +62 -6
  2. package/dist/cli.js +87 -5
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/adopt.d.ts +4 -2
  5. package/dist/commands/adopt.d.ts.map +1 -1
  6. package/dist/commands/adopt.js +47 -8
  7. package/dist/commands/adopt.js.map +1 -1
  8. package/dist/commands/init.d.ts +1 -0
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +1 -1
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/commands/pack.d.ts +28 -0
  13. package/dist/commands/pack.d.ts.map +1 -0
  14. package/dist/commands/pack.js +206 -0
  15. package/dist/commands/pack.js.map +1 -0
  16. package/dist/commands/skill.d.ts +53 -0
  17. package/dist/commands/skill.d.ts.map +1 -0
  18. package/dist/commands/skill.js +371 -0
  19. package/dist/commands/skill.js.map +1 -0
  20. package/dist/commands/update.d.ts +24 -0
  21. package/dist/commands/update.d.ts.map +1 -0
  22. package/dist/commands/update.js +100 -0
  23. package/dist/commands/update.js.map +1 -0
  24. package/dist/generators/ai-config.js +40 -1
  25. package/dist/generators/ai-config.js.map +1 -1
  26. package/dist/generators/docs.d.ts +10 -1
  27. package/dist/generators/docs.d.ts.map +1 -1
  28. package/dist/generators/docs.js +40 -65
  29. package/dist/generators/docs.js.map +1 -1
  30. package/dist/generators/index.d.ts +2 -1
  31. package/dist/generators/index.d.ts.map +1 -1
  32. package/dist/generators/index.js +85 -9
  33. package/dist/generators/index.js.map +1 -1
  34. package/dist/generators/skills.d.ts +32 -0
  35. package/dist/generators/skills.d.ts.map +1 -0
  36. package/dist/generators/skills.js +220 -0
  37. package/dist/generators/skills.js.map +1 -0
  38. package/dist/generators/spring-boot.d.ts +12 -0
  39. package/dist/generators/spring-boot.d.ts.map +1 -0
  40. package/dist/generators/spring-boot.js +220 -0
  41. package/dist/generators/spring-boot.js.map +1 -0
  42. package/dist/generators/structure.d.ts +1 -0
  43. package/dist/generators/structure.d.ts.map +1 -1
  44. package/dist/generators/structure.js +129 -24
  45. package/dist/generators/structure.js.map +1 -1
  46. package/dist/prompts/adoption.d.ts +35 -0
  47. package/dist/prompts/adoption.d.ts.map +1 -0
  48. package/dist/prompts/adoption.js +153 -0
  49. package/dist/prompts/adoption.js.map +1 -0
  50. package/dist/prompts/frameworks.d.ts +5 -1
  51. package/dist/prompts/frameworks.d.ts.map +1 -1
  52. package/dist/prompts/frameworks.js +49 -1
  53. package/dist/prompts/frameworks.js.map +1 -1
  54. package/dist/prompts/index.d.ts +2 -1
  55. package/dist/prompts/index.d.ts.map +1 -1
  56. package/dist/prompts/index.js +32 -7
  57. package/dist/prompts/index.js.map +1 -1
  58. package/dist/prompts/project-type.d.ts.map +1 -1
  59. package/dist/prompts/project-type.js +6 -1
  60. package/dist/prompts/project-type.js.map +1 -1
  61. package/dist/prompts/skill-config.d.ts +19 -0
  62. package/dist/prompts/skill-config.d.ts.map +1 -0
  63. package/dist/prompts/skill-config.js +22 -0
  64. package/dist/prompts/skill-config.js.map +1 -0
  65. package/dist/types/config.d.ts +9 -3
  66. package/dist/types/config.d.ts.map +1 -1
  67. package/dist/utils/file-system.d.ts.map +1 -1
  68. package/dist/utils/file-system.js +4 -2
  69. package/dist/utils/file-system.js.map +1 -1
  70. package/dist/utils/logger.d.ts +2 -2
  71. package/dist/utils/logger.d.ts.map +1 -1
  72. package/dist/utils/logger.js +49 -36
  73. package/dist/utils/logger.js.map +1 -1
  74. package/dist/utils/project-detector.d.ts +20 -4
  75. package/dist/utils/project-detector.d.ts.map +1 -1
  76. package/dist/utils/project-detector.js +156 -27
  77. package/dist/utils/project-detector.js.map +1 -1
  78. package/dist/utils/update-check.d.ts +27 -0
  79. package/dist/utils/update-check.d.ts.map +1 -0
  80. package/dist/utils/update-check.js +111 -0
  81. package/dist/utils/update-check.js.map +1 -0
  82. package/dist/version.d.ts +1 -1
  83. package/dist/version.js +1 -1
  84. package/package.json +9 -2
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
10
10
  [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org/)
11
- [![Vitest](https://img.shields.io/badge/Vitest-190_Passing-green?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev/)
11
+ [![Vitest](https://img.shields.io/badge/Vitest-225_Passing-green?style=for-the-badge&logo=vitest&logoColor=white)](https://vitest.dev/)
12
12
  [![npm](https://img.shields.io/npm/v/@nexus-framework/cli?style=for-the-badge&logo=npm&logoColor=white&label=npm)](https://www.npmjs.com/package/@nexus-framework/cli)
13
13
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue?style=for-the-badge)](LICENSE)
14
14
  [![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-brightgreen?style=for-the-badge)](https://github.com/GDA-Africa/nexus-cli/pulls)
@@ -79,6 +79,20 @@ Every project gets a documentation system AI agents can parse, a knowledge base
79
79
  - **`nexus adopt`** — add NEXUS to any existing codebase
80
80
  - **`nexus upgrade`** — regenerate templates, preserve user work
81
81
  - **`nexus repair`** — fix missing or corrupted NEXUS files
82
+ - **`nexus pack`** — zip `.nexus/` into a portable backup
83
+ - **`nexus unpack`** — restore from a backup zip with verification
84
+ - **`nexus update`** — self-update the CLI to the latest version
85
+
86
+ </td>
87
+ <td width="50%">
88
+
89
+ ### 🧠 Skills System
90
+ - **`nexus skill list`** — see all skills installed in your project
91
+ - **`nexus skill registry`** — browse all available skills in the registry
92
+ - **`nexus skill new`** — scaffold a custom skill interactively
93
+ - **`nexus skill status`** — health-check all installed skills
94
+ - Pre-read instruction files so AI agents know *how* to do tasks
95
+ - Sourced from `@nexus-framework/skills` — updated independently
82
96
 
83
97
  </td>
84
98
  <td width="50%">
@@ -112,7 +126,7 @@ nexus init my-app
112
126
  You'll be guided through an interactive setup:
113
127
 
114
128
  ```
115
- 🔮 NEXUS CLI v0.2.0 — AI-Native Development Framework
129
+ 🔮 NEXUS CLI v0.3.0 — AI-Native Development Framework
116
130
 
117
131
  ? What are you building? › Web Application
118
132
  ? How will your app handle data? › Cloud First
@@ -161,6 +175,7 @@ Every generated project includes:
161
175
  | `src/` | Framework-specific source code and branded landing page |
162
176
  | `.nexus/docs/` | **The NEXUS Doc System** — 8 AI-readable files + project brain + knowledge base |
163
177
  | `.nexus/ai/` | Master AI instructions — the single source of truth for agent behavior |
178
+ | `.nexus/skills/` | **Skills System** — `core/` (framework skills), `custom/` (yours), `community/` (registry) |
164
179
  | Tool configs | `.cursorrules`, `.windsurfrules`, `.clinerules`, `AGENTS.md`, `.github/copilot-instructions.md` — each embeds full instructions |
165
180
  | `tests/` | Vitest/Jest config, example tests, and test helpers |
166
181
  | `package.json` | Real dependencies, real scripts — `npm run dev` works immediately |
@@ -184,6 +199,44 @@ Every generated project includes:
184
199
 
185
200
  ---
186
201
 
202
+ ## 🧠 Skills System
203
+
204
+ Skills are pre-read instruction files that tell AI agents *how* to execute tasks in your specific project — not just what to do, but the exact patterns, conventions, and anti-patterns your codebase follows.
205
+
206
+ Every project gets a `.nexus/skills/` directory with three zones:
207
+
208
+ ```
209
+ .nexus/skills/
210
+ README.md ← auto-generated index agents read first
211
+ core/ ← framework-matched skills from @nexus-framework/skills
212
+ custom/ ← your own skills (created with nexus skill new, never touched by NEXUS)
213
+ community/ ← skills installed from the registry
214
+ ```
215
+
216
+ ### Managing Skills
217
+
218
+ ```bash
219
+ nexus skill list # what's installed in this project
220
+ nexus skill registry # browse everything in the registry
221
+ nexus skill registry --framework nextjs # filter to one framework
222
+ nexus skill new # scaffold a custom skill interactively
223
+ nexus skill status # health-check: deprecated, invalid frontmatter
224
+ nexus skill install <pkg> # install a community skill pack
225
+ nexus skill remove <name> # remove a community skill
226
+ ```
227
+
228
+ ### Custom Skills
229
+
230
+ ```bash
231
+ nexus skill new my-service-pattern
232
+ ```
233
+
234
+ Guides you through setting a category, trigger phrases, and scaffolds a full markdown template. The AI agent reads this file before any task matching the triggers.
235
+
236
+ **Precedence:** `custom/` > `core/` > `community/` — your skills always win.
237
+
238
+ ---
239
+
187
240
  ## 🎭 Agent Persona
188
241
 
189
242
  NEXUS lets you configure how AI agents communicate when they're synced with your project.
@@ -232,18 +285,21 @@ After adopting, your AI coding tool will auto-detect the NEXUS docs, scan your c
232
285
  ### ✅ Shipped
233
286
  - [x] Core CLI with `nexus init`, `nexus adopt`, `nexus upgrade`, `nexus repair`
234
287
  - [x] Interactive prompt system (7 modules including persona)
235
- - [x] Generator engine (8 modules: structure, docs, config, tests, CI/CD, landing page, AI config, orchestrator)
288
+ - [x] Generator engine (8 modules: structure, docs, config, tests, CI/CD, landing page, AI config, skills)
236
289
  - [x] AI-native documentation system (8 structured files + project brain + knowledge base + onboarding protocol)
237
290
  - [x] Agent Persona system (tone, verbosity, identity, custom directives)
238
291
  - [x] Multi-tool AI support (Cursor, Copilot, Windsurf, Cline, Claude Code)
239
292
  - [x] 6 frontend frameworks supported
240
293
  - [x] Smart file strategy (upgrade preserves user work, repair fixes corruption)
241
294
  - [x] Progressive knowledge base (append-only, category-tagged, AI-scannable)
242
- - [x] 190 unit tests passing
295
+ - [x] **Skills System** `nexus skill` (6 subcommands), `.nexus/skills/`, sourced from `@nexus-framework/skills`
296
+ - [x] **`nexus pack` / `nexus unpack`** — portable `.nexus/` migration with zip + verification
297
+ - [x] **`nexus update`** — self-updating CLI + startup update notifications
298
+ - [x] 225 unit tests passing
243
299
  - [x] Published to npm as `@nexus-framework/cli`
244
300
  - [x] CI/CD with auto-publish to npm on version bump
245
301
 
246
- ### 🔜 Next Up (v0.3.0)
302
+ ### 🔜 Next Up (v0.3.x)
247
303
  - [ ] E2E tests — generate a project, run its build, verify all files
248
304
  - [ ] Framework-specific template content (not just landing pages)
249
305
  - [ ] `nexus add <feature>` — add capabilities to existing NEXUS projects
@@ -272,7 +328,7 @@ We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
272
328
  ```bash
273
329
  git clone https://github.com/GDA-Africa/nexus-cli.git
274
330
  cd nexus-cli && yarn install
275
- yarn lint && yarn test # 190 tests, zero lint errors
331
+ yarn lint && yarn test # 225 tests, zero lint errors
276
332
  ```
277
333
 
278
334
  ---
package/dist/cli.js CHANGED
@@ -6,8 +6,12 @@
6
6
  import { Command } from 'commander';
7
7
  import { adoptCommand } from './commands/adopt.js';
8
8
  import { initCommand } from './commands/init.js';
9
+ import { packCommand, unpackCommand } from './commands/pack.js';
9
10
  import { repairCommand } from './commands/repair.js';
11
+ import { skillInstallCommand, skillListCommand, skillNewCommand, skillRegistryCommand, skillRemoveCommand, skillStatusCommand, } from './commands/skill.js';
12
+ import { updateCommand, printUpdateBanner } from './commands/update.js';
10
13
  import { upgradeCommand } from './commands/upgrade.js';
14
+ import { checkForUpdate } from './utils/update-check.js';
11
15
  import { version } from './version.js';
12
16
  const program = new Command();
13
17
  program
@@ -18,14 +22,16 @@ program
18
22
  .command('init [project-name]')
19
23
  .description('Initialize a new NEXUS project with interactive setup')
20
24
  .option('--adopt', 'Shorthand: same as `nexus adopt` (add NEXUS to an existing project)')
25
+ .option('--local', 'Configure NEXUS as local-only (not tracked by git)')
21
26
  .action(async (projectName, options) => {
22
- await initCommand(projectName, { adopt: options.adopt ?? false });
27
+ await initCommand(projectName, { adopt: options.adopt ?? false, local: options.local ?? false });
23
28
  });
24
29
  program
25
30
  .command('adopt [path]')
26
31
  .description('Add NEXUS docs & AI config to an existing project (no scaffolding)')
27
- .action(async (targetPath) => {
28
- await adoptCommand(targetPath);
32
+ .option('--force', 'Force adoption even if no project is detected')
33
+ .action(async (targetPath, options) => {
34
+ await adoptCommand(targetPath, options);
29
35
  });
30
36
  program
31
37
  .command('upgrade [path]')
@@ -39,6 +45,82 @@ program
39
45
  .action(async (targetPath) => {
40
46
  await repairCommand(targetPath);
41
47
  });
42
- // Default to help if no command is given
43
- program.parse();
48
+ // ── nexus skill ──────────────────────────────────────────────
49
+ const skillCmd = program
50
+ .command('skill')
51
+ .description('Manage NEXUS Skills — pre-read AI task instructions in .nexus/skills/');
52
+ skillCmd
53
+ .command('new [name]')
54
+ .description('Scaffold a new custom skill in .nexus/skills/custom/')
55
+ .action(async (name) => {
56
+ await skillNewCommand(name);
57
+ });
58
+ skillCmd
59
+ .command('list')
60
+ .description('List all installed skills (core / custom / community)')
61
+ .action(async () => {
62
+ await skillListCommand();
63
+ });
64
+ skillCmd
65
+ .command('registry')
66
+ .description('Browse all skills available in the @nexus-framework/skills registry')
67
+ .option('--framework <name>', 'Filter to a single framework (e.g. nextjs, react-vite, shared)')
68
+ .action(async (options) => {
69
+ await skillRegistryCommand(options);
70
+ });
71
+ skillCmd
72
+ .command('install <package>')
73
+ .description('Install community skills from @nexus-framework/skills or a registry package')
74
+ .action(async (pkg) => {
75
+ await skillInstallCommand(pkg);
76
+ });
77
+ skillCmd
78
+ .command('remove <name>')
79
+ .description('Remove a community skill (cannot remove core or custom skills)')
80
+ .action(async (name) => {
81
+ await skillRemoveCommand(name);
82
+ });
83
+ skillCmd
84
+ .command('status')
85
+ .description('Check skill health — missing core skills, invalid frontmatter, deprecated status')
86
+ .action(async () => {
87
+ await skillStatusCommand();
88
+ });
89
+ // ── nexus pack / unpack ───────────────────────────────────────
90
+ program
91
+ .command('pack [path]')
92
+ .description('Zip .nexus/ into a portable nexus-backup-<timestamp>.zip for migration')
93
+ .action(async (targetPath) => {
94
+ await packCommand(targetPath);
95
+ });
96
+ program
97
+ .command('unpack [path]')
98
+ .description('Extract a nexus-backup-*.zip and verify the restored .nexus/ structure')
99
+ .option('--file <zipfile>', 'Specify a zip file to unpack (default: most recent backup in directory)')
100
+ .action(async (targetPath, options) => {
101
+ await unpackCommand(targetPath, options);
102
+ });
103
+ // ── nexus update ──────────────────────────────────────────────
104
+ program
105
+ .command('update')
106
+ .description('Check for a newer version of NEXUS CLI and install it automatically')
107
+ .action(async () => {
108
+ await updateCommand();
109
+ });
110
+ // ── Startup update notification ───────────────────────────────
111
+ // Silently checks the npm registry after every command.
112
+ // If a newer version exists, prints a short non-blocking banner
113
+ // at the end of the command output.
114
+ async function runWithUpdateCheck() {
115
+ // Fire update check in background — does not block CLI startup
116
+ const updatePromise = checkForUpdate(4000);
117
+ // Parse and run the actual command
118
+ await program.parseAsync();
119
+ // After the command finishes, check if an update was found
120
+ const info = await updatePromise;
121
+ if (info?.hasUpdate) {
122
+ printUpdateBanner(info);
123
+ }
124
+ }
125
+ void runWithUpdateCheck();
44
126
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,8DAA8D,CAAC;KAC3E,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AAErC,OAAO;KACJ,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,SAAS,EAAE,qEAAqE,CAAC;KACxF,MAAM,CAAC,KAAK,EAAE,WAA+B,EAAE,OAA4B,EAAE,EAAE;IAC9E,MAAM,WAAW,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,oEAAoE,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,EAAE;IAC/C,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,2EAA2E,CAAC;KACxF,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,EAAE;IAC/C,MAAM,cAAc,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,wEAAwE,CAAC;KACrF,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,EAAE;IAC/C,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEL,yCAAyC;AACzC,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,9 @@
19
19
  * Handler for `nexus adopt [path]`.
20
20
  *
21
21
  * @param targetPath - Optional path to the project to adopt (defaults to cwd)
22
- * @param options - Reserved for future flags (e.g. --force)
22
+ * @param options - Command options (--force to skip project detection)
23
23
  */
24
- export declare function adoptCommand(targetPath?: string, _options?: Record<string, unknown>): Promise<void>;
24
+ export declare function adoptCommand(targetPath?: string, options?: {
25
+ force?: boolean;
26
+ }): Promise<void>;
25
27
  //# sourceMappingURL=adopt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,OAAO,CAAC,IAAI,CAAC,CAmDf"}
1
+ {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAUH;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAChC,OAAO,CAAC,IAAI,CAAC,CA0Ff"}
@@ -17,6 +17,7 @@
17
17
  */
18
18
  import path from 'node:path';
19
19
  import { adoptProject } from '../generators/index.js';
20
+ import { promptAdoption } from '../prompts/adoption.js';
20
21
  import { logger } from '../utils/logger.js';
21
22
  import { detectProject } from '../utils/project-detector.js';
22
23
  import { version } from '../version.js';
@@ -24,21 +25,57 @@ import { version } from '../version.js';
24
25
  * Handler for `nexus adopt [path]`.
25
26
  *
26
27
  * @param targetPath - Optional path to the project to adopt (defaults to cwd)
27
- * @param options - Reserved for future flags (e.g. --force)
28
+ * @param options - Command options (--force to skip project detection)
28
29
  */
29
- export async function adoptCommand(targetPath, _options = {}) {
30
+ export async function adoptCommand(targetPath, options = {}) {
30
31
  logger.banner(version);
31
32
  const targetDir = targetPath
32
33
  ? path.resolve(process.cwd(), targetPath)
33
34
  : process.cwd();
34
- // Detect the existing project
35
- const projectInfo = await detectProject(targetDir);
36
- if (!projectInfo.detected) {
35
+ // Detect the existing project (skip if --force)
36
+ const projectInfo = options.force
37
+ ? {
38
+ detected: true,
39
+ signals: {
40
+ hasPackageJson: false,
41
+ hasGit: false,
42
+ hasSrc: false,
43
+ hasTsConfig: false,
44
+ hasNodeModules: false,
45
+ hasGoMod: false,
46
+ hasCargoToml: false,
47
+ hasPyProjectToml: false,
48
+ hasFirebaseJson: false,
49
+ hasPomXml: false,
50
+ hasBuildGradle: false,
51
+ isInsideMonorepo: false,
52
+ monorepoRoot: null,
53
+ },
54
+ name: null,
55
+ description: null,
56
+ framework: null,
57
+ testFramework: null,
58
+ packageManager: null,
59
+ hasNexus: false,
60
+ dependencies: [],
61
+ }
62
+ : await detectProject(targetDir);
63
+ if (!projectInfo.detected && !options.force) {
37
64
  logger.error('No existing project detected in this directory.');
38
65
  logger.newline();
39
- logger.info('The adopt command is for existing projects that already have a package.json.');
40
- logger.info('To create a brand-new project, run:');
66
+ logger.info('NEXUS adopt works with:');
67
+ logger.info(' Node.js projects (package.json)');
68
+ logger.info(' • Spring Boot projects (pom.xml, build.gradle)');
69
+ logger.info(' • Cloud Functions (firebase.json)');
70
+ logger.info(' • Go projects (go.mod)');
71
+ logger.info(' • Rust projects (Cargo.toml)');
72
+ logger.info(' • Python projects (pyproject.toml)');
73
+ logger.info(' • Monorepos (workspace structure)');
74
+ logger.newline();
75
+ logger.info('To force adoption of any directory:');
76
+ logger.nexus(' nexus adopt --force');
41
77
  logger.newline();
78
+ logger.info('To create a brand-new project:');
42
79
  logger.nexus(' nexus init <project-name>');
43
80
  logger.newline();
44
81
  process.exit(1);
@@ -58,8 +95,10 @@ export async function adoptCommand(targetPath, _options = {}) {
58
95
  logger.info(`Detected test framework: ${testFw}`);
59
96
  logger.info(`Detected package manager: ${pm}`);
60
97
  logger.newline();
98
+ // Run pre-adoption interview
99
+ const adoptionContext = await promptAdoption(projectInfo);
61
100
  try {
62
- await adoptProject(targetDir, projectInfo);
101
+ await adoptProject(targetDir, projectInfo, adoptionContext);
63
102
  logger.adoptComplete(displayName);
64
103
  }
65
104
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAmB,EACnB,WAAoC,EAAE;IAEtC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvB,MAAM,SAAS,GAAG,UAAU;QAC1B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC;QACzC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAElB,8BAA8B;IAC9B,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAEnD,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;QAC5F,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC7D,MAAM,CAAC,IAAI,CACT,oGAAoG,CACrG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,IAAI,SAAS,CAAC;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,IAAI,MAAM,CAAC;IACnD,MAAM,EAAE,GAAG,WAAW,CAAC,cAAc,IAAI,KAAK,CAAC;IAE/C,MAAM,CAAC,KAAK,CAAC,aAAa,WAAW,+BAA+B,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,CAAC;IACjB,MAAM,CAAC,IAAI,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;IAChD,MAAM,CAAC,IAAI,CAAC,4BAA4B,MAAM,EAAE,CAAC,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACzC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@
13
13
  /** Options passed from cli.ts */
14
14
  export interface InitOptions {
15
15
  adopt?: boolean;
16
+ local?: boolean;
16
17
  }
17
18
  /**
18
19
  * Handler for the `nexus init` command.
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CA2Df"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CA2Df"}
@@ -54,7 +54,7 @@ export async function initCommand(projectName, options = {}) {
54
54
  }
55
55
  try {
56
56
  // Run interactive prompts
57
- const config = await runPrompts(projectName);
57
+ const config = await runPrompts(projectName, options.local);
58
58
  logger.newline();
59
59
  logger.nexus(`Creating "${config.displayName}" with ${config.frontendFramework}...`);
60
60
  logger.newline();
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * NEXUS CLI - Pack & Unpack Commands
3
+ *
4
+ * `nexus pack` — Zips .nexus/ into nexus-backup-<timestamp>.zip for portable migration.
5
+ * `nexus unpack` — Finds + unzips a nexus-backup-*.zip, then verifies the restored structure.
6
+ */
7
+ /**
8
+ * `nexus pack [path]`
9
+ *
10
+ * Zips the .nexus/ folder in the target directory into a portable
11
+ * nexus-backup-<timestamp>.zip file placed in the same directory.
12
+ * Safe to run anywhere — does not modify .nexus/ at all.
13
+ */
14
+ export declare function packCommand(targetPath?: string): Promise<void>;
15
+ /**
16
+ * `nexus unpack [path] [--file <zipfile>]`
17
+ *
18
+ * Finds the most recent nexus-backup-*.zip in the target directory
19
+ * (or a specific file via --file), extracts it, then verifies the
20
+ * restored .nexus/ structure is complete.
21
+ *
22
+ * Safe to run even if .nexus/ already exists — extracted files will
23
+ * overwrite/merge but no existing file is deleted.
24
+ */
25
+ export declare function unpackCommand(targetPath?: string, options?: {
26
+ file?: string;
27
+ }): Promise<void>;
28
+ //# sourceMappingURL=pack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/commands/pack.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA8BH;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDpE;AAID;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9B,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * NEXUS CLI - Pack & Unpack Commands
3
+ *
4
+ * `nexus pack` — Zips .nexus/ into nexus-backup-<timestamp>.zip for portable migration.
5
+ * `nexus unpack` — Finds + unzips a nexus-backup-*.zip, then verifies the restored structure.
6
+ */
7
+ import fs from 'node:fs';
8
+ import { createWriteStream } from 'node:fs';
9
+ import fsp from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import archiver from 'archiver';
12
+ import unzipper from 'unzipper';
13
+ import { logger } from '../utils/logger.js';
14
+ // ─── Constants ────────────────────────────────────────────────
15
+ const NEXUS_DIR = '.nexus';
16
+ const ZIP_PREFIX = 'nexus-backup-';
17
+ const ZIP_PATTERN = /^nexus-backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.zip$/;
18
+ /**
19
+ * Directories and files that must be present after a successful unpack.
20
+ */
21
+ const REQUIRED_AFTER_UNPACK = [
22
+ '.nexus',
23
+ '.nexus/docs',
24
+ '.nexus/ai',
25
+ '.nexus/manifest.json',
26
+ ];
27
+ // ─── Pack ─────────────────────────────────────────────────────
28
+ /**
29
+ * `nexus pack [path]`
30
+ *
31
+ * Zips the .nexus/ folder in the target directory into a portable
32
+ * nexus-backup-<timestamp>.zip file placed in the same directory.
33
+ * Safe to run anywhere — does not modify .nexus/ at all.
34
+ */
35
+ export async function packCommand(targetPath) {
36
+ const cwd = targetPath ? path.resolve(targetPath) : process.cwd();
37
+ const nexusDir = path.join(cwd, NEXUS_DIR);
38
+ // Guard: .nexus/ must exist
39
+ try {
40
+ const stat = await fsp.stat(nexusDir);
41
+ if (!stat.isDirectory()) {
42
+ logger.error(`.nexus is not a directory at: ${cwd}`);
43
+ process.exit(1);
44
+ }
45
+ }
46
+ catch {
47
+ logger.error(`No .nexus/ folder found at: ${cwd}`);
48
+ logger.info('Run nexus init or nexus adopt first.');
49
+ process.exit(1);
50
+ }
51
+ // Build output filename with ISO timestamp (colons → dashes for cross-platform)
52
+ const ts = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
53
+ const zipName = `${ZIP_PREFIX}${ts}.zip`;
54
+ const zipPath = path.join(cwd, zipName);
55
+ logger.nexus(`Packing .nexus/ → ${zipName} …`);
56
+ await new Promise((resolve, reject) => {
57
+ const output = createWriteStream(zipPath);
58
+ const archive = archiver('zip', { zlib: { level: 9 } });
59
+ output.on('close', resolve);
60
+ archive.on('error', reject);
61
+ archive.pipe(output);
62
+ // Add the whole .nexus/ directory, preserving internal structure
63
+ archive.directory(nexusDir, NEXUS_DIR);
64
+ void archive.finalize();
65
+ });
66
+ const stats = fs.statSync(zipPath);
67
+ const kb = (stats.size / 1024).toFixed(1);
68
+ logger.newline();
69
+ logger.success(`Packed successfully!`);
70
+ logger.info(` File : ${zipName}`);
71
+ logger.info(` Size : ${kb} KB`);
72
+ logger.info(` Location: ${zipPath}`);
73
+ logger.newline();
74
+ logger.info('To migrate: copy this zip to another project or computer,');
75
+ logger.info('then run: nexus unpack');
76
+ logger.newline();
77
+ }
78
+ // ─── Unpack ───────────────────────────────────────────────────
79
+ /**
80
+ * `nexus unpack [path] [--file <zipfile>]`
81
+ *
82
+ * Finds the most recent nexus-backup-*.zip in the target directory
83
+ * (or a specific file via --file), extracts it, then verifies the
84
+ * restored .nexus/ structure is complete.
85
+ *
86
+ * Safe to run even if .nexus/ already exists — extracted files will
87
+ * overwrite/merge but no existing file is deleted.
88
+ */
89
+ export async function unpackCommand(targetPath, options = {}) {
90
+ const cwd = targetPath ? path.resolve(targetPath) : process.cwd();
91
+ // Resolve the zip file to use
92
+ let zipPath;
93
+ if (options.file) {
94
+ zipPath = path.isAbsolute(options.file)
95
+ ? options.file
96
+ : path.join(cwd, options.file);
97
+ }
98
+ else {
99
+ zipPath = await findLatestBackup(cwd);
100
+ }
101
+ // Verify the zip exists
102
+ try {
103
+ await fsp.stat(zipPath);
104
+ }
105
+ catch {
106
+ logger.error(`Zip file not found: ${zipPath}`);
107
+ logger.newline();
108
+ logger.info('Looking for a file matching: nexus-backup-YYYY-MM-DDTHH-MM-SS.zip');
109
+ logger.info(`In directory: ${cwd}`);
110
+ logger.newline();
111
+ logger.info('To create one: nexus pack');
112
+ logger.info('To specify one: nexus unpack --file <path-to-zip>');
113
+ process.exit(1);
114
+ }
115
+ const zipName = path.basename(zipPath);
116
+ logger.nexus(`Unpacking ${zipName} → ${cwd} …`);
117
+ // Extract
118
+ await new Promise((resolve, reject) => {
119
+ fs.createReadStream(zipPath)
120
+ .pipe(unzipper.Extract({ path: cwd }))
121
+ .on('close', resolve)
122
+ .on('error', reject);
123
+ });
124
+ logger.success('Extraction complete.');
125
+ logger.newline();
126
+ // Verify
127
+ await verifyUnpack(cwd);
128
+ }
129
+ // ─── Helpers ──────────────────────────────────────────────────
130
+ /**
131
+ * Scan cwd for nexus-backup-*.zip files and return the most recent one.
132
+ */
133
+ async function findLatestBackup(cwd) {
134
+ let entries;
135
+ try {
136
+ entries = await fsp.readdir(cwd);
137
+ }
138
+ catch {
139
+ logger.error(`Cannot read directory: ${cwd}`);
140
+ process.exit(1);
141
+ }
142
+ const zips = entries
143
+ .filter((f) => ZIP_PATTERN.test(f))
144
+ .sort()
145
+ .reverse(); // ISO timestamps sort lexicographically, newest last → reverse for newest first
146
+ if (zips.length === 0) {
147
+ logger.error('No nexus-backup-*.zip file found in this directory.');
148
+ logger.newline();
149
+ logger.info('To create one: nexus pack');
150
+ logger.info('To specify one: nexus unpack --file <path-to-zip>');
151
+ process.exit(1);
152
+ }
153
+ if (zips.length > 1) {
154
+ logger.info(`Found ${zips.length} backup zips — using the most recent:`);
155
+ logger.info(` ${zips[0]}`);
156
+ logger.info(` (others: ${zips.slice(1).join(', ')})`);
157
+ logger.newline();
158
+ }
159
+ return path.join(cwd, zips[0]);
160
+ }
161
+ /**
162
+ * After extraction, verify all expected .nexus/ paths exist and report.
163
+ */
164
+ async function verifyUnpack(cwd) {
165
+ logger.info('Verifying restored structure …');
166
+ logger.newline();
167
+ let allOk = true;
168
+ for (const rel of REQUIRED_AFTER_UNPACK) {
169
+ const full = path.join(cwd, rel);
170
+ try {
171
+ await fsp.stat(full);
172
+ logger.success(` ✔ ${rel}`);
173
+ }
174
+ catch {
175
+ logger.error(` ✖ ${rel} — MISSING`);
176
+ allOk = false;
177
+ }
178
+ }
179
+ // Also check for optional but expected items and report informatively
180
+ const optionals = [
181
+ '.nexus/skills',
182
+ '.nexus/docs/knowledge.md',
183
+ '.nexus/docs/index.md',
184
+ ];
185
+ for (const rel of optionals) {
186
+ const full = path.join(cwd, rel);
187
+ try {
188
+ await fsp.stat(full);
189
+ logger.success(` ✔ ${rel}`);
190
+ }
191
+ catch {
192
+ logger.warn(` ⚠ ${rel} — not present (optional)`);
193
+ }
194
+ }
195
+ logger.newline();
196
+ if (allOk) {
197
+ logger.success('All required NEXUS files are in place.');
198
+ logger.info('Your AI tools will detect .nexus/ automatically on next use.');
199
+ }
200
+ else {
201
+ logger.warn('Some required files are missing. The archive may be incomplete.');
202
+ logger.info('Run nexus repair to restore any missing files from templates.');
203
+ }
204
+ logger.newline();
205
+ }
206
+ //# sourceMappingURL=pack.js.map