nerdsystem 0.0.6 → 0.0.7

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/dist/index.js CHANGED
@@ -1,263 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { parseArgs } from "node:util";
3
- import { authConfig, authSecret } from "./commands/auth.js";
4
- import { check } from "./commands/check.js";
5
- import { dbMigrate, dbMigrations, dbQuery } from "./commands/db.js";
6
- import { deploy, deployments } from "./commands/deploy.js";
7
- import { dev } from "./commands/dev.js";
8
- import { doctor } from "./commands/doctor.js";
9
- import { cron, health, rollback, secretList, secretRemove, secretSet, transfer, waitlist } from "./commands/ops.js";
10
- import { agentsSync } from "./commands/agents.js";
11
- import { billingPortal, billingShow, billingUpgrade } from "./commands/billing.js";
12
- import { auditExport, clientsCreate, clientsList, clientsRelease, domainsAdd, domainsList, domainsRemove, logs, membersInvite, membersList, membersRemove } from "./commands/org.js";
13
- import { buildsList, buildsShow, buildsTrigger } from "./commands/builds.js";
14
- import { githubConnect, githubLink, githubStatus, githubUnlink } from "./commands/github.js";
15
- import { init, linkProject } from "./commands/init.js";
16
- import { login, whoami } from "./commands/login.js";
17
- import { findProjectRoot } from "./project.js";
18
- import { CliError, log } from "./util.js";
19
- const HELP = `nerd — deploy apps to nerdsystem
20
-
21
- nerd login [--email you@x.com] Sign in or sign up: prints a link to approve in the browser (--email sends it; --token nsk_... for scripts)
22
- nerd whoami Show the current user and orgs
23
- nerd doctor Check Node, pnpm, git, login, and the project
24
- nerd init <dir> [--org] [--name] [--describe "what it does"] Create an app and a project for it
25
- nerd link --slug <project> [--org] Link this directory to an existing or new project
26
- nerd dev [vite args] Run locally (writes .dev.vars, applies local migrations)
27
- nerd check [--no-build] [--rule id] [--json] Run every gate a deploy runs; --json gives failures the agent can fix (alias: nerd verify)
28
- nerd deploy [--note "what changed"] Check, build, migrate, upload. Prints the URL
29
- nerd rollback [deploymentId] Re-publish the previous production bundle
30
- nerd cron [off|hourly|daily] Scheduled job: the platform calls POST /api/cron
31
- nerd transfer <org> Move this project to another org you administer
32
- nerd health Platform component health (operators)
33
- nerd waitlist [approve <id>] Who is waiting for access while sign-up is invite-only (operators)
34
- nerd deployments List recent deployments
35
- nerd db query "<sql>" Run SQL on the production database
36
- nerd db migrate Apply pending migrations to production
37
- nerd db migrations List applied migrations
38
- nerd auth config [--roles a,b] [--default-role r] [--signup on|off]
39
- nerd auth secret Mint a dev tenant secret into .dev.vars
40
- nerd secret set NAME [value] App secret for production (c.env.NAME); value from stdin when omitted
41
- nerd secret list | rm NAME Names only; values are never shown
42
- nerd github connect Install the GitHub App for this org (prints a link)
43
- nerd github link owner/repo [--branch main] [--root-dir dir] [--no-previews] [--require-pr] [--agent @claude]
44
- nerd github status | unlink
45
- nerd builds [--limit n] List git-triggered builds
46
- nerd builds show <id> Build details and log
47
- nerd builds trigger [--branch b] [--commit sha]
48
- nerd agents sync Regenerate AGENTS.md, Cursor, Copilot, Gemini files from the skill
49
- nerd billing [--org slug] Plan, limits, and usage for the org
50
- nerd billing upgrade --plan pro|studio [--annual] Start checkout
51
- nerd billing portal Manage cards, invoices, and plan
52
- nerd members [invite <email> --role r | remove <userId>] Org members and invitations
53
- nerd clients [create <slug> --name n | release <slug>] Studio: one org per client, billed through yours
54
- nerd domains [add <hostname> | remove <id>] Custom domains for this project
55
- nerd logs [--since 30m] [--limit 100] [--q text] [--pr n] Logs from the deployed app
56
- nerd audit [--out file.csv] Export deployments and builds (Studio)
57
-
58
- Every command accepts --json for machine-readable output.`;
59
- const BOOL = { type: "boolean", default: false };
60
- const STR = { type: "string" };
61
- async function main(argv) {
62
- const [cmd, ...rest] = argv;
63
- if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
64
- console.log(HELP);
65
- return;
66
- }
67
- const parse = (options, allowPositionals = true) => parseArgs({ args: rest, options: { json: BOOL, ...options }, allowPositionals, strict: cmd !== "dev" });
68
- switch (cmd) {
69
- case "login": {
70
- const { values } = parse({ token: STR, "api-url": STR, email: STR });
71
- return login(values);
72
- }
73
- case "doctor": {
74
- const { values } = parse({});
75
- return doctor({ json: Boolean(values.json) });
76
- }
77
- case "whoami": {
78
- const { values } = parse({});
79
- return whoami({ json: Boolean(values.json) });
80
- }
81
- case "init": {
82
- const { values, positionals } = parse({ org: STR, name: STR, slug: STR, describe: STR, "no-create": BOOL });
83
- return init(positionals[0], values);
84
- }
85
- case "link": {
86
- const { values } = parse({ org: STR, slug: STR, name: STR, "no-create": BOOL });
87
- if (!values.slug)
88
- throw new CliError("Usage: nerd link --slug <project> [--org <org>] [--name 'My App']");
89
- const root = (() => {
90
- try {
91
- return findProjectRoot();
92
- }
93
- catch {
94
- return process.cwd();
95
- }
96
- })();
97
- await linkProject(root, { ...(values.org ? { org: values.org } : {}), slug: values.slug, name: values.name ?? values.slug, create: !values["no-create"] });
98
- return;
99
- }
100
- case "dev":
101
- return dev(rest);
102
- case "check":
103
- case "verify": {
104
- const { values } = parse({ "no-build": BOOL, "no-remote": BOOL, "no-typecheck": BOOL, rule: STR });
105
- return check({ json: Boolean(values.json), "no-build": Boolean(values["no-build"]), "no-remote": Boolean(values["no-remote"]), ...(values.rule ? { rule: values.rule } : {}) });
106
- }
107
- case "deploy": {
108
- const { values } = parse({ "skip-check": BOOL, "skip-build": BOOL, note: STR });
109
- return deploy(values);
110
- }
111
- case "rollback": {
112
- const { values, positionals } = parse({ note: STR });
113
- return rollback(positionals[0], { json: Boolean(values.json), ...(values.note ? { note: values.note } : {}) });
114
- }
115
- case "cron": {
116
- const { values, positionals } = parse({});
117
- return cron(positionals[0], { json: Boolean(values.json) });
118
- }
119
- case "transfer": {
120
- const { values, positionals } = parse({});
121
- return transfer(positionals[0], { json: Boolean(values.json) });
122
- }
123
- case "health": {
124
- const { values } = parse({});
125
- return health({ json: Boolean(values.json) });
126
- }
127
- case "waitlist": {
128
- const [sub, ...subRest] = rest;
129
- const { values, positionals } = parseArgs({ args: sub === "approve" ? subRest : rest, options: { json: BOOL }, allowPositionals: true });
130
- return waitlist({ json: Boolean(values.json), ...(sub === "approve" ? { approve: positionals[0] } : {}) });
131
- }
132
- case "deployments": {
133
- const { values } = parse({ limit: { type: "string", default: "10" } });
134
- return deployments(values);
135
- }
136
- case "db": {
137
- const [sub, ...subRest] = rest;
138
- const { values, positionals } = parseArgs({ args: subRest, options: { json: BOOL }, allowPositionals: true });
139
- if (sub === "query")
140
- return dbQuery(positionals[0], { json: Boolean(values.json) });
141
- if (sub === "migrate")
142
- return dbMigrate({ json: Boolean(values.json) });
143
- if (sub === "migrations")
144
- return dbMigrations({ json: Boolean(values.json) });
145
- throw new CliError("Usage: nerd db query|migrate|migrations");
146
- }
147
- case "auth": {
148
- const [sub, ...subRest] = rest;
149
- const { values } = parseArgs({ args: subRest, options: { json: BOOL, roles: STR, "default-role": STR, signup: STR }, allowPositionals: false });
150
- if (sub === "config")
151
- return authConfig(values);
152
- if (sub === "secret")
153
- return authSecret();
154
- throw new CliError("Usage: nerd auth config|secret");
155
- }
156
- case "billing": {
157
- const [sub, ...subRest] = rest;
158
- const isSub = sub === "upgrade" || sub === "portal" || sub === "show";
159
- const { values } = parseArgs({ args: isSub ? subRest : rest, options: { json: BOOL, org: STR, plan: STR, annual: BOOL }, allowPositionals: false });
160
- const o = { json: Boolean(values.json), ...(values.org ? { org: values.org } : {}) };
161
- if (sub === "upgrade")
162
- return billingUpgrade({ ...o, ...(values.plan ? { plan: values.plan } : {}), annual: Boolean(values.annual) });
163
- if (sub === "portal")
164
- return billingPortal(o);
165
- return billingShow(o);
166
- }
167
- case "members": {
168
- const [sub, ...subRest] = rest;
169
- const isSub = sub === "invite" || sub === "remove" || sub === "list";
170
- const { values, positionals } = parseArgs({ args: isSub ? subRest : rest, options: { json: BOOL, org: STR, role: STR }, allowPositionals: true });
171
- const o = { json: Boolean(values.json), ...(values.org ? { org: values.org } : {}) };
172
- if (sub === "invite")
173
- return membersInvite(positionals[0], { ...o, ...(values.role ? { role: values.role } : {}) });
174
- if (sub === "remove")
175
- return membersRemove(positionals[0], o);
176
- return membersList(o);
177
- }
178
- case "clients": {
179
- const [sub, ...subRest] = rest;
180
- const isSub = sub === "create" || sub === "release" || sub === "list";
181
- const { values, positionals } = parseArgs({ args: isSub ? subRest : rest, options: { json: BOOL, org: STR, name: STR }, allowPositionals: true });
182
- const o = { json: Boolean(values.json), ...(values.org ? { org: values.org } : {}) };
183
- if (sub === "create")
184
- return clientsCreate(positionals[0], { ...o, ...(values.name ? { name: values.name } : {}) });
185
- if (sub === "release")
186
- return clientsRelease(positionals[0], o);
187
- return clientsList(o);
188
- }
189
- case "secret": {
190
- const [sub, ...subRest] = rest;
191
- const { values, positionals } = parseArgs({ args: subRest, options: { json: BOOL, previews: BOOL }, allowPositionals: true });
192
- const json = Boolean(values.json);
193
- if (sub === "set")
194
- return secretSet(positionals[0], positionals[1], { json, previews: Boolean(values.previews) });
195
- if (sub === "rm" || sub === "remove" || sub === "delete")
196
- return secretRemove(positionals[0], { json });
197
- if (sub === "list" || sub === "ls" || sub === undefined)
198
- return secretList({ json });
199
- throw new CliError("Usage: nerd secret set NAME [value] [--previews] | list | rm NAME");
200
- }
201
- case "domains": {
202
- const [sub, ...subRest] = rest;
203
- const isSub = sub === "add" || sub === "remove" || sub === "list";
204
- const { values, positionals } = parseArgs({ args: isSub ? subRest : rest, options: { json: BOOL }, allowPositionals: true });
205
- const o = { json: Boolean(values.json) };
206
- if (sub === "add")
207
- return domainsAdd(positionals[0], o);
208
- if (sub === "remove")
209
- return domainsRemove(positionals[0], o);
210
- return domainsList(o);
211
- }
212
- case "logs": {
213
- const { values } = parse({ since: STR, limit: STR, q: STR, pr: STR });
214
- return logs({ json: Boolean(values.json), ...(values.since ? { since: values.since } : {}), ...(values.limit ? { limit: values.limit } : {}), ...(values.q ? { q: values.q } : {}), ...(values.pr ? { pr: values.pr } : {}) });
215
- }
216
- case "audit": {
217
- const { values } = parse({ org: STR, out: STR });
218
- return auditExport({ json: Boolean(values.json), ...(values.org ? { org: values.org } : {}), ...(values.out ? { out: values.out } : {}) });
219
- }
220
- case "agents": {
221
- const [sub, ...subRest] = rest;
222
- const { values } = parseArgs({ args: subRest, options: { json: BOOL }, allowPositionals: false });
223
- if (sub === "sync")
224
- return agentsSync({ json: Boolean(values.json) });
225
- throw new CliError("Usage: nerd agents sync");
226
- }
227
- case "github": {
228
- const [sub, ...subRest] = rest;
229
- const { values, positionals } = parseArgs({ args: subRest, options: { json: BOOL, branch: STR, "root-dir": STR, "no-previews": BOOL, "require-pr": BOOL, installation: STR, agent: STR }, allowPositionals: true });
230
- const json = Boolean(values.json);
231
- if (sub === "connect")
232
- return githubConnect({ json });
233
- if (sub === "link")
234
- return githubLink(positionals[0], { json, "no-previews": Boolean(values["no-previews"]), "require-pr": Boolean(values["require-pr"]), ...(values.agent ? { agent: String(values.agent) } : {}), ...(values.branch ? { branch: values.branch } : {}), ...(values["root-dir"] ? { "root-dir": values["root-dir"] } : {}), ...(values.installation ? { installation: values.installation } : {}) });
235
- if (sub === "unlink")
236
- return githubUnlink({ json });
237
- if (sub === "status" || sub === undefined)
238
- return githubStatus({ json });
239
- throw new CliError("Usage: nerd github connect|link|unlink|status");
240
- }
241
- case "builds": {
242
- const [sub, ...subRest] = rest;
243
- const isSub = sub === "show" || sub === "trigger" || sub === "list";
244
- const { values, positionals } = parseArgs({ args: isSub ? subRest : rest, options: { json: BOOL, limit: { type: "string", default: "10" }, branch: STR, commit: STR }, allowPositionals: true });
245
- const json = Boolean(values.json);
246
- if (sub === "show")
247
- return buildsShow(positionals[0], { json });
248
- if (sub === "trigger")
249
- return buildsTrigger({ json, ...(values.branch ? { branch: values.branch } : {}), ...(values.commit ? { commit: values.commit } : {}) });
250
- return buildsList({ json, limit: values.limit });
251
- }
252
- default:
253
- throw new CliError(`Unknown command "${cmd}". Run \`nerd help\`.`);
254
- }
255
- }
256
- main(process.argv.slice(2)).catch((err) => {
257
- if (err instanceof CliError) {
258
- log.warn(err.message);
259
- process.exit(err.exitCode);
260
- }
261
- console.error(err);
262
- process.exit(1);
263
- });
2
+ import { runCli } from "./cli.js";
3
+ await runCli(process.argv.slice(2));
package/dist/util.d.ts CHANGED
@@ -1,7 +1,16 @@
1
1
  export declare class CliError extends Error {
2
2
  readonly exitCode: number;
3
- constructor(message: string, exitCode?: number);
3
+ /** The API's error code (e.g. "not_found") when the error came from a response; callers branch on this, never on the message. */
4
+ readonly code: string | undefined;
5
+ /** The HTTP status when the error came from a response. */
6
+ readonly status: number | undefined;
7
+ constructor(message: string, exitCode?: number, extra?: {
8
+ code?: string | undefined;
9
+ status?: number | undefined;
10
+ });
4
11
  }
