@p10i/create-nestbox 0.1.0 → 0.1.2

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/INSTALL.md CHANGED
@@ -10,7 +10,7 @@ For ordinary new projects, prefer the npm creator:
10
10
  npm create @p10i/nestbox@latest
11
11
  ```
12
12
 
13
- The published npm package is `@p10i/create-nestbox`; npm maps `npm create @p10i/nestbox` to that package. The creator scaffolds one of the two default layouts, copies `.env.example` to `.env`, copies `home/configs/opencode/instance.example.md` to `instance.md`, records npm package provenance in the instance policy, and initializes fresh installation Git history when Git is available.
13
+ The published npm package is `@p10i/create-nestbox`; npm maps `npm create @p10i/nestbox` to that package. The creator explains and previews one of the two default layouts before writing files. The recommended layout installs at `<workspace>/.nestbox` so Nestbox stays separate from project files. The direct layout writes Nestbox files into an empty selected directory. The creator copies `.env.example` to `.env`, copies `home/configs/opencode/instance.example.md` to `instance.md`, records npm package provenance in the instance policy, and initializes fresh installation Git history when Git is available.
14
14
 
15
15
  The creator does not start Docker or collect secrets. After it finishes, edit `.env`, then run from the installation directory:
16
16
 
package/README.md CHANGED
@@ -24,7 +24,7 @@ Create a new Nestbox project with npm:
24
24
  npm create @p10i/nestbox@latest
25
25
  ```
26
26
 
27
- The creator offers the two default layouts: install directly into the selected directory or install at `<workspace>/.nestbox`. After creation, edit `.env`, then run the Docker Compose validation and startup commands printed by the creator.
27
+ The creator previews the exact paths before it writes files. The recommended layout installs Nestbox at `<workspace>/.nestbox` so Nestbox stays separate from your project files. You can also choose a direct install into an empty directory. After creation, edit `.env`, then run the Docker Compose validation and startup commands printed by the creator.
28
28
 
29
29
  For agent-guided installation or repair work, copy and send this to an agent with filesystem, Git, Docker, and terminal access:
30
30
 
@@ -49,7 +49,12 @@ function parseArgs(argv) {
49
49
  }
50
50
 
51
51
  function printHelp() {
52
- console.log(`Create a Nestbox project.\n\nUsage:\n npm create @p10i/nestbox@latest [target] [options]\n npx @p10i/create-nestbox [target] [options]\n\nOptions:\n --layout current|nestbox Install directly into target or into target/.nestbox\n --target <path> Target directory\n --yes, -y Use defaults for missing prompts\n --no-git Do not initialize fresh installation Git history\n --help, -h Show this help\n`);
52
+ console.log(`Create a Nestbox project.\n\nUsage:\n npm create @p10i/nestbox@latest [workspace] [options]\n npx @p10i/create-nestbox [workspace] [options]\n\nOptions:\n --layout nestbox Create <workspace>/.nestbox (recommended)\n --layout current Put Nestbox files directly in <workspace>\n --target <path> Workspace directory\n --yes, -y Use defaults and skip confirmation\n --no-git Do not initialize fresh installation Git history\n --help, -h Show this help\n`);
53
+ }
54
+
55
+ function printBanner() {
56
+ console.log('\nNestbox Creator');
57
+ console.log('Create an agent-guided Docker workspace for project tools and interfaces.\n');
53
58
  }
54
59
 
