@surph_ai/cli 0.0.34 → 0.0.35

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/board/deploy.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // the board's folder. Built up step by step; so far:
4
4
  //
5
5
  // 1. Zip the board's site: every file in the folder except the project
6
- // files (package.json, package-lock.json, README.md, board.json,
6
+ // files (package.json, package-lock.json, README.md, AGENTS.md, CLAUDE.md, board.json,
7
7
  // node_modules), dot-files (.env, .git, .DS_Store) and the zip itself.
8
8
  // Written to site.zip in the board's folder.
9
9
  // 2. Ask Surph for an upload address for it: boards/<slug>/site/site.zip on
@@ -14,7 +14,8 @@
14
14
  // 5. Upload board.json to boards/<slug>/board.json — last, so the live
15
15
  // board's definition only changes once its site is up.
16
16
  //
17
- // Node's built-ins only (zlib for compression, fetch for the upload; Node 18+).
17
+ // Node's built-ins only (zlib for compression, fetch for the upload). Needs
18
+ // Node.js 20 or later.
18
19
 
19
20
  const fs = require('fs');
20
21
  const path = require('path');
@@ -28,7 +29,7 @@ const SYNC_URL = 'https://e3lunom2hka3u6iiotrlzrcez40uwdnk.lambda-url.us-east-1.
28
29
  const SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
29
30
 
30
31
  // Left out at the board's top level: the project's own files.
31
- const SKIP_AT_ROOT = new Set(['package.json', 'package-lock.json', 'README.md', 'board.json', ZIP_NAME]);
32
+ const SKIP_AT_ROOT = new Set(['package.json', 'package-lock.json', 'README.md', 'AGENTS.md', 'CLAUDE.md', 'board.json', ZIP_NAME]);
32
33
 
33
34
  // The files to deploy, as paths relative to the board's folder ('/'-separated).
