deployai 0.1.0-beta.6 → 0.1.0-beta.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +102 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -38,7 +38,7 @@ Node 20 or newer. No other setup: the CLI talks to https://deployai.co.il.
38
38
 
39
39
  | Command | What it does |
40
40
  |---------|--------------|
41
- | `deployai init` | Creates `DEPLOYAI.md` (rules for the AI agent) and `.deployai/project.json`. Never edits your code and does not link a project (use `link`). `--force` overwrites `DEPLOYAI.md`. |
41
+ | `deployai init` | Creates `DEPLOYAI.md` (rules for the AI agent: the stack to build with, what to avoid, how to keep existing data), adds one line pointing to it in `AGENTS.md` and `CLAUDE.md`, and `.deployai/project.json`. Run it first in a new project, even an empty folder. Never edits your code and does not link a project (use `link`). `--force` overwrites `DEPLOYAI.md`, `--no-agent-files` leaves `AGENTS.md` and `CLAUDE.md` alone. |
42
42
  | `deployai inspect` | Shows framework, package manager, language, database, storage and the number of env files (values are never read). `--json` for machine output. |
43
43
  | `deployai check` | Lists blockers and warnings with file and line. It answers only whether the project can run on DeployAI. More below. |
44
44
  | `deployai login` | Logs in through the browser (device code). The token lasts 30 days and is stored in `~/.deployai/config.json` with the API address that issued it; it is never sent to another address. |