55
60
  async function pathExists(path) {
@@ -70,7 +75,7 @@ async function isDirectoryEmpty(path) {
70
75
 
71
76
  function validateLayout(layout) {
72
77
  if (layout !== 'current' && layout !== 'nestbox') {
73
- throw new Error('Layout must be "current" or "nestbox".');
78
+ throw new Error('Layout must be "nestbox" or "current".');
74
79
  }
75
80
  }
76
81
 
@@ -81,6 +86,39 @@ async function ask(question, defaultValue, rl, yes) {
81
86
  return answer || defaultValue;
82
87
  }
83
88
 
89
+ async function askLayout(rl, yes) {
90
+ if (yes) return 'nestbox';
91
+
92
+ console.log('Where should Nestbox files go?');
93
+ console.log(' 1. Keep Nestbox in .nestbox (recommended)');
94
+ console.log(' Creates <workspace>/.nestbox and keeps Nestbox separate from project files.');
95
+ console.log(' 2. Put Nestbox directly in the workspace');
96
+ console.log(' Writes docker-compose.yaml, docker/, home/, and tests/ into the selected directory.');
97
+
98
+ while (true) {
99
+ const answer = (await rl.question('Choose layout [1]: ')).trim().toLowerCase();
100
+ if (!answer || answer === '1' || answer === 'nestbox' || answer === '.nestbox') return 'nestbox';
101
+ if (answer === '2' || answer === 'current' || answer === 'direct') return 'current';
102
+ console.log('Please choose 1 for .nestbox or 2 for direct install.');
103
+ }
104
+ }
105
+
106
+ async function confirmCreation(rl, yes, workspaceDir, installDir, layout) {
107
+ console.log('\nReview');
108
+ console.log(` Workspace: ${workspaceDir}`);
109
+ console.log(` Nestbox files: ${installDir}`);
110
+ console.log(` Layout: ${layout === 'nestbox' ? 'workspace/.nestbox' : 'directly in workspace'}`);
111
+ console.log(' Creates: .env, home/configs/opencode/instance.md');
112
+ console.log(' Does not: start Docker or collect provider secrets');
113
+
114
+ if (yes) return;
115
+
116
+ const answer = (await rl.question('\nCreate Nestbox here? [y/N]: ')).trim().toLowerCase();
117
+ if (answer !== 'y' && answer !== 'yes') {
118
+ throw new Error('Cancelled. No files were created.');
119
+ }
120
+ }
121
+
84
122
  async function copyTemplate(installDir) {
85
123
  for (const entry of copyEntries) {
86
124
  await cp(join(packageRoot, entry), join(installDir, entry), {
@@ -127,13 +165,13 @@ async function configureInstance(installDir, workspaceDir, layout) {
127
165
  }
128
166
 
129
167
  function commandExists(command) {
130
- const result = spawnSync(command, ['--version'], { stdio: 'ignore', shell: process.platform === 'win32' });
168
+ const result = spawnSync(command, ['--version'], { stdio: 'ignore' });
131
169
  return result.status === 0;
132
170
  }
133
171
 
134
172
  function initGit(installDir) {
135
173
  if (!commandExists('git')) return false;
136
- const result = spawnSync('git', ['init'], { cwd: installDir, stdio: 'inherit', shell: process.platform === 'win32' });
174
+ const result = spawnSync('git', ['init'], { cwd: installDir, stdio: 'inherit' });
137
175
  if (result.status !== 0) throw new Error('git init failed.');
138
176
  return true;
139
177
  }
@@ -147,13 +185,17 @@ async function main() {
147
185
 
148
186
  const rl = createInterface({ input, output });
149
187
  try {
150
- const targetInput = options.target || await ask('Target directory', '.', rl, options.yes);
151
- const layoutInput = options.layout || await ask('Layout: current or nestbox', 'nestbox', rl, options.yes);
188
+ printBanner();
189
+
190
+ const targetInput = options.target || await ask('Workspace directory', '.', rl, options.yes);
191
+ const layoutInput = options.layout || await askLayout(rl, options.yes);
152
192
  validateLayout(layoutInput);
153
193
 
154
194
  const workspaceDir = resolve(process.cwd(), targetInput);
155
195
  const installDir = layoutInput === 'nestbox' ? join(workspaceDir, '.nestbox') : workspaceDir;
156
196
 
197
+ await confirmCreation(rl, options.yes, workspaceDir, installDir, layoutInput);
198
+
157
199
  if (!(await isDirectoryEmpty(installDir))) {
158
200
  throw new Error(`Refusing to overwrite non-empty installation target: ${installDir}`);
159
201
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@p10i/create-nestbox",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Create Nestbox projects.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
8
- "create-nestbox": "./bin/create-nestbox.js"
8
+ "create-nestbox": "bin/create-nestbox.js"
9
9
  },
10
10
  "files": [
11
11
  "bin/",