34
35
  const siteFiles = (dir = ROOT, rel = '') => {
@@ -224,7 +225,13 @@ const main = async () => {
224
225
  console.log(`Uploaded: ${boardUrl.split('?')[0]}`);
225
226
  };
226
227
 
227
- const run = () => main().catch((error) => fail(`Deploy failed: ${error.message}`));
228
+ const MIN_NODE = 20;
229
+
230
+ const run = () => {
231
+ const major = Number(process.versions.node.split('.')[0]);
232
+ if (major < MIN_NODE) fail(`Deploying a board needs Node.js ${MIN_NODE} or later; this is ${process.version}. Install a newer Node.js (https://nodejs.org) and try again.`);
233
+ return main().catch((error) => fail(`Deploy failed: ${error.message}`));
234
+ };
228
235
 
229
236
  // `surph board-deploy` calls run(); running this file directly runs it too.
230
237
  if (require.main === module) run();
package/board/server.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // The board's local dev server (`npm run dev` → `surph-board-dev`): serves
3
3
  // the board folder it's run from (the current directory) at
4
4
  // http://localhost:4180 for Surph's dev mode (Settings → Developer → Run
5
- // Surph as a local board). Node's built-ins only.
5
+ // Surph as a local board). Node's built-ins only; needs Node.js 20 or later.
6
6
  //
7
7
  // GET /<file> This folder's files, never cached, with CORS so
8
8
  // Surph (another address) can read board.json.
@@ -158,7 +158,14 @@ const handle = async (req, res) => {
158
158
 
159
159
  // Start serving the current folder. localhost may be reached over IPv4 or
160
160
  // IPv6: listen on both loopbacks.
161
+ const MIN_NODE = 20;
162
+
161
163
  const start = () => {
164
+ const major = Number(process.versions.node.split('.')[0]);
165
+ if (major < MIN_NODE) {
166
+ console.error(`The board dev server needs Node.js ${MIN_NODE} or later; this is ${process.version}. Install a newer Node.js (https://nodejs.org) and try again.`);
167
+ process.exit(1);
168
+ }
162
169
  http.createServer(handle)
163
170
  .on('error', (error) => {
164
171
  console.error(error.code === 'EADDRINUSE'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@surph_ai/cli",
3
- "version": "0.0.34",
3
+ "version": "0.0.35",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "types": "./types.d.ts",
@@ -0,0 +1,32 @@
1
+ # Surph board: notes for coding agents
2
+
3
+ This folder is a **Surph board**: static web pages that Surph shows in its canvas, beside the Surph chat. The person you're working with may not be technical. Explain steps in plain words, and say what a command does before you run it.
4
+
5
+ **`README.md` is the full reference.** Read it before writing or changing a page: it lists every operation Surph answers, the item shape, the rules for pages, and how `board.json` works. This file covers setup and the working loop.
6
+
7
+ ## Setup: Node.js
8
+
9
+ Previewing and publishing the board need **Node.js 20 or later**. The pages themselves don't.
10
+
11
+ 1. Check with `node -v`.
12
+ 2. If it's missing or older than 20, tell the person that Node.js is needed to preview the board inside Surph and to publish it, and offer to install it. Install only with their OK.
13
+ - **Mac:** prefer a user-level install that needs no admin password, such as [fnm](https://github.com/Schniz/fnm) (`curl -fsSL https://fnm.vercel.app/install | bash`, then `fnm install --lts`). Homebrew (`brew install node`) is fine if Homebrew is already installed.
14
+ - **Windows:** `winget install OpenJS.NodeJS.LTS` (Windows may ask the person to approve once).
15
+ - **Linux:** the distribution's package manager, or fnm as on Mac.
16
+ 3. A fresh install may not be visible in the current terminal. If `node -v` still fails afterwards, open a new terminal session (or load the shell profile) and check again.
17
+ 4. If an install isn't possible (declined, or blocked on a work computer), point them to the installer at https://nodejs.org and wait for them.
18
+
19
+ ## The working loop
20
+
21
+ 1. **Preview:** run `npm run dev` from this folder and leave it running. It serves the board at `http://localhost:4180` (nothing to install; it uses the Surph CLI through `npx`).
22
+ 2. **See it in Surph:** ask the person to open Surph, go to **Settings → Developer**, turn on **Run Surph as a local board**, and keep the address `http://localhost:4180`. Surph reloads as this board.
23
+ 3. **Configure the board** (name, contexts, tools, instructions): the person can click the **DEV** label in Surph's canvas header to open the Local board panel, which saves `board.json` for you. You can also edit `board.json` directly; the README describes every field.
24
+ 4. **Change pages:** edit the HTML in this folder and keep `board.json`'s `config.pages` in step (every page listed, `shows` written as plain facts, `ops` matching the page's `host.rpc` calls). The person reloads Surph to see the change.
25
+ 5. **Publish:** `npm run deploy`. **Only when the person asks you to in this conversation.** It replaces the live board for everyone who uses it. Check the board in dev mode first.
26
+
27
+ ## What to keep in mind
28
+
29
+ - Pages talk to Surph only through the Surph SDK (`host.rpc(…)`) and only with the operations the README lists. Don't invent operations or fields; if a page needs data Surph doesn't offer, say so.
30
+ - Write data from Surph with `textContent`, never `innerHTML`.
31
+ - Everything in this folder except `package.json`, `package-lock.json`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `board.json`, `node_modules` and dot-files gets published by `npm run deploy`. Keep drafts, exports and secrets out of it (or in dot-files).
32
+ - Before handing off, go through the README's "Checklist before handing off a change".
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -410,10 +410,10 @@ A field marked "omitted" is missing from the object, not `null`. Every URL is `h
410
410
 
411
411
  ## Deploying
412
412
 
413
- `npm run deploy` (`npx @surph_ai/cli board-deploy`, from the Surph CLI) publishes the board to Surph. Run it from the board's folder. It needs Node 18 or later and nothing else installed. In order, it:
413
+ `npm run deploy` (`npx @surph_ai/cli board-deploy`, from the Surph CLI) publishes the board to Surph. Run it from the board's folder. It needs Node.js 20 or later and nothing else installed. In order, it:
414
414
 
415
415
  1. **Reads the board's `slug`** from `board.json` (lowercase letters, digits and dashes). The slug names the board's place in Surph; without a valid one it stops before doing anything.
416
- 2. **Zips the site** into `site.zip`: every file in the folder except `package.json`, `package-lock.json`, `README.md`, `board.json`, `node_modules`, dot-files (`.env`, `.git`, `.DS_Store`) and `site.zip` itself. It lists the files it zipped.
416
+ 2. **Zips the site** into `site.zip`: every file in the folder except `package.json`, `package-lock.json`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `board.json`, `node_modules`, dot-files (`.env`, `.git`, `.DS_Store`) and `site.zip` itself. It lists the files it zipped.
417
417
  3. **Uploads `site.zip`** to the board's `site/` folder in Surph's storage, then deletes the local `site.zip`. If the upload fails, the zip is kept to look at.
418
418
  4. **Unzips it there**, so the pages and `assets/` sit in the board's `site/` folder, where each page's `file` is found.
419
419
  5. **Uploads `board.json`**, last, so the live board's definition only changes once its pages are up. If an earlier step fails, `board.json` isn't uploaded and the live board keeps its previous version.
@@ -9,5 +9,8 @@
9
9
  "keywords": [],
10
10
  "author": "",
11
11
  "license": "ISC",
12
- "type": "commonjs"
12
+ "type": "commonjs",
13
+ "engines": {
14
+ "node": ">=20"
15
+ }
13
16
  }
package/scaffold/index.js CHANGED
@@ -270,6 +270,8 @@ const scaffoldBoard = async (name) => {
270
270
  utils.write('package.json', JSON.stringify(pkgJson, null, 2) + '\n')
271
271
 
272
272
  shell.cp('-R', path.join(__dirname, `board/README.md`), 'README.md')
273
+ shell.cp('-R', path.join(__dirname, `board/AGENTS.md`), 'AGENTS.md')
274
+ shell.cp('-R', path.join(__dirname, `board/CLAUDE.md`), 'CLAUDE.md')
273
275
  shell.cp('-R', path.join(__dirname, `board/index.html`), 'index.html')
274
276
  shell.cp('-R', path.join(__dirname, `board/board.json`), 'board.json')
275
277