package/dist/index.js CHANGED
@@ -21365,7 +21365,7 @@ var CLI_MAP_NODES = [
21365
21365
  n("cmd-start", "cli", "start <id>", "\u05DE\u05DB\u05D9\u05DF \u05D0\u05EA \u05D4\u05EA\u05D9\u05E7\u05D9\u05D9\u05D4 \u05DC\u05E4\u05D9 \u05DB\u05DC \u05D4\u05D1\u05D7\u05D9\u05E8\u05D5\u05EA: \u05EA\u05D9\u05E7\u05D9\u05D9\u05D4, \u05D3\u05D5\u05D2\u05DE\u05D4 \u05D5\u05D4\u05EA\u05E7\u05E0\u05D4, \u05E7\u05D5\u05D1\u05E5 \u05D4\u05E4\u05E8\u05D8\u05D9\u05DD \u05D5\u05D7\u05D9\u05D1\u05D5\u05E8 \u05DC\u05D0\u05EA\u05E8. \u05DE\u05D3\u05E4\u05D9\u05E1 \u05DC\u05E1\u05D5\u05DB\u05DF \u05D0\u05EA \u05D4\u05D8\u05E7\u05E1\u05D8 \u05D5\u05D0\u05EA \u05D4\u05E4\u05E7\u05D5\u05D3\u05D5\u05EA.", "Prepares the folder with every choice: folder, sample and install, the details file and the site link. Prints the text and the commands for the agent."),
21366
21366
  n("cmd-samples", "cli", "samples [key]", "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05D3\u05D5\u05D2\u05DE\u05D0\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E8\u05D3\u05D4 \u05E9\u05DC \u05D0\u05D7\u05EA.", "Lists the samples, or downloads one."),
21367
21367
  n("cmd-check", "cli", "check", "\u05D4\u05D0\u05DD \u05D4\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D9\u05DB\u05D5\u05DC \u05DC\u05E8\u05D5\u05E5 \u05D0\u05E6\u05DC\u05E0\u05D5: \u05D7\u05D5\u05E1\u05DE\u05D9\u05DD \u05D5\u05D0\u05D6\u05D4\u05E8\u05D5\u05EA, \u05E2\u05DD \u05E4\u05E8\u05D5\u05DE\u05E4\u05D8 \u05EA\u05D9\u05E7\u05D5\u05DF.", "Can the project run on our hosting: blockers and warnings, with a fix prompt."),
21368
- n("cmd-init", "cli", "init", "\u05D9\u05D5\u05E6\u05E8 DEPLOYAI.md \u05D5 .deployai/project.json.", "Creates DEPLOYAI.md and .deployai/project.json."),
21368
+ n("cmd-init", "cli", "init", "\u05D9\u05D5\u05E6\u05E8 DEPLOYAI.md \u05E2\u05DD \u05D4\u05DB\u05DC\u05DC\u05D9\u05DD \u05DC\u05E1\u05D5\u05DB\u05DF, \u05E9\u05D5\u05E8\u05D4 \u05D0\u05DC\u05D9\u05D5 \u05D1 AGENTS.md \u05D5 CLAUDE.md, \u05D5 .deployai/project.json. \u05E8\u05D0\u05E9\u05D5\u05DF \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D7\u05D3\u05E9.", "Creates DEPLOYAI.md with the agent rules, a line to it in AGENTS.md and CLAUDE.md, and .deployai/project.json. First in a new project."),
21369
21369
  n("cmd-inspect", "cli", "inspect", "\u05DE\u05D4 \u05D6\u05D5\u05D4\u05D4 \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8: \u05DE\u05E1\u05D2\u05E8\u05EA, \u05E9\u05E4\u05D4, \u05DE\u05E1\u05D3 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD.", "What the project is: framework, language, database."),
21370
21370
  n("cmd-login", "cli", "login", "\u05DB\u05E0\u05D9\u05E1\u05D4 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF, \u05D1\u05E2\u05DC \u05D4\u05D0\u05EA\u05E8 \u05DE\u05D0\u05E9\u05E8.", "Login in the browser, the owner approves."),
21371
21371
  n("cmd-logout", "cli", "logout", "\u05DE\u05D1\u05D8\u05DC \u05D0\u05EA \u05D4\u05D8\u05D5\u05E7\u05DF \u05D5\u05D9\u05D5\u05E6\u05D0 \u05DE\u05D4\u05D7\u05E9\u05D1\u05D5\u05DF \u05D1\u05DE\u05D7\u05E9\u05D1 \u05D4\u05D6\u05D4.", "Cancels the token and logs out on this computer."),
@@ -21643,6 +21643,26 @@ var SPACES = {
21643
21643
  test: build("test", { ...CLOUDFLARE_SPACES.prod, kvNamespaceId: "", sitesZoneId: null, backupBucket: null, toolsWorkerUrl: "" }, { ...SPACE_ADDRESSES.prod, appUrl: "http://localhost:3000", siteUrl: "http://localhost:3000", trustedOrigins: [], storage: "local" })
21644
21644
  };
21645
21645
 
21646
+ // ../shared/src/agent-rules.ts
21647
+ var BUILD_WITH = [
21648
+ `Frameworks: ${SUPPORTED_FRAMEWORKS.map((f) => f.name).join(", ")}. In beta: ${BETA_FRAMEWORKS.map((f) => f.name).join(", ")} (Next.js through the OpenNext Cloudflare adapter).`,
21649
+ "Database: Cloudflare D1 (SQLite), through Drizzle with drizzle-orm/d1 or Prisma with the D1 adapter.",
21650
+ "Uploaded files and images: Cloudflare R2 (object storage), never the local disk.",
21651
+ "Settings and secrets: environment variables, set with: npx deployai@latest env set <key>",
21652
+ "Images: resize at build time or serve them as they are; no native image modules at runtime.",
21653
+ "Passwords: bcryptjs or Web Crypto, never native bcrypt.",
21654
+ "Server code runs per request: no long-running processes, background servers or child processes."
21655
+ ];
21656
+ var KEEP_DATA_RULES = [
21657
+ "Moving to DeployAI changes where data lives. It never moves the data by itself. Before you switch any of these, save a copy inside the project and tell the user, in simple words, what was saved and where:",
21658
+ "- Database (Postgres, MySQL, MongoDB, a SQLite file): export it to a file (pg_dump, mysqldump, mongoexport, sqlite3 .dump), so it can be imported into D1 later.",
21659
+ "- Uploaded files and images on the local disk or another storage service: keep them in a folder (download them first if they are on another service), so they can be uploaded to R2 later.",
21660
+ "- User accounts and passwords: keep existing password hashes working (bcryptjs reads bcrypt hashes), so no one has to reset.",
21661
+ "- Sessions and cache (Redis, memory): these can be lost, and users may have to log in again. Say so.",
21662
+ "Never delete the old database, files or storage service."
21663
+ ];
21664
+ var AGENT_POINTER = "Read DEPLOYAI.md before you write code, change the plan or add a dependency: this project is published with DeployAI.";
21665
+
21646
21666
  // src/config.ts
21647
21667
  import { randomUUID } from "crypto";
21648
21668
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -21790,6 +21810,7 @@ var M = {
21790
21810
  startInstalled: "Installed its packages (npm install).",
21791
21811
  startBrief: "Wrote the owner's details to {file} (kept out of git and never uploaded).",
21792
21812
  startLinked: 'Linked this folder to the site "{name}".',
21813
+ startRules: "Wrote the rules for your agent to DEPLOYAI.md (never uploaded).",
21793
21814
  startRelinked: 'Linked this folder to the site "{name}" instead of the site it was linked to.',
21794
21815
  statusLine: "Status: {s}",
21795
21816
  ready: "ready",
@@ -21803,6 +21824,7 @@ var M = {
21803
21824
  pasteFix: " Paste the prompt below into your AI editor, then run: npx deployai@latest check",
21804
21825
  copied: " (copied to clipboard)",
21805
21826
  runDeploy: ' Run: npx deployai@latest deploy -m "<message>"',
21827
+ initHint: " So your agent follows the DeployAI rules, run: npx deployai@latest init",
21806
21828
  deployTitle: "DeployAI deploy",
21807
21829
  guestTitle: "DeployAI deploy (no account)",
21808
21830
  uploading: "Uploading...",
@@ -21959,6 +21981,7 @@ var M = {
21959
21981
  startInstalled: "\u05D4\u05D7\u05D1\u05D9\u05DC\u05D5\u05EA \u05E9\u05DC\u05D4 \u05D4\u05D5\u05EA\u05E7\u05E0\u05D5 (npm install).",
21960
21982
  startBrief: "\u05D4\u05E4\u05E8\u05D8\u05D9\u05DD \u05E9\u05DC \u05D1\u05E2\u05DC \u05D4\u05D0\u05EA\u05E8 \u05E0\u05DB\u05EA\u05D1\u05D5 \u05DC {file} (\u05DC\u05D0 \u05E0\u05DB\u05E0\u05E1\u05D9\u05DD \u05DC\u05BEgit \u05D5\u05DC\u05D0 \u05E2\u05D5\u05DC\u05D9\u05DD \u05DC\u05D0\u05EA\u05E8).",
21961
21983
  startLinked: '\u05D4\u05EA\u05D9\u05E7\u05D9\u05D9\u05D4 \u05D7\u05D5\u05D1\u05E8\u05D4 \u05DC\u05D0\u05EA\u05E8 "{name}".',
21984
+ startRules: "\u05D4\u05DB\u05DC\u05DC\u05D9\u05DD \u05DC\u05E1\u05D5\u05DB\u05DF \u05E0\u05DB\u05EA\u05D1\u05D5 \u05DC DEPLOYAI.md (\u05DC\u05D0 \u05E2\u05D5\u05DC\u05D9\u05DD \u05DC\u05D0\u05EA\u05E8).",
21962
21985
  startRelinked: '\u05D4\u05EA\u05D9\u05E7\u05D9\u05D9\u05D4 \u05D7\u05D5\u05D1\u05E8\u05D4 \u05DC\u05D0\u05EA\u05E8 "{name}" \u05D1\u05DE\u05E7\u05D5\u05DD \u05D4\u05D0\u05EA\u05E8 \u05E9\u05D4\u05D9\u05D9\u05EA\u05D4 \u05DE\u05D7\u05D5\u05D1\u05E8\u05EA \u05D0\u05DC\u05D9\u05D5.',
21963
21986
  statusLine: "\u05DE\u05E6\u05D1: {s}",
21964
21987
  ready: "\u05DE\u05D5\u05DB\u05DF \u05DC\u05E2\u05DC\u05D5\u05EA",
@@ -21972,6 +21995,7 @@ var M = {
21972
21995
  pasteFix: " \u05D4\u05D3\u05D1\u05D9\u05E7\u05D5 \u05D0\u05EA \u05D4\u05E4\u05E8\u05D5\u05DE\u05E4\u05D8 \u05E9\u05DC\u05DE\u05D8\u05D4 \u05DC\u05E1\u05D5\u05DB\u05DF, \u05D5\u05D0\u05D6 \u05D4\u05E8\u05D9\u05E6\u05D5: npx deployai@latest check",
21973
21996
  copied: " (\u05D4\u05D5\u05E2\u05EA\u05E7)",
21974
21997
  runDeploy: ' \u05D4\u05E8\u05D9\u05E6\u05D5: npx deployai@latest deploy -m "<message>"',
21998
+ initHint: " \u05DB\u05D3\u05D9 \u05E9\u05D4\u05E1\u05D5\u05DB\u05DF \u05D9\u05E2\u05D1\u05D5\u05D3 \u05DC\u05E4\u05D9 \u05D4\u05DB\u05DC\u05DC\u05D9\u05DD \u05E9\u05DC DeployAI, \u05D4\u05E8\u05D9\u05E6\u05D5: npx deployai@latest init",
21975
21999
  deployTitle: "DeployAI deploy",
21976
22000
  guestTitle: "DeployAI deploy (\u05D1\u05DC\u05D9 \u05D7\u05E9\u05D1\u05D5\u05DF)",
21977
22001
  uploading: "\u05DE\u05E2\u05DC\u05D9\u05DD...",
@@ -22132,7 +22156,7 @@ function messages(root) {
22132
22156
  }
22133
22157
 
22134
22158
  // src/version.ts
22135
- var CLI_VERSION = "0.1.0-beta.6";
22159
+ var CLI_VERSION = "0.1.0-beta.7";
22136
22160
 
22137
22161
  // src/api.ts
22138
22162
  function apiContext(apiFlag) {
@@ -22361,7 +22385,7 @@ async function sendTelemetryEvent(ctx, event) {
22361
22385
  }
22362
22386
 
22363
22387
  // src/commands/init.ts
22364
- import { existsSync as existsSync5, writeFileSync as writeFileSync3 } from "fs";
22388
+ import { appendFileSync, existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
22365
22389
  import { join as join5 } from "path";
22366
22390
 
22367
22391
  // src/analyze.ts
@@ -22529,6 +22553,7 @@ function planUpload(root) {
22529
22553
  }
22530
22554
 
22531
22555
  // src/analyze.ts
22556
+ var INIT_FILES = /* @__PURE__ */ new Set(["DEPLOYAI.md", "AGENTS.md", "CLAUDE.md"]);
22532
22557
  var CODE_EXT = /\.(js|jsx|ts|tsx|mjs|cjs|mts|cts|vue|svelte|astro)$/;
22533
22558
  var SECRET_SCAN_EXT = /\.(js|jsx|ts|tsx|mjs|cjs|mts|cts|vue|svelte|astro|json|ya?ml|toml|html|prisma)$/;
22534
22559
  var LOCKFILES = /* @__PURE__ */ new Set(["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb"]);
@@ -22886,7 +22911,7 @@ function analyzeProject(root) {
22886
22911
  }
22887
22912
  const otherStack = detectOtherStack(files.map((f) => f.rel));
22888
22913
  if (otherStack) add({ code: "other_stack", severity: "blocker", detail: ` ${otherStack.name}` });
22889
- const empty = !files.some((f) => !f.rel.startsWith(".deployai/") && f.rel !== "DEPLOYAI.md" && !isEnvFile(f.rel.split("/").pop() ?? ""));
22914
+ const empty = !files.some((f) => !f.rel.startsWith(".deployai/") && !INIT_FILES.has(f.rel) && !isEnvFile(f.rel.split("/").pop() ?? ""));
22890
22915
  if (empty) add({ code: "no_files", severity: "blocker" });
22891
22916
  if (framework.id === "unknown" && !otherStack && !empty) {
22892
22917
  add({ code: "unknown_framework", severity: "warning", detail: framework.flavor ? ` (looks like ${framework.flavor})` : "" });
@@ -22984,13 +23009,28 @@ This project is published with DeployAI.
22984
23009
 
22985
23010
  Always explain to the user in simple words, in the language they write to you in. The user may not read English.
22986
23011
 
22987
- Do not add:
23012
+ Before you write code or change the plan, compare it with these rules. If something in it does not fit, say what and propose the change.
23013
+
23014
+ ## Build with
23015
+
23016
+ ${BUILD_WITH.map((l) => `- ${l}`).join("\n")}
23017
+
23018
+ To start from working code, see the samples: npx deployai@latest samples
23019
+
23020
+ ## Do not add
23021
+
22988
23022
  - local file system writes
22989
23023
  - database drivers DeployAI does not support (see: npx deployai@latest inspect)
22990
23024
  - long-running processes or background servers
22991
23025
  - native binary modules
22992
23026
  - DeployAI or any cloud credentials in source code
22993
23027
 
23028
+ ## Keep existing data
23029
+
23030
+ ${KEEP_DATA_RULES.join("\n")}
23031
+
23032
+ ## Check
23033
+
22994
23034
  Before adding a dependency or a new server feature, run: npx deployai@latest check
22995
23035
  Ask the developer before removing any existing functionality.
22996
23036
 
@@ -22998,9 +23038,11 @@ Files:
22998
23038
  - .deployai/project.json: project id and settings (safe to commit)
22999
23039
  - .deployai/last-check.json: latest check result (not committed)
23000
23040
  `;
23041
+ var AGENT_FILES = ["AGENTS.md", "CLAUDE.md"];
23001
23042
  function runInit(root, opts = {}) {
23002
23043
  const created = [];
23003
23044
  const kept = [];
23045
+ const updated = [];
23004
23046
  const md = join5(root, "DEPLOYAI.md");
23005
23047
  if (existsSync5(md) && !opts.force) {
23006
23048
  kept.push("DEPLOYAI.md");
@@ -23008,20 +23050,35 @@ function runInit(root, opts = {}) {
23008
23050
  writeFileSync3(md, DEPLOYAI_MD);
23009
23051
  created.push("DEPLOYAI.md");
23010
23052
  }
23053
+ if (opts.agentFiles !== false) {
23054
+ for (const name of AGENT_FILES) {
23055
+ const file2 = join5(root, name);
23056
+ const text = existsSync5(file2) ? readFileSync5(file2, "utf8") : null;
23057
+ if (text === null) {
23058
+ writeFileSync3(file2, `${AGENT_POINTER}
23059
+ `);
23060
+ created.push(name);
23061
+ } else if (text.includes("DEPLOYAI.md")) {
23062
+ kept.push(name);
23063
+ } else {
23064
+ const eol = text.includes("\r\n") ? "\r\n" : "\n";
23065
+ const gap = !text.trim() ? "" : text.endsWith("\n") ? eol : eol + eol;
23066
+ appendFileSync(file2, `${gap}${AGENT_POINTER}${eol}`);
23067
+ updated.push(name);
23068
+ }
23069
+ }
23070
+ }
23011
23071
  ensureDeployaiDir(root);
23012
23072
  const existing = readProject(root);
23073
+ const framework = existing?.framework ?? analyzeProject(root).inspect.framework.id;
23013
23074
  if (existing) {
23014
23075
  kept.push(".deployai/project.json");
23015
23076
  } else {
23016
- const analysis = analyzeProject(root);
23017
- writeProject(root, {
23018
- projectId: null,
23019
- framework: analysis.inspect.framework.id,
23020
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
23021
- });
23077
+ writeProject(root, { projectId: null, framework, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
23022
23078
  created.push(".deployai/project.json");
23023
23079
  }
23024
- return { created, kept };
23080
+ const hasCode = existsSync5(join5(root, "package.json")) || framework !== "unknown";
23081
+ return { created, kept, updated, hasCode };
23025
23082
  }
23026
23083
  function initCommand(root, opts) {
23027
23084
  const res = runInit(root, opts);
@@ -23031,6 +23088,7 @@ function initCommand(root, opts) {
23031
23088
  out(
23032
23089
  rows([
23033
23090
  ...res.created.map((f) => ["Created", f]),
23091
+ ...res.updated.map((f) => ["Added a line", `${f} (read DEPLOYAI.md)`]),
23034
23092
  ...res.kept.map((f) => ["Kept", f]),
23035
23093
  ["Guard", ".deployai/last-check.json (git ignored)"],
23036
23094
  ["Linked project", project?.projectId ?? "none yet"]
@@ -23038,12 +23096,18 @@ function initCommand(root, opts) {
23038
23096
  );
23039
23097
  out();
23040
23098
  out("Next step");
23041
- out(" Run: npx deployai@latest check");
23099
+ if (res.hasCode) {
23100
+ out(" Run: npx deployai@latest check");
23101
+ } else {
23102
+ out(" Start from a sample: npx deployai@latest samples");
23103
+ out(" Or tell your agent what to build, or to review your plan. It follows DEPLOYAI.md.");
23104
+ }
23042
23105
  if (!project?.projectId) out(" Then: npx deployai@latest login, npx deployai@latest link");
23043
23106
  }
23044
23107
 
23045
23108
  // src/commands/check.ts
23046
- import { writeFileSync as writeFileSync4 } from "fs";
23109
+ import { existsSync as existsSync6, writeFileSync as writeFileSync4 } from "fs";
23110
+ import { join as join6 } from "path";
23047
23111
 
23048
23112
  // src/prompt.ts
23049
23113
  var PROMPT_RULES = [
@@ -23053,8 +23117,10 @@ var PROMPT_RULES = [
23053
23117
  "Keep the project runnable outside DeployAI.",
23054
23118
  "Never add credentials to source code.",
23055
23119
  "Explain every step to the user in simple words, in the language they write to you in.",
23056
- "For the database, use D1 as shown in the DeployAI CRUD sample."
23120
+ "For the database, use D1 as shown in the DeployAI CRUD sample.",
23121
+ "Follow DEPLOYAI.md for every future change. If it is missing, run: npx deployai@latest init"
23057
23122
  ];
23123
+ var DATA_CODES = /* @__PURE__ */ new Set(["fs_write", "unsupported_db_postgres", "unsupported_db_mysql", "unsupported_db_mongodb", "unsupported_db_sqlite_file", "native_module_bcrypt"]);
23058
23124
  var MAX_LOCATIONS = 3;
23059
23125
  function locList(items) {
23060
23126
  const locs = [...new Set(items.map(locationOf).filter(Boolean))];
@@ -23093,6 +23159,11 @@ function buildPrompt(analysis) {
23093
23159
  if (def) lines.push(`- ${def.fixForAgent}`);
23094
23160
  }
23095
23161
  lines.push("");
23162
+ if (blockerGroups.some((g) => DATA_CODES.has(g.code))) {
23163
+ lines.push("Keep existing data:");
23164
+ lines.push(...KEEP_DATA_RULES);
23165
+ lines.push("");
23166
+ }
23096
23167
  lines.push("Rules:");
23097
23168
  for (const r of PROMPT_RULES) lines.push(`- ${r}`);
23098
23169
  lines.push("");
@@ -23242,6 +23313,7 @@ async function runCheck(root, ctx, opts = {}) {
23242
23313
  } else {
23243
23314
  out(t("runDeploy"));
23244
23315
  }
23316
+ if (!existsSync6(join6(root, "DEPLOYAI.md"))) out(t("initHint"));
23245
23317
  }
23246
23318
  await telemetry;
23247
23319
  return a;
@@ -23455,7 +23527,7 @@ async function linkCommand(root, ctx, target, opts) {
23455
23527
  import { createInterface as createInterface2 } from "readline/promises";
23456
23528
 
23457
23529
  // src/tar.ts
23458
- import { readFileSync as readFileSync5 } from "fs";
23530
+ import { readFileSync as readFileSync6 } from "fs";
23459
23531
  import { gzipSync } from "zlib";
23460
23532
  var BLOCK = 512;
23461
23533
  function writeString(buf, offset, length, value) {
@@ -23539,7 +23611,7 @@ function packFiles(files) {
23539
23611
  return createTarGz(
23540
23612
  files.map((f) => ({
23541
23613
  name: f.rel,
23542
- data: readFileSync5(f.abs),
23614
+ data: readFileSync6(f.abs),
23543
23615
  mtimeMs: f.mtimeMs,
23544
23616
  mode: f.mode & 64 ? 493 : 420
23545
23617
  }))
@@ -23742,8 +23814,8 @@ async function claimCommand(root, ctx, opts) {
23742
23814
 
23743
23815
  // src/commands/samples.ts
23744
23816
  import { createInterface as createInterface3 } from "readline/promises";
23745
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync5 } from "fs";
23746
- import { dirname, join as join6, relative, resolve, sep } from "path";
23817
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync5 } from "fs";
23818
+ import { dirname, join as join7, relative, resolve, sep } from "path";
23747
23819
  import { gunzipSync } from "zlib";
23748
23820
  var SAMPLES = [
23749
23821
  { key: "landing", title: "Landing page: a full one-page site with WhatsApp sign-up", stack: "static HTML and CSS" },
@@ -23754,7 +23826,7 @@ var SAMPLES = [
23754
23826
  { key: "admin", title: "Back office with login: dashboard, orders, stock, customers", stack: "Astro on Workers, D1" }
23755
23827
  ];
23756
23828
  var MAX_BYTES = 20 * 1024 * 1024;
23757
- var IGNORED = /* @__PURE__ */ new Set([".git", ".DS_Store", "Thumbs.db", ".deployai"]);
23829
+ var IGNORED = /* @__PURE__ */ new Set([".git", ".DS_Store", "Thumbs.db", ".deployai", "DEPLOYAI.md", "AGENTS.md", "CLAUDE.md"]);
23758
23830
  function listSamples(apiUrl) {
23759
23831
  out("DeployAI samples");
23760
23832
  out("");
@@ -23764,7 +23836,7 @@ function listSamples(apiUrl) {
23764
23836
  out(`See them live: ${apiUrl}/samples`);
23765
23837
  }
23766
23838
  function filesIn(dir) {
23767
- return existsSync6(dir) ? readdirSync3(dir).filter((f) => !IGNORED.has(f)) : [];
23839
+ return existsSync7(dir) ? readdirSync3(dir).filter((f) => !IGNORED.has(f)) : [];
23768
23840
  }
23769
23841
  function freeFolder(cwd, key) {
23770
23842
  for (let n2 = 1; ; n2++) {
@@ -23847,7 +23919,7 @@ async function samplesCommand(cwd, ctx, key, opts = {}) {
23847
23919
  }
23848
23920
  const written = await downloadSample(ctx, sample.key, root);
23849
23921
  const base = resolve(root);
23850
- const hasPackage = existsSync6(join6(base, "package.json"));
23922
+ const hasPackage = existsSync7(join7(base, "package.json"));
23851
23923
  out(base === resolve(cwd) ? `Downloaded the ${sample.key} sample: ${written} files.` : `Downloaded the ${sample.key} sample into the new folder ${relative(cwd, base)}: ${written} files. Work in that folder from now on.`);
23852
23924
  out("");
23853
23925
  const t = messages(base);
@@ -23992,8 +24064,8 @@ async function statusCommand(root, ctx) {
23992
24064
 
23993
24065
  // src/commands/start.ts
23994
24066
  import { spawnSync as spawnSync2 } from "child_process";
23995
- import { existsSync as existsSync7, writeFileSync as writeFileSync6 } from "fs";
23996
- import { join as join7, relative as relative2, resolve as resolve2 } from "path";
24067
+ import { existsSync as existsSync8, writeFileSync as writeFileSync6 } from "fs";
24068
+ import { join as join8, relative as relative2, resolve as resolve2 } from "path";
23997
24069
  var REASONS = { start_not_found: "startNotFound", start_expired: "startExpired", start_used_up: "startUsedUp" };
23998
24070
  var reason = (code) => messages(process.cwd())(REASONS[code] ?? "startNotFound");
23999
24071
  async function fetchStart(ctx, id) {
@@ -24031,19 +24103,20 @@ async function startCommand(cwd, ctx, id, opts = {}) {
24031
24103
  if (sample && !sameSite) {
24032
24104
  const written = await downloadSample(ctx, sample.key, root);
24033
24105
  done.push(t("startDownloaded", { key: sample.key, n: written }));
24034
- if (existsSync7(join7(root, "package.json"))) {
24106
+ if (existsSync8(join8(root, "package.json"))) {
24035
24107
  if (opts.install !== false && install(root)) done.push(t("startInstalled"));
24036
24108
  else steps.unshift({ cmd: "npm install", say: "Installs the sample's packages." });
24037
24109
  }
24038
24110
  }
24039
24111
  if (choices.brief) {
24040
24112
  ensureDeployaiDir(root);
24041
- writeFileSync6(join7(root, BRIEF_FILE), `# The owner's details
24113
+ writeFileSync6(join8(root, BRIEF_FILE), `# The owner's details
24042
24114
 
24043
24115
  ${choices.brief}
24044
24116
  `);
24045
24117
  done.push(t("startBrief", { file: BRIEF_FILE }));
24046
24118
  }
24119
+ if (runInit(root).created.includes("DEPLOYAI.md")) done.push(t("startRules"));
24047
24120
  if (choices.projectId) {
24048
24121
  const before = readProject(root);
24049
24122
  writeProject(root, { ...before ?? {}, projectId: choices.projectId, name: choices.name ?? void 0, slug: choices.slug ?? void 0, createdAt: before?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString() });
@@ -24069,7 +24142,7 @@ ${choices.brief}
24069
24142
  }
24070
24143
 
24071
24144
  // src/commands/addon.ts
24072
- import { readFileSync as readFileSync6 } from "fs";
24145
+ import { readFileSync as readFileSync7 } from "fs";
24073
24146
  import { resolve as resolve3 } from "path";
24074
24147
  function linkedProjectId2(root) {
24075
24148
  const id = readProject(root)?.projectId;
@@ -24150,7 +24223,7 @@ async function addonDoneCommand(root, ctx, runId, opts) {
24150
24223
  let report;
24151
24224
  if (opts.report) {
24152
24225
  try {
24153
- report = JSON.parse(readFileSync6(resolve3(root, opts.report), "utf8"));
24226
+ report = JSON.parse(readFileSync7(resolve3(root, opts.report), "utf8"));
24154
24227
  } catch {
24155
24228
  throw new CliError(`Cannot read the report file ${opts.report} as JSON.`, 1, "usage");
24156
24229
  }
@@ -24246,7 +24319,7 @@ function buildProgram() {
24246
24319
  const g = (cmd) => cmd.optsWithGlobals();
24247
24320
  const root = (cmd) => resolve4(g(cmd).dir ?? process.cwd());
24248
24321
  const ctx = (cmd) => apiContext(g(cmd).api);
24249
- program.command("init").description("create DEPLOYAI.md and .deployai/ guard files").option("--force", "overwrite DEPLOYAI.md").action((opts, cmd) => initCommand(root(cmd), opts));
24322
+ program.command("init").description("create DEPLOYAI.md and .deployai/ guard files").option("--force", "overwrite DEPLOYAI.md").option("--no-agent-files", "do not add the DEPLOYAI.md line to AGENTS.md and CLAUDE.md").action((opts, cmd) => initCommand(root(cmd), opts));
24250
24323
  program.command("inspect").description("show framework, package manager, language, database, storage").option("--json", "machine readable output").action((opts, cmd) => inspectCommand(root(cmd), opts));
24251
24324
  program.command("check").description("can this project run on DeployAI: blockers and warnings, with the AI prompt").option("--json", "machine readable output").option("--no-clipboard", "do not copy the prompt to the clipboard").action(async (opts, cmd) => {
24252
24325
  const a = await runCheck(root(cmd), ctx(cmd), opts);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deployai",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.7",
4
4
  "description": "Check a site built with an AI editor, see what has to change, and publish it to DeployAI. Hebrew first.",
5
5
  "keywords": [
6
6
  "deployai",