@p10i/create-nestbox 0.5.0 → 0.6.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.
package/.dockerignore CHANGED
@@ -1,17 +1,17 @@
1
- # Build context hygiene — keep image builds small and reproducible.
2
-
3
- # VCS / IDE
1
+ # Build context hygiene — keep image builds small and reproducible.
2
+
3
+ # VCS / IDE
4
4
  .git
5
5
  **/.git
6
- .gitignore
7
- .vscode
8
- .idea
9
-
10
- # Local environment
6
+ .gitignore
7
+ .vscode
8
+ .idea
9
+
10
+ # Local environment
11
11
  .env
12
12
  .env.*
13
13
  !.env.example
14
-
14
+
15
15
  # npm / Composer caches that may live in the working tree
16
16
  node_modules
17
17
  vendor
@@ -22,15 +22,15 @@ vendor
22
22
  # Page state is local by default and must not leak into image layers. A page
23
23
  # that deliberately ships durable data must explicitly revise this policy.
24
24
  home/code/**/__data/**
25
-
26
- # OS junk
27
- .DS_Store
28
- Thumbs.db
29
-
30
- # Bundles are produced inside the build, not pulled from the host.
31
- home/code/scripts-bundle.js
32
- home/code/scripts-bundle.css
33
-
25
+
26
+ # OS junk
27
+ .DS_Store
28
+ Thumbs.db
29
+
30
+ # Bundles are produced inside the build, not pulled from the host.
31
+ home/code/scripts-bundle.js
32
+ home/code/scripts-bundle.css
33
+
34
34
  # Docs and metadata not needed at build time
35
35
  README.md
36
36
  LICENSE
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ - Consistently track latest-stable runtime images, dynamically select Alpine's newest PHP CLI branch, and document fresh builds with `--pull --no-cache`.
6
+ - Remove native host npm execution, npm script confirmation tools, the host runner, its stdio bridge, and the loopback job API. Keep label-gated container execution and structured control logs.
7
+ - Stop creating or modifying workspace package manifests during installation. Remove package.json-specific bind mounts and the control service's workspace mount.
8
+ - Run the installed runtime entirely in Docker; host Node.js is needed only when using the npm creator.
9
+ - Load OpenCode instructions and instance policy by absolute `/etc/opencode` paths, incorporating Gitea fix `4d53e89`.
10
+ - See `INSTALL.md` for existing-installation cleanup and activation steps.
11
+
3
12
  ## 0.5.0
4
13
 
5
14
  - Replace the public token-authenticated host API with a persistent `docker compose exec -T control` stdio bridge.
package/INSTALL.md CHANGED
@@ -12,15 +12,14 @@ npm create @p10i/nestbox@latest
12
12
 
13
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
- The creator does not start Docker, start the host bridge, or collect secrets. Node.js and npm are required for the bridge. After it finishes, edit `.env`, then run from the installation directory:
15
+ The creator does not start Docker or collect secrets. Node.js and npm are needed only to run the creator, not the installed runtime. After it finishes, edit `.env`, then run from the installation directory:
16
16
 
17
17
  ```sh
18
18
  docker compose config --quiet
19
- docker compose up -d --build
19
+ docker compose build --pull --no-cache
20
+ docker compose up -d
20
21
  ```
21
22
 
22
- After `control` is healthy, run `npm run host --` from the workspace in a separate terminal.
23
-
24
23
  Then run the host test suite documented in section 7.
25
24
 
26
25
  ## 1. Choose Language
@@ -56,7 +55,7 @@ docker version
56
55
  docker compose version
57
56
  ```
58
57
 
59
- Nestbox requires Git, Node.js with npm, a running Docker Engine, and Docker Compose v2. If something is missing, explain the platform-specific requirement and pause. Do not install system software without approval.
58
+ Nestbox requires Git, a running Docker Engine, and Docker Compose v2. The npm creator additionally requires Node.js with npm; installation from Git does not. If something is missing, explain the platform-specific requirement and pause. Do not install system software without approval.
60
59
 
61
60
  Inspect Git status for the selected directory and installation target before changing files. Preserve unrelated changes. The fresh Nestbox repository remains independent in both default layouts, including when `.nestbox` is nested inside another Git workspace.
62
61
 
@@ -96,14 +95,7 @@ Copy `.env.example` to `.env` and `home/configs/opencode/instance.example.md` to
96
95
 
97
96
  Relative bind paths resolve from the installation directory. The page tree is mounted as `/home/code` in runtime services and as the writable `/nestbox/home/code` agent path. `WORKSPACE_PATH` is mounted as `/workspace` in PHP and OpenCode. `NESTBOX_PAGE_PATH` remains an optional advanced override for a user-requested external page tree.
98
97
 
99
- Configure the host bridge in the workspace root before Compose starts:
100
-
101
- - For `.nestbox` layout, create `package.json` from `.nestbox/package.host.json` when absent, or merge only its `host` and `test:host` scripts into the existing manifest.
102
- - For direct layout, use `node host-runner.mjs` and `node tests/host-runner.mjs` for those scripts. A source clone's publisher-oriented `package.json` may be replaced by this installation manifest after preserving any intentional project metadata.
103
- - Never overwrite a conflicting script. Stop and ask for a different script name.
104
- - Start `npm run host --` after `control` is healthy. The runner opens a persistent `docker compose exec -T control` stdio bridge from the installation directory. The image-resident helper sends heartbeats and job results through the server's container-loopback API without a host listener, token, published port, or shared queue files.
105
- - If the runner reports a stale control image, rebuild and recreate `control` with `docker compose build control` and `docker compose up -d control`.
106
- - The workspace manifest is mounted read-only in runtime containers. Confirmed changes are written only by the native host runner.
98
+ The runtime does not require a workspace `package.json`. Project manifests are accessed through the ordinary workspace mounts in PHP-FPM and OpenCode. The control service mounts only the Docker socket and provides label-gated container execution.
107
99
 
108
100
  Update the new `home/configs/opencode/instance.md` with:
109
101
 
@@ -126,7 +118,7 @@ Then ask about:
126
118
  - Linux UID and GID when bind-mount ownership matters;
127
119
  - additional directories required by PHP and OpenCode;
128
120
  - an optional reverse-proxy URL prefix;
129
- - rolling or pinned container images;
121
+ - the default latest-stable image policy, with pinning only as an explicitly requested adaptation;
130
122
  - `NESTBOX_OPENCODE_PUBLIC_URL` when `agent.<nestbox-host>` cannot be derived.
131
123
 
132
124
  Open `.env` in a local editor for runtime settings and secrets. Never ask the user to paste provider keys into chat or print the completed file.
@@ -135,7 +127,9 @@ Before startup, query existing Docker containers with the proposed Compose proje
135
127
 
136
128
  For additional directories, mount the same host path at the same container path in PHP and OpenCode. Extend OpenCode's `external_directory` permission when unattended access is intended. Prefer read-only mounts unless writing is required.
137
129
 
138
- Keep PHP-FPM and OpenCode's PHP CLI on the same PHP version. For a path-prefixed reverse proxy, the outer proxy removes the prefix before forwarding and configures `NESTBOX_URL_PREFIX`. Set `NESTBOX_OPENCODE_PUBLIC_URL` explicitly whenever the public OpenCode scheme or host differs from direct Nestbox access.
130
+ Nestbox defaults to rolling latest-stable image tags and the latest system packages available in their configured repositories. OpenCode selects the newest PHP branch available from Alpine; PHP-FPM follows the official rolling PHP image. Verify both runtime versions after each build because Alpine packaging can lag upstream PHP. Resolve any incompatible branch mismatch before handoff. Use `docker compose build --pull --no-cache` to refresh base images and cached package-install layers. Application library lockfiles remain authoritative and are updated separately.
131
+
132
+ For a path-prefixed reverse proxy, the outer proxy removes the prefix before forwarding and configures `NESTBOX_URL_PREFIX`. Set `NESTBOX_OPENCODE_PUBLIC_URL` explicitly whenever the public OpenCode scheme or host differs from direct Nestbox access.
139
133
 
140
134
  ## 6. Keep The Public Page Tree Empty
141
135
 
@@ -149,17 +143,12 @@ Run from the installation directory:
149
143
 
150
144
  ```sh
151
145
  docker compose config --quiet
152
- docker compose up -d --build
146
+ docker compose build --pull --no-cache
147
+ docker compose up -d
153
148
  docker compose ps
154
149
  docker compose port nginx 80
155
150
  ```
156
151
 
157
- In a separate terminal, keep the bridge running from the workspace root:
158
-
159
- ```sh
160
- npm run host --
161
- ```
162
-
163
152
  Verify:
164
153
 
165
154
  - `/` retains HTTP 404 and renders the OpenCode implementation form;
@@ -167,7 +156,7 @@ Verify:
167
156
  - `php /sources/php/cli.php __templates/super-document` is rejected;
168
157
  - `/Agent` redirects to OpenCode on the same published port;
169
158
  - the actual OpenCode URL works in the user's client;
170
- - `npm run test:host` passes and control health reports the host runner as available;
159
+ - `control` is healthy and its API is not published on the host;
171
160
  - a provider and model are available for agent work, without printing credentials or sending a billable prompt unless the user approves it;
172
161
  - `/_nestbox/health` returns HTTP 200;
173
162
  - a transient PHP event reaches an EventSource subscriber through Nchan;
@@ -245,7 +234,7 @@ Send this work to the internal OpenCode agent. A useful prompt is:
245
234
  Extend this Nestbox installation for the following requirement: <request>. Inspect /workspace and /nestbox, follow the internal Nestbox manual, implement and verify all file changes you can, and report the exact host-side activation command for any container or infrastructure change.
246
235
  ```
247
236
 
248
- The internal agent edits pages and infrastructure definitions. It has no Docker socket. It may use only the label-gated control MCP for approved container commands and declared host npm scripts; broader activation remains an external-maintainer task.
237
+ The internal agent edits pages and infrastructure definitions. It has no Docker socket. It uses the label-gated control MCP for approved container commands; host-side activation remains an external-maintainer task.
249
238
 
250
239
  ## 10. Git And Generated State
251
240
 
@@ -274,3 +263,22 @@ When a super-document intentionally changes files in `/workspace`, follow that w
274
263
  ## 11. Optional Adaptations
275
264
 
276
265
  Retaining upstream Git history, adding an upstream remote, external page trees, parent-owned engines, submodules, vendoring, shared repositories, alternate Compose layouts, and operating-system shortcuts are optional. Explain their ownership consequences and obtain explicit confirmation before creating them. They must not obscure the two default installation paths.
266
+
267
+ ## Upgrading From Host-Runner Versions
268
+
269
+ Host npm execution and npm script confirmation tools have been removed. Container execution through `docker_exec` and `nestbox_control_exec()` remains available.
270
+
271
+ 1. Stop the old `npm run host --` terminal or any service configured to launch it.
272
+ 2. Apply the source update while preserving installation-specific Compose overrides, `.env`, pages, and `instance.md`. Remove obsolete `host-runner.mjs`, `package.host.json`, `docker/control/host_bridge.py`, and `tests/host-runner.mjs` if the update mechanism leaves deleted files behind.
273
+ 3. Remove only the Nestbox-generated `host` and `test:host` scripts from the workspace `package.json`, after checking that they still point to the removed runner and test. Preserve project scripts and metadata. If the manifest was generated solely for the runner, it may be removed after confirming nothing else uses it.
274
+ 4. Remove `nestbox.npm.allow`, package.json-specific read-only mounts, and the control service's workspace mount from any local overrides. Keep the ordinary workspace mounts in PHP-FPM and OpenCode. Older installations may also remove obsolete host-token settings and mounts described in the changelog.
275
+ 5. From the installation directory, validate and activate the affected services:
276
+
277
+ ```sh
278
+ docker compose config --quiet
279
+ docker compose build --pull --no-cache control opencode
280
+ docker compose up -d control php-fpm opencode
281
+ bash tests/nestbox.sh
282
+ ```
283
+
284
+ On Windows, run `.\tests\nestbox.ps1` instead of the Bash test. Reconnect to OpenCode after recreation so it loads the updated MCP tools and instructions. Inspect `docker compose ps` and `docker compose logs control` to confirm health. Project workloads formerly executed on the host must use an appropriate project container or be run manually by the host maintainer.
package/README.md CHANGED
@@ -8,13 +8,29 @@ Its core design is the **super-document**: one cohesive PHP and Markdown documen
8
8
 
9
9
  Nestbox runs with Docker Compose using Nginx, PHP-FPM, Rollup, OpenCode, and a private control service. A fresh installation opens with a prompt for creating its first screen instead of shipping a predefined application.
10
10
 
11
- ## Container And Host Control
11
+ ## Container Control
12
12
 
13
13
  The `control` service is the only container with `/var/run/docker.sock`. Its internal-only API permits exec only when caller, target, project, and root-user labels allow it. OpenCode reaches the API through the bundled control MCP and can target PHP-FPM and Rollup by default. Trusted PHP pages can use `nestbox_control_exec()` and are restricted to PHP-FPM self-exec.
14
14
 
15
- Native host commands are limited to scripts already declared in the workspace `package.json`. Keep `npm run host --` running from the workspace when host scripts are needed. The native runner maintains a `docker compose exec -T control` stdio bridge; its image-resident helper talks only to the control server on container loopback. No host API, runner token, second published port, or shared filesystem queue is used. MCP can request script additions, edits, or deletions, but the host runner applies them only after the user supplies a short-lived code displayed exclusively in the host terminal.
15
+ Project commands run inside the appropriate container through `docker_exec`. Host-side Docker Compose activation is performed by the user or external maintainer. Nestbox needs no background process on the host and no workspace `package.json`.
16
16
 
17
- Control emits bounded structured events to ordinary container logs. Use `docker compose logs control`; no telemetry collector, database, or observability dependency is installed. Docker socket access is root-equivalent on the host, and host scripts execute in the trusted writable workspace, so neither mechanism is a sandbox.
17
+ Control emits bounded structured events to ordinary container logs. Use `docker compose logs control`; no telemetry collector, database, or observability dependency is installed. Docker socket access is root-equivalent on the host, so this is a controlled capability, not a sandbox.
18
+
19
+ ## Runtime Versions And Updates
20
+
21
+ Nestbox tracks the latest stable container images by default: OpenCode and Composer use `latest`, Alpine uses `latest`, and Node, Python, and PHP use their rolling Alpine variants. Alpine-installed tools use the newest packages available in the base image's configured repositories; OpenCode's PHP CLI selects the newest available PHP branch. These repositories can lag upstream releases, so verify the resulting PHP CLI and FPM versions after a refresh.
22
+
23
+ Refresh images and installed system packages from the installation directory:
24
+
25
+ ```sh
26
+ docker compose config --quiet
27
+ docker compose build --pull --no-cache
28
+ docker compose up -d
29
+ docker compose exec -T php-fpm php --version
30
+ docker compose exec -T opencode php --version
31
+ ```
32
+
33
+ Reconnect to OpenCode after recreation, then run `bash tests/nestbox.sh` or `.\tests\nestbox.ps1`. Existing containers do not update automatically. JavaScript and PHP library dependencies continue to use their committed lockfiles; runtime refreshes do not rewrite those dependencies.
18
34
 
19
35
  ## Learn More
20
36
 
@@ -32,7 +48,9 @@ Create a new Nestbox project with npm:
32
48
  npm create @p10i/nestbox@latest
33
49
  ```
34
50
 
35
- 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. It creates a minimal workspace `package.json` when absent or safely merges non-conflicting `host` and `test:host` scripts into an existing manifest. After creation, edit `.env`, start `npm run host --`, then run the Docker Compose validation and startup commands printed by the creator.
51
+ 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. The workspace's package manifest is left untouched. After creation, edit `.env`, then run the Docker Compose validation and startup commands printed by the creator. Node.js and npm are needed only to use the creator; the installed runtime runs entirely in Docker.
52
+
53
+ For upgrades from versions with host npm execution, see the migration notes in [INSTALL.md](INSTALL.md#upgrading-from-host-runner-versions).
36
54
 
37
55
  For agent-guided installation or repair work, copy and send this to an agent with filesystem, Git, Docker, and terminal access:
38
56
 
@@ -14,8 +14,6 @@ const copyEntries = [
14
14
  'docker',
15
15
  'home',
16
16
  'tests',
17
- 'host-runner.mjs',
18
- 'package.host.json',
19
17
  'docker-compose.yaml',
20
18
  '.dockerignore',
21
19
  '.env.example',
@@ -171,57 +169,6 @@ async function configureInstance(installDir, workspaceDir, layout) {
171
169
  await writeFile(instancePath, instance, 'utf8');
172
170
  }
173
171
 
174
- function hostScripts(layout) {
175
- const prefix = layout === 'nestbox' ? '.nestbox/' : '';
176
- return {
177
- host: `node ${prefix}host-runner.mjs`,
178
- 'test:host': `node ${prefix}tests/host-runner.mjs`
179
- };
180
- }
181
-
182
- async function readWorkspacePackage(workspaceDir) {
183
- const path = join(workspaceDir, 'package.json');
184
- if (!(await pathExists(path))) return null;
185
- let document;
186
- try {
187
- document = JSON.parse(await readFile(path, 'utf8'));
188
- } catch (error) {
189
- throw new Error(`Cannot use workspace package.json: ${error.message}`);
190
- }
191
- if (!document || typeof document !== 'object' || Array.isArray(document)) {
192
- throw new Error('Workspace package.json must contain a JSON object.');
193
- }
194
- if (document.scripts !== undefined && (!document.scripts || typeof document.scripts !== 'object' || Array.isArray(document.scripts))) {
195
- throw new Error('Workspace package.json scripts must be an object.');
196
- }
197
- return document;
198
- }
199
-
200
- async function preflightHostPackage(workspaceDir, layout) {
201
- const document = await readWorkspacePackage(workspaceDir);
202
- if (!document) return;
203
- for (const [name, command] of Object.entries(hostScripts(layout))) {
204
- if (document.scripts?.[name] !== undefined && document.scripts[name] !== command) {
205
- throw new Error(`Refusing to overwrite existing workspace npm script: ${name}`);
206
- }
207
- }
208
- }
209
-
210
- async function configureHostPackage(installDir, workspaceDir, layout) {
211
- const scripts = hostScripts(layout);
212
- const document = await readWorkspacePackage(workspaceDir) || {
213
- name: 'nestbox-workspace',
214
- private: true
215
- };
216
- document.scripts = { ...(document.scripts || {}), ...scripts };
217
- await writeFile(join(workspaceDir, 'package.json'), `${JSON.stringify(document, null, 2)}\n`, 'utf8');
218
- await writeFile(join(installDir, 'package.host.json'), `${JSON.stringify({
219
- name: 'nestbox-workspace',
220
- private: true,
221
- scripts
222
- }, null, 2)}\n`, 'utf8');
223
- }
224
-
225
172
  function commandExists(command) {
226
173
  const result = spawnSync(command, ['--version'], { stdio: 'ignore' });
227
174
  return result.status === 0;
@@ -258,12 +205,9 @@ async function main() {
258
205
  throw new Error(`Refusing to overwrite non-empty installation target: ${installDir}`);
259
206
  }
260
207
 
261
- await preflightHostPackage(workspaceDir, layoutInput);
262
-
263
208
  await mkdir(installDir, { recursive: true });
264
209
  await copyTemplate(installDir);
265
210
  await configureInstance(installDir, workspaceDir, layoutInput);
266
- await configureHostPackage(installDir, workspaceDir, layoutInput);
267
211
  const gitInitialized = options.git ? initGit(installDir) : false;
268
212
 
269
213
  console.log('\nNestbox project created.');
@@ -274,10 +218,8 @@ async function main() {
274
218
  console.log(` cd ${installDir}`);
275
219
  console.log(' Edit .env and set COMPOSE_PROJECT_NAME, WEB_PORT, OpenCode credentials, and provider keys.');
276
220
  console.log(' docker compose config --quiet');
277
- console.log(' docker compose up -d --build');
278
- console.log(` cd ${workspaceDir}`);
279
- console.log(' npm run host --');
280
- console.log(` cd ${installDir}`);
221
+ console.log(' docker compose build --pull --no-cache');
222
+ console.log(' docker compose up -d');
281
223
  console.log(process.platform === 'win32' ? ' .\\tests\\nestbox.ps1' : ' bash tests/nestbox.sh');
282
224
  } finally {
283
225
  rl.close();
@@ -1,12 +1,11 @@
1
- FROM python:3.12-alpine
1
+ FROM python:alpine
2
2
 
3
3
  COPY ./docker/control/server.py /usr/local/bin/nestbox-control
4
- COPY ./docker/control/host_bridge.py /usr/local/bin/nestbox-host-bridge
5
4
 
6
- RUN python -m py_compile /usr/local/bin/nestbox-control /usr/local/bin/nestbox-host-bridge && \
7
- chmod 0755 /usr/local/bin/nestbox-control /usr/local/bin/nestbox-host-bridge
5
+ RUN python -m py_compile /usr/local/bin/nestbox-control && \
6
+ chmod 0755 /usr/local/bin/nestbox-control
8
7
 
9
- WORKDIR /workspace
8
+ WORKDIR /
10
9
 
11
10
  EXPOSE 4088
12
11