12
+ /** The one sentence every unauthenticated command prints, with both ways in. */
13
+ export declare const NOT_LOGGED_IN = "Not logged in. Run `nerd login --email you@example.com` (one click in the email signs you in and creates your account the first time), or set NERD_TOKEN to an API token for scripts.";
5
14
  export declare const log: {
6
15
  info: (msg: string) => void;
7
16
  step: (msg: string) => void;
package/dist/util.js CHANGED
@@ -3,11 +3,19 @@ import { existsSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  export class CliError extends Error {
5
5
  exitCode;
6
- constructor(message, exitCode = 1) {
6
+ /** The API's error code (e.g. "not_found") when the error came from a response; callers branch on this, never on the message. */
7
+ code;
8
+ /** The HTTP status when the error came from a response. */
9
+ status;
10
+ constructor(message, exitCode = 1, extra = {}) {
7
11
  super(message);
8
12
  this.exitCode = exitCode;
13
+ this.code = extra.code;
14
+ this.status = extra.status;
9
15
  }
10
16
  }
17
+ /** The one sentence every unauthenticated command prints, with both ways in. */
18
+ export const NOT_LOGGED_IN = "Not logged in. Run `nerd login --email you@example.com` (one click in the email signs you in and creates your account the first time), or set NERD_TOKEN to an API token for scripts.";
11
19
  export const log = {
12
20
  info: (msg) => console.error(`${msg}`),
13
21
  step: (msg) => console.error(`\x1b[36m›\x1b[0m ${msg}`),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nerdsystem",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "nerd: deploy apps to nerdsystem from the terminal or a coding agent.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,11 +28,11 @@ Throughout, show commands rather than describing them, and never ask the person
28
28
  4. `nerd deploy` when it is ready. It runs the checks, builds, applies pending migrations, uploads, and prints the URL.
29
29
  5. If something is wrong after deploying: `nerd logs` shows recent output from the deployed app (`--q` to search, `--pr 12` for a preview), `nerd deployments` shows status and errors, `nerd db query "..."` inspects production data.
30
30
 
31
- Run `nerd check --json` when you want a machine-readable list of problems.
31
+ Run `nerd check --json` when you want a machine-readable list of problems. Its summary says how many gates ran and which were skipped (`skipped` in the JSON): semgrep and gitleaks only run locally when installed; git builds always run them in the builder.
32
32
 
33
33
  ## Deploying from GitHub
34
34
 
35
- Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically, and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
35
+ Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically (for accounts younger than seven days, counted from the nerdsystem account's creation, git builds are deferred: deploy with `nerd deploy` from the machine until then), and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
36
36
 
37
37
  ## Where things go
38
38
 
@@ -82,6 +82,7 @@ Then in `src/server/index.ts`: `app.route("/api/notes", notes);`
82
82
  - Schema changes are migrations. Edit `schema.ts`, run `pnpm db:generate`, commit the new file in `migrations/`. Never hand-write SQL into production; `nerd deploy` applies migrations in name order and records which ran.
83
83
  - Migrations are forward-only. To undo, write another migration.
84
84
  - Prefer small, additive migrations. SQLite cannot alter columns in place.
85
+ - `nerd db export` downloads a SQL dump of the production database (`<slug>-<date>.sql`, or `--out file.sql`); use it before a risky migration or when the person wants their data.
85
86
 
86
87
  ## Errors
87
88
 
@@ -121,6 +122,10 @@ Without MCP, `nerd check --json` returns the same shape, and `nerd check --rule
121
122
 
122
123
  When something is wrong on the deployed app: `nerd logs --since 1h` (add `--q "text"` to search, `--pr 12` for a preview) shows errors with the request that caused them. Reproduce locally with `nerd dev` using the same input, fix it, run `nerd verify`, and deploy or open a pull request. If a deploy made things worse, `nerd rollback` puts the previous production bundle back without touching the database. Write a one-line note on every deploy (`nerd deploy --note "fix: todos query filtered by user"`); the dashboard shows these as a changelog people can read.
123
124
 
125
+ ## Deleting a project
126
+
127
+ `nerd delete --yes` takes the app offline at once and moves the project to the trash; its database and files are kept for seven days (the command prints the date), then destroyed. `nerd trash` lists what can still be restored and `nerd trash restore <slug>` brings one back (the app stays offline until the next `nerd deploy` or a rollback). Never run `nerd delete` unless the person asked for it in so many words.
128
+
124
129
  ## Not available yet
125
130
 
126
131
  Queues, Durable Objects, and log streaming. If the task needs one, say so instead of working around it with an unsupported binding.
@@ -2,7 +2,7 @@
2
2
  description: How to build, run, and deploy this app on nerdsystem. Applies to server, database, auth, and deploy work.
3
3
  alwaysApply: true
4
4
  ---
5
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (b1d847104ce0); edit the skill, then run: nerd agents sync -->
5
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (088a9335c558); edit the skill, then run: nerd agents sync -->
6
6
 
7
7
  # Building on nerdsystem
8
8
 
@@ -29,11 +29,11 @@ Throughout, show commands rather than describing them, and never ask the person
29
29
  4. `nerd deploy` when it is ready. It runs the checks, builds, applies pending migrations, uploads, and prints the URL.
30
30
  5. If something is wrong after deploying: `nerd logs` shows recent output from the deployed app (`--q` to search, `--pr 12` for a preview), `nerd deployments` shows status and errors, `nerd db query "..."` inspects production data.
31
31
 
32
- Run `nerd check --json` when you want a machine-readable list of problems.
32
+ Run `nerd check --json` when you want a machine-readable list of problems. Its summary says how many gates ran and which were skipped (`skipped` in the JSON): semgrep and gitleaks only run locally when installed; git builds always run them in the builder.
33
33
 
34
34
  ## Deploying from GitHub
35
35
 
36
- Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically, and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
36
+ Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically (for accounts younger than seven days, counted from the nerdsystem account's creation, git builds are deferred: deploy with `nerd deploy` from the machine until then), and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
37
37
 
38
38
  ## Where things go
39
39
 
@@ -83,6 +83,7 @@ Then in `src/server/index.ts`: `app.route("/api/notes", notes);`
83
83
  - Schema changes are migrations. Edit `schema.ts`, run `pnpm db:generate`, commit the new file in `migrations/`. Never hand-write SQL into production; `nerd deploy` applies migrations in name order and records which ran.
84
84
  - Migrations are forward-only. To undo, write another migration.
85
85
  - Prefer small, additive migrations. SQLite cannot alter columns in place.
86
+ - `nerd db export` downloads a SQL dump of the production database (`<slug>-<date>.sql`, or `--out file.sql`); use it before a risky migration or when the person wants their data.
86
87
 
87
88
  ## Errors
88
89
 
@@ -122,6 +123,10 @@ Without MCP, `nerd check --json` returns the same shape, and `nerd check --rule
122
123
 
123
124
  When something is wrong on the deployed app: `nerd logs --since 1h` (add `--q "text"` to search, `--pr 12` for a preview) shows errors with the request that caused them. Reproduce locally with `nerd dev` using the same input, fix it, run `nerd verify`, and deploy or open a pull request. If a deploy made things worse, `nerd rollback` puts the previous production bundle back without touching the database. Write a one-line note on every deploy (`nerd deploy --note "fix: todos query filtered by user"`); the dashboard shows these as a changelog people can read.
124
125
 
126
+ ## Deleting a project
127
+
128
+ `nerd delete --yes` takes the app offline at once and moves the project to the trash; its database and files are kept for seven days (the command prints the date), then destroyed. `nerd trash` lists what can still be restored and `nerd trash restore <slug>` brings one back (the app stays offline until the next `nerd deploy` or a rollback). Never run `nerd delete` unless the person asked for it in so many words.
129
+
125
130
  ## Not available yet
126
131
 
127
132
  Queues, Durable Objects, and log streaming. If the task needs one, say so instead of working around it with an unsupported binding.
@@ -1,4 +1,4 @@
1
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (b1d847104ce0); edit the skill, then run: nerd agents sync -->
1
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (088a9335c558); edit the skill, then run: nerd agents sync -->
2
2
 
3
3
  # Building on nerdsystem
4
4
 
@@ -25,11 +25,11 @@ Throughout, show commands rather than describing them, and never ask the person
25
25
  4. `nerd deploy` when it is ready. It runs the checks, builds, applies pending migrations, uploads, and prints the URL.
26
26
  5. If something is wrong after deploying: `nerd logs` shows recent output from the deployed app (`--q` to search, `--pr 12` for a preview), `nerd deployments` shows status and errors, `nerd db query "..."` inspects production data.
27
27
 
28
- Run `nerd check --json` when you want a machine-readable list of problems.
28
+ Run `nerd check --json` when you want a machine-readable list of problems. Its summary says how many gates ran and which were skipped (`skipped` in the JSON): semgrep and gitleaks only run locally when installed; git builds always run them in the builder.
29
29
 
30
30
  ## Deploying from GitHub
31
31
 
32
- Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically, and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
32
+ Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically (for accounts younger than seven days, counted from the nerdsystem account's creation, git builds are deferred: deploy with `nerd deploy` from the machine until then), and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
33
33
 
34
34
  ## Where things go
35
35
 
@@ -79,6 +79,7 @@ Then in `src/server/index.ts`: `app.route("/api/notes", notes);`
79
79
  - Schema changes are migrations. Edit `schema.ts`, run `pnpm db:generate`, commit the new file in `migrations/`. Never hand-write SQL into production; `nerd deploy` applies migrations in name order and records which ran.
80
80
  - Migrations are forward-only. To undo, write another migration.
81
81
  - Prefer small, additive migrations. SQLite cannot alter columns in place.
82
+ - `nerd db export` downloads a SQL dump of the production database (`<slug>-<date>.sql`, or `--out file.sql`); use it before a risky migration or when the person wants their data.
82
83
 
83
84
  ## Errors
84
85
 
@@ -118,6 +119,10 @@ Without MCP, `nerd check --json` returns the same shape, and `nerd check --rule
118
119
 
119
120
  When something is wrong on the deployed app: `nerd logs --since 1h` (add `--q "text"` to search, `--pr 12` for a preview) shows errors with the request that caused them. Reproduce locally with `nerd dev` using the same input, fix it, run `nerd verify`, and deploy or open a pull request. If a deploy made things worse, `nerd rollback` puts the previous production bundle back without touching the database. Write a one-line note on every deploy (`nerd deploy --note "fix: todos query filtered by user"`); the dashboard shows these as a changelog people can read.
120
121
 
122
+ ## Deleting a project
123
+
124
+ `nerd delete --yes` takes the app offline at once and moves the project to the trash; its database and files are kept for seven days (the command prints the date), then destroyed. `nerd trash` lists what can still be restored and `nerd trash restore <slug>` brings one back (the app stays offline until the next `nerd deploy` or a rollback). Never run `nerd delete` unless the person asked for it in so many words.
125
+
121
126
  ## Not available yet
122
127
 
123
128
  Queues, Durable Objects, and log streaming. If the task needs one, say so instead of working around it with an unsupported binding.
@@ -1,4 +1,4 @@
1
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (b1d847104ce0); edit the skill, then run: nerd agents sync -->
1
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (088a9335c558); edit the skill, then run: nerd agents sync -->
2
2
 
3
3
  # Building on nerdsystem
4
4
 
@@ -25,11 +25,11 @@ Throughout, show commands rather than describing them, and never ask the person
25
25
  4. `nerd deploy` when it is ready. It runs the checks, builds, applies pending migrations, uploads, and prints the URL.
26
26
  5. If something is wrong after deploying: `nerd logs` shows recent output from the deployed app (`--q` to search, `--pr 12` for a preview), `nerd deployments` shows status and errors, `nerd db query "..."` inspects production data.
27
27
 
28
- Run `nerd check --json` when you want a machine-readable list of problems.
28
+ Run `nerd check --json` when you want a machine-readable list of problems. Its summary says how many gates ran and which were skipped (`skipped` in the JSON): semgrep and gitleaks only run locally when installed; git builds always run them in the builder.
29
29
 
30
30
  ## Deploying from GitHub
31
31
 
32
- Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically, and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
32
+ Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically (for accounts younger than seven days, counted from the nerdsystem account's creation, git builds are deferred: deploy with `nerd deploy` from the machine until then), and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
33
33
 
34
34
  ## Where things go
35
35
 
@@ -79,6 +79,7 @@ Then in `src/server/index.ts`: `app.route("/api/notes", notes);`
79
79
  - Schema changes are migrations. Edit `schema.ts`, run `pnpm db:generate`, commit the new file in `migrations/`. Never hand-write SQL into production; `nerd deploy` applies migrations in name order and records which ran.
80
80
  - Migrations are forward-only. To undo, write another migration.
81
81
  - Prefer small, additive migrations. SQLite cannot alter columns in place.
82
+ - `nerd db export` downloads a SQL dump of the production database (`<slug>-<date>.sql`, or `--out file.sql`); use it before a risky migration or when the person wants their data.
82
83
 
83
84
  ## Errors
84
85
 
@@ -118,6 +119,10 @@ Without MCP, `nerd check --json` returns the same shape, and `nerd check --rule
118
119
 
119
120
  When something is wrong on the deployed app: `nerd logs --since 1h` (add `--q "text"` to search, `--pr 12` for a preview) shows errors with the request that caused them. Reproduce locally with `nerd dev` using the same input, fix it, run `nerd verify`, and deploy or open a pull request. If a deploy made things worse, `nerd rollback` puts the previous production bundle back without touching the database. Write a one-line note on every deploy (`nerd deploy --note "fix: todos query filtered by user"`); the dashboard shows these as a changelog people can read.
120
121
 
122
+ ## Deleting a project
123
+
124
+ `nerd delete --yes` takes the app offline at once and moves the project to the trash; its database and files are kept for seven days (the command prints the date), then destroyed. `nerd trash` lists what can still be restored and `nerd trash restore <slug>` brings one back (the app stays offline until the next `nerd deploy` or a rollback). Never run `nerd delete` unless the person asked for it in so many words.
125
+
121
126
  ## Not available yet
122
127
 
123
128
  Queues, Durable Objects, and log streaming. If the task needs one, say so instead of working around it with an unsupported binding.
@@ -1,4 +1,4 @@
1
- <!-- generated from .claude/skills/nerdsystem/SKILL.md (b1d847104ce0); edit the skill, then run: nerd agents sync -->
1
+ <!-- generated from .claude/skills/nerdsystem/SKILL.md (088a9335c558); edit the skill, then run: nerd agents sync -->
2
2
 
3
3
  # Building on nerdsystem
4
4
 
@@ -25,11 +25,11 @@ Throughout, show commands rather than describing them, and never ask the person
25
25
  4. `nerd deploy` when it is ready. It runs the checks, builds, applies pending migrations, uploads, and prints the URL.
26
26
  5. If something is wrong after deploying: `nerd logs` shows recent output from the deployed app (`--q` to search, `--pr 12` for a preview), `nerd deployments` shows status and errors, `nerd db query "..."` inspects production data.
27
27
 
28
- Run `nerd check --json` when you want a machine-readable list of problems.
28
+ Run `nerd check --json` when you want a machine-readable list of problems. Its summary says how many gates ran and which were skipped (`skipped` in the JSON): semgrep and gitleaks only run locally when installed; git builds always run them in the builder.
29
29
 
30
30
  ## Deploying from GitHub
31
31
 
32
- Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically, and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
32
+ Once the repo is linked (`nerd github connect`, then `nerd github link owner/repo`), every push to the production branch builds and deploys automatically (for accounts younger than seven days, counted from the nerdsystem account's creation, git builds are deferred: deploy with `nerd deploy` from the machine until then), and every pull request gets a preview at its own URL, posted as a PR comment. `nerd builds` lists builds; `nerd builds show <id>` prints the log when one fails. A failing build reports the same `nerd check` problems you would see locally, so fix and push again. Every preview gets its own database and bucket, and pending migrations are applied to it on each preview build, so a PR that changes the schema can be tried end to end before it merges.
33
33
 
34
34
  ## Where things go
35
35
 
@@ -79,6 +79,7 @@ Then in `src/server/index.ts`: `app.route("/api/notes", notes);`
79
79
  - Schema changes are migrations. Edit `schema.ts`, run `pnpm db:generate`, commit the new file in `migrations/`. Never hand-write SQL into production; `nerd deploy` applies migrations in name order and records which ran.
80
80
  - Migrations are forward-only. To undo, write another migration.
81
81
  - Prefer small, additive migrations. SQLite cannot alter columns in place.
82
+ - `nerd db export` downloads a SQL dump of the production database (`<slug>-<date>.sql`, or `--out file.sql`); use it before a risky migration or when the person wants their data.
82
83
 
83
84
  ## Errors
84
85
 
@@ -118,6 +119,10 @@ Without MCP, `nerd check --json` returns the same shape, and `nerd check --rule
118
119
 
119
120
  When something is wrong on the deployed app: `nerd logs --since 1h` (add `--q "text"` to search, `--pr 12` for a preview) shows errors with the request that caused them. Reproduce locally with `nerd dev` using the same input, fix it, run `nerd verify`, and deploy or open a pull request. If a deploy made things worse, `nerd rollback` puts the previous production bundle back without touching the database. Write a one-line note on every deploy (`nerd deploy --note "fix: todos query filtered by user"`); the dashboard shows these as a changelog people can read.
120
121
 
122
+ ## Deleting a project
123
+
124
+ `nerd delete --yes` takes the app offline at once and moves the project to the trash; its database and files are kept for seven days (the command prints the date), then destroyed. `nerd trash` lists what can still be restored and `nerd trash restore <slug>` brings one back (the app stays offline until the next `nerd deploy` or a rollback). Never run `nerd delete` unless the person asked for it in so many words.
125
+
121
126
  ## Not available yet
122
127
 
123
128
  Queues, Durable Objects, and log streaming. If the task needs one, say so instead of working around it with an unsupported binding.
@@ -19,6 +19,12 @@
19
19
  "react": "^19.3.1",
20
20
  "react-dom": "^19.3.1"
21
21
  },
22
+ "pnpm": {
23
+ "onlyBuiltDependencies": [
24
+ "esbuild",
25
+ "workerd"
26
+ ]
27
+ },
22
28
  "devDependencies": {
23
29
  "@cloudflare/vite-plugin": "^1.67.0",
24
30
  "@cloudflare/workers-types": "^5.20261102.1",