@donotdev/cli 0.0.12 → 0.0.14

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 (85) hide show
  1. package/dependencies-matrix.json +32 -118
  2. package/dist/bin/commands/agent-setup.d.ts +6 -0
  3. package/dist/bin/commands/agent-setup.d.ts.map +1 -0
  4. package/dist/bin/commands/agent-setup.js +623 -0
  5. package/dist/bin/commands/agent-setup.js.map +1 -0
  6. package/dist/bin/commands/build.js +13 -12
  7. package/dist/bin/commands/bump.js +103 -35
  8. package/dist/bin/commands/cacheout.js +13 -12
  9. package/dist/bin/commands/create-app.js +53 -151
  10. package/dist/bin/commands/create-project.js +109 -167
  11. package/dist/bin/commands/deploy.js +7620 -30
  12. package/dist/bin/commands/dev.js +13 -12
  13. package/dist/bin/commands/emu.js +13 -12
  14. package/dist/bin/commands/firebase-setup.d.ts +6 -0
  15. package/dist/bin/commands/firebase-setup.d.ts.map +1 -0
  16. package/dist/bin/commands/firebase-setup.js +7 -0
  17. package/dist/bin/commands/firebase-setup.js.map +1 -0
  18. package/dist/bin/commands/format.js +13 -12
  19. package/dist/bin/commands/lint.js +13 -12
  20. package/dist/bin/commands/preview.js +13 -12
  21. package/dist/bin/commands/staging.d.ts +11 -0
  22. package/dist/bin/commands/staging.d.ts.map +1 -0
  23. package/dist/bin/commands/staging.js +12 -0
  24. package/dist/bin/commands/staging.js.map +1 -0
  25. package/dist/bin/commands/sync-secrets.js +13 -12
  26. package/dist/bin/commands/wai.js +7397 -11
  27. package/dist/bin/dndev.js +28 -3
  28. package/dist/bin/donotdev.js +28 -3
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +7760 -109
  32. package/dist/index.js.map +1 -1
  33. package/package.json +1 -1
  34. package/templates/app-demo/src/pages/DetailPage.tsx.example +1 -1
  35. package/templates/app-demo/src/pages/FullPage.tsx.example +3 -3
  36. package/templates/app-demo/src/pages/HomePage.tsx.example +1 -1
  37. package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +5 -5
  38. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +3 -3
  39. package/templates/app-next/.env.example +2 -0
  40. package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
  41. package/templates/app-vite/.env.example +2 -0
  42. package/templates/app-vite/src/pages/HomePage.tsx.example +163 -73
  43. package/templates/functions-firebase/build.mjs.example +26 -10
  44. package/templates/functions-firebase/functions-firebase/build.mjs.example +26 -10
  45. package/templates/functions-firebase/functions.config.js.example +11 -15
  46. package/templates/github-consumer/.github/workflows/ci.yml.example +36 -0
  47. package/templates/root-consumer/.claude/agents/architect.md.example +2 -2
  48. package/templates/root-consumer/.claude/agents/builder.md.example +2 -2
  49. package/templates/root-consumer/.claude/agents/coder.md.example +2 -2
  50. package/templates/root-consumer/.claude/agents/extractor.md.example +2 -3
  51. package/templates/root-consumer/.claude/agents/polisher.md.example +67 -291
  52. package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +4 -4
  53. package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
  54. package/templates/root-consumer/.claude/commands/build.md.example +3 -3
  55. package/templates/root-consumer/.claude/commands/design.md.example +1 -1
  56. package/templates/root-consumer/.claude/commands/polish.md.example +66 -82
  57. package/templates/root-consumer/.dndev/args.json.example +6 -0
  58. package/templates/root-consumer/.env.example +13 -13
  59. package/templates/root-consumer/.gemini/settings.json.example +9 -0
  60. package/templates/root-consumer/.gitignore.example +3 -1
  61. package/templates/root-consumer/AI.md.example +150 -0
  62. package/templates/root-consumer/CLAUDE.md.example +19 -104
  63. package/templates/root-consumer/README.md.example +81 -255
  64. package/templates/root-consumer/entities/Contact.ts.example +126 -0
  65. package/templates/root-consumer/entities/index.ts.example +6 -3
  66. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +59 -326
  67. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +2 -1
  68. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +144 -9
  69. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
  70. package/templates/root-consumer/guides/dndev/INDEX.md.example +10 -0
  71. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +13 -16
  72. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +263 -0
  73. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +1 -1
  74. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +168 -0
  75. package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +17 -19
  76. package/templates/root-consumer/guides/dndev/SETUP_TESTING.md.example +184 -0
  77. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +134 -69
  78. package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +66 -44
  79. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +18 -1
  80. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +1 -0
  81. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +2 -1
  82. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +2 -1
  83. package/templates/root-consumer/guides/wai-way/blueprints/4_configure.md.example +180 -108
  84. package/templates/root-consumer/guides/wai-way/context_map.json.example +8 -7
  85. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +4 -4
@@ -2139,7 +2139,7 @@ var require_parse = __commonJS({
2139
2139
  CHAR_NO_BREAK_SPACE,
2140
2140
  CHAR_ZERO_WIDTH_NOBREAK_SPACE
2141
2141
  } = require_constants();
2142
- var parse = (input, options = {}) => {
2142
+ var parse2 = (input, options = {}) => {
2143
2143
  if (typeof input !== "string") {
2144
2144
  throw new TypeError("Expected a string");
2145
2145
  }
@@ -2339,7 +2339,7 @@ var require_parse = __commonJS({
2339
2339
  push({ type: "eos" });
2340
2340
  return ast;
2341
2341
  };
2342
- module.exports = parse;
2342
+ module.exports = parse2;
2343
2343
  }
2344
2344
  });
2345
2345
 
@@ -2351,7 +2351,7 @@ var require_braces = __commonJS({
2351
2351
  var stringify2 = require_stringify();
2352
2352
  var compile = require_compile();
2353
2353
  var expand = require_expand();
2354
- var parse = require_parse();
2354
+ var parse2 = require_parse();
2355
2355
  var braces = (input, options = {}) => {
2356
2356
  let output = [];
2357
2357
  if (Array.isArray(input)) {
@@ -2371,7 +2371,7 @@ var require_braces = __commonJS({
2371
2371
  }
2372
2372
  return output;
2373
2373
  };
2374
- braces.parse = (input, options = {}) => parse(input, options);
2374
+ braces.parse = (input, options = {}) => parse2(input, options);
2375
2375
  braces.stringify = (input, options = {}) => {
2376
2376
  if (typeof input === "string") {
2377
2377
  return stringify2(braces.parse(input, options), options);
@@ -3028,7 +3028,7 @@ var require_parse2 = __commonJS({
3028
3028
  var syntaxError = (type, char) => {
3029
3029
  return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
3030
3030
  };
3031
- var parse = (input, options) => {
3031
+ var parse2 = (input, options) => {
3032
3032
  if (typeof input !== "string") {
3033
3033
  throw new TypeError("Expected a string");
3034
3034
  }
@@ -3177,7 +3177,7 @@ var require_parse2 = __commonJS({
3177
3177
  output = token.close = `)$))${extglobStar}`;
3178
3178
  }
3179
3179
  if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
3180
- const expression = parse(rest, { ...options, fastpaths: false }).output;
3180
+ const expression = parse2(rest, { ...options, fastpaths: false }).output;
3181
3181
  output = token.close = `)${expression})${extglobStar})`;
3182
3182
  }
3183
3183
  if (token.prev.type === "bos") {
@@ -3702,7 +3702,7 @@ var require_parse2 = __commonJS({
3702
3702
  }
3703
3703
  return state;
3704
3704
  };
3705
- parse.fastpaths = (input, options) => {
3705
+ parse2.fastpaths = (input, options) => {
3706
3706
  const opts = { ...options };
3707
3707
  const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
3708
3708
  const len = input.length;
@@ -3768,7 +3768,7 @@ var require_parse2 = __commonJS({
3768
3768
  }
3769
3769
  return source;
3770
3770
  };
3771
- module.exports = parse;
3771
+ module.exports = parse2;
3772
3772
  }
3773
3773
  });
3774
3774
 
@@ -3779,7 +3779,7 @@ var require_picomatch = __commonJS({
3779
3779
  init_utils();
3780
3780
  var path = __require("path");
3781
3781
  var scan = require_scan();
3782
- var parse = require_parse2();
3782
+ var parse2 = require_parse2();
3783
3783
  var utils = require_utils2();
3784
3784
  var constants2 = require_constants2();
3785
3785
  var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
@@ -3867,7 +3867,7 @@ var require_picomatch = __commonJS({
3867
3867
  picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
3868
3868
  picomatch.parse = (pattern, options) => {
3869
3869
  if (Array.isArray(pattern)) return pattern.map((p2) => picomatch.parse(p2, options));
3870
- return parse(pattern, { ...options, fastpaths: false });
3870
+ return parse2(pattern, { ...options, fastpaths: false });
3871
3871
  };
3872
3872
  picomatch.scan = (input, options) => scan(input, options);
3873
3873
  picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => {
@@ -3893,10 +3893,10 @@ var require_picomatch = __commonJS({
3893
3893
  }
3894
3894
  let parsed = { negated: false, fastpaths: true };
3895
3895
  if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
3896
- parsed.output = parse.fastpaths(input, options);
3896
+ parsed.output = parse2.fastpaths(input, options);
3897
3897
  }
3898
3898
  if (!parsed.output) {
3899
- parsed = parse(input, options);
3899
+ parsed = parse2(input, options);
3900
3900
  }
3901
3901
  return picomatch.compileRe(parsed, options, returnOutput, returnState);
3902
3902
  };
@@ -7757,119 +7757,6 @@ var init_PathResolver = __esm({
7757
7757
  }
7758
7758
  });
7759
7759
 
7760
- // packages/tooling/src/utils/errors.ts
7761
- var DoNotDevError;
7762
- var init_errors = __esm({
7763
- "packages/tooling/src/utils/errors.ts"() {
7764
- "use strict";
7765
- init_utils();
7766
- DoNotDevError = class _DoNotDevError extends Error {
7767
- /** The error code categorizing this error */
7768
- code;
7769
- /** Original error if this is wrapping another error */
7770
- originalError;
7771
- /** Additional context for the error */
7772
- context;
7773
- /** Whether this error should be displayed to the user */
7774
- displayable;
7775
- /**
7776
- * Creates a new DoNotDev error
7777
- *
7778
- * @param {string} message - Error message
7779
- * @param {DoNotDevErrorCode} code - Error code
7780
- * @param {object} [options] - Additional error options
7781
- * @param {Error} [options.originalError] - Original error if wrapping
7782
- * @param {Record<string, any>} [options.context] - Additional context data
7783
- * @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
7784
- */
7785
- constructor(message, code = "unknown-error", options) {
7786
- super(message);
7787
- this.name = "DoNotDevError";
7788
- this.code = code;
7789
- this.originalError = options?.originalError;
7790
- this.context = options?.context;
7791
- this.displayable = options?.displayable !== false;
7792
- Object.setPrototypeOf(this, _DoNotDevError.prototype);
7793
- if (Error.captureStackTrace) {
7794
- Error.captureStackTrace(this, _DoNotDevError);
7795
- }
7796
- }
7797
- /**
7798
- * Formats the error for logging or display
7799
- *
7800
- * @returns {string} Formatted error message with code
7801
- */
7802
- format() {
7803
- return `[${this.code}] ${this.message}`;
7804
- }
7805
- /**
7806
- * Creates a wrapped error from another error
7807
- *
7808
- * @param {Error} error - Original error to wrap
7809
- * @param {string} [context] - Additional context for the error
7810
- * @param {DoNotDevErrorCode} [code='unknown-error'] - Error code
7811
- * @param {object} [options] - Additional error options
7812
- * @param {Record<string, any>} [options.context] - Additional context data
7813
- * @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
7814
- * @returns {DoNotDevError} New DoNotDev error wrapping the original
7815
- */
7816
- static from(error2, context, code = "unknown-error", options) {
7817
- if (!(error2 instanceof Error)) {
7818
- return new _DoNotDevError(
7819
- `Unknown error: ${String(error2)}`,
7820
- code,
7821
- options
7822
- );
7823
- }
7824
- if (error2 instanceof _DoNotDevError) {
7825
- if (!context) {
7826
- return error2;
7827
- }
7828
- return new _DoNotDevError(`${context}: ${error2.message}`, error2.code, {
7829
- originalError: error2.originalError || error2,
7830
- context: { ...error2.context, ...options?.context || {} },
7831
- displayable: options?.displayable ?? error2.displayable
7832
- });
7833
- }
7834
- const message = context ? `${context}: ${error2.message}` : error2.message;
7835
- return new _DoNotDevError(message, code, {
7836
- originalError: error2,
7837
- context: options?.context,
7838
- displayable: options?.displayable
7839
- });
7840
- }
7841
- /**
7842
- * Maps common error types to DoNotDevErrorCode
7843
- *
7844
- * @param {Error} error - Error to analyze
7845
- * @returns {DoNotDevErrorCode} Mapped error code
7846
- */
7847
- static getErrorCodeFromError(error2) {
7848
- if (error2 instanceof _DoNotDevError) {
7849
- return error2.code;
7850
- }
7851
- const message = error2.message.toLowerCase();
7852
- if (error2.name === "ValidationError" || message.includes("validation")) {
7853
- return "validation-error";
7854
- }
7855
- if (message.includes("not found") || message.includes("no such file")) {
7856
- return "file-not-found";
7857
- }
7858
- if (message.includes("permission") || message.includes("access denied")) {
7859
- return "permission-denied";
7860
- }
7861
- if (message.includes("timeout") || message.includes("timed out")) {
7862
- return "timeout-error";
7863
- }
7864
- if (message.includes("dependency") || message.includes("module not found")) {
7865
- return "dependency-error";
7866
- }
7867
- return "unknown-error";
7868
- }
7869
- };
7870
- }
7871
- });
7872
-
7873
7760
  // packages/tooling/src/utils/pathResolver.ts
7874
7761
  var pathResolver_exports = {};
7875
7762
  __export(pathResolver_exports, {
@@ -7884,6 +7771,7 @@ __export(pathResolver_exports, {
7884
7771
  ensureDirSync: () => ensureDirSync,
7885
7772
  findFiles: () => findFiles,
7886
7773
  findNodeModulesDir: () => findNodeModulesDir,
7774
+ findPackageRootUp: () => findPackageRootUp,
7887
7775
  fromAppRoot: () => fromAppRoot,
7888
7776
  getAppRoot: () => getAppRoot,
7889
7777
  getBasename: () => getBasename,
@@ -7900,7 +7788,6 @@ __export(pathResolver_exports, {
7900
7788
  getRelativePathBetween: () => getRelativePathBetween,
7901
7789
  getRepoRoot: () => getRepoRoot,
7902
7790
  getTemplatesRoot: () => getTemplatesRoot,
7903
- getToolingPath: () => getToolingPath,
7904
7791
  glob: () => glob,
7905
7792
  globSync: () => globSync,
7906
7793
  isAbsolute: () => isAbsolute,
@@ -7939,6 +7826,7 @@ import {
7939
7826
  extname as extname2,
7940
7827
  relative as relative2,
7941
7828
  resolve as resolve2,
7829
+ parse,
7942
7830
  isAbsolute as pathIsAbsolute
7943
7831
  } from "node:path";
7944
7832
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -7995,37 +7883,19 @@ function getBinPath(binaryName) {
7995
7883
  }
7996
7884
  return binaryName;
7997
7885
  }
7998
- function getToolingPath() {
7999
- const mode = detectExecutionMode();
8000
- if (mode === "development") {
8001
- const repoRoot = getRepoRoot();
8002
- const packagesToolingPath = normalizePath(repoRoot, PACKAGE_PATHS.TOOLING);
8003
- if (pathExists(packagesToolingPath)) {
8004
- return normalizePath(packagesToolingPath);
8005
- }
8006
- }
8007
- throw new DoNotDevError(
8008
- "Could not find tooling package. This function is only available in development mode.",
8009
- "path-resolution-error"
8010
- );
8011
- }
8012
7886
  function detectExecutionMode() {
8013
- const currentDir = process.cwd();
8014
- const toolingPath = joinPath(currentDir, PACKAGE_PATHS.TOOLING);
8015
- if (pathExists(toolingPath)) {
8016
- return "development";
8017
- }
8018
7887
  const fileUrlPath = new URL(import.meta.url).pathname;
8019
- if (fileUrlPath.includes("node_modules/@donotdev/cli")) {
8020
- return "published";
7888
+ if (!fileUrlPath.includes("node_modules")) {
7889
+ return "development";
8021
7890
  }
8022
7891
  return "published";
8023
7892
  }
8024
7893
  function getTemplatesRoot() {
8025
7894
  const mode = detectExecutionMode();
8026
7895
  if (mode === "development") {
8027
- const repoRoot = getRepoRoot();
8028
- return normalizePath(repoRoot, PACKAGE_PATHS.CLI, "templates");
7896
+ const fileUrlPath = new URL(import.meta.url).pathname;
7897
+ const frameworkRoot = normalizePath(dirname2(fileUrlPath), "../../../..");
7898
+ return normalizePath(frameworkRoot, PACKAGE_PATHS.CLI, "templates");
8029
7899
  } else {
8030
7900
  try {
8031
7901
  const cliRoot2 = resolveFrameworkPackage("@donotdev/cli");
@@ -8047,10 +7917,43 @@ function getTemplatesRoot() {
8047
7917
  }
8048
7918
  } catch {
8049
7919
  }
7920
+ try {
7921
+ const currentScriptDir = getDirnameFromUrl(import.meta.url);
7922
+ const packageRoot = findPackageRootUp(currentScriptDir, "@donotdev/cli");
7923
+ if (packageRoot) {
7924
+ const templatesPath = normalizePath(packageRoot, "templates");
7925
+ if (pathExists(templatesPath)) {
7926
+ return templatesPath;
7927
+ }
7928
+ }
7929
+ } catch {
7930
+ }
8050
7931
  const cliRoot = getCliRootFromBundle();
8051
7932
  return normalizePath(cliRoot, "templates");
8052
7933
  }
8053
7934
  }
7935
+ function findPackageRootUp(startDir, packageName) {
7936
+ let currentDir = normalizePath(startDir);
7937
+ const root = parse(currentDir).root;
7938
+ const fs2 = createRequire2(import.meta.url)("node:fs");
7939
+ while (currentDir !== root) {
7940
+ const packageJsonPath = joinPath(currentDir, "package.json");
7941
+ if (fs2.existsSync(packageJsonPath)) {
7942
+ try {
7943
+ const content = fs2.readFileSync(packageJsonPath, "utf8");
7944
+ const pkg = JSON.parse(content);
7945
+ if (pkg.name === packageName) {
7946
+ return currentDir;
7947
+ }
7948
+ } catch {
7949
+ }
7950
+ }
7951
+ const parentDir = getDirname(currentDir);
7952
+ if (parentDir === currentDir) break;
7953
+ currentDir = parentDir;
7954
+ }
7955
+ return null;
7956
+ }
8054
7957
  function getCliRootFromBundle() {
8055
7958
  const currentDir = getDirnameFromUrl(import.meta.url);
8056
7959
  return normalizePath(currentDir, "..", "..", "..");
@@ -8170,7 +8073,6 @@ var init_pathResolver = __esm({
8170
8073
  "use strict";
8171
8074
  init_utils();
8172
8075
  init_PathResolver();
8173
- init_errors();
8174
8076
  pathResolverInstance = PathResolver.getInstance({ debug: false });
8175
8077
  getPathResolver = (options) => PathResolver.getInstance(options);
8176
8078
  getRepoRoot = () => pathResolverInstance.getRepoRoot();
@@ -8287,7 +8189,7 @@ async function askForInput(message, defaultValue = "") {
8287
8189
  const result = await he({
8288
8190
  message,
8289
8191
  placeholder: defaultValue || void 0,
8290
- initialValue: defaultValue || void 0
8192
+ defaultValue: defaultValue || void 0
8291
8193
  });
8292
8194
  if (pD(result)) {
8293
8195
  xe("Operation cancelled.");
@@ -9267,6 +9169,17 @@ function detectExecutionMode2() {
9267
9169
  async function main(options) {
9268
9170
  try {
9269
9171
  Ie("\u{1F680} DoNotDev Project Creator");
9172
+ try {
9173
+ const { execSync } = await import("node:child_process");
9174
+ execSync("bun --version", { stdio: "ignore" });
9175
+ } catch {
9176
+ log.error("bun is required but not installed.");
9177
+ Me(
9178
+ "Install bun:\n\n curl -fsSL https://bun.sh/install | bash\n\nThen re-run: dndev init",
9179
+ "Missing dependency"
9180
+ );
9181
+ process.exit(1);
9182
+ }
9270
9183
  if (SHOW_WIP2) {
9271
9184
  Me("WIP mode enabled - showing experimental features", "\u{1F527} Debug");
9272
9185
  }
@@ -9499,9 +9412,6 @@ async function main(options) {
9499
9412
  log.info(
9500
9413
  `Creating project "${projectName}" with ${appNames.length} app(s): ${appNames.join(", ")}`
9501
9414
  );
9502
- let needsAuth = false;
9503
- let needsOAuth = false;
9504
- let needsBilling = false;
9505
9415
  for (const appName of appNames) {
9506
9416
  if (!appConfigs[appName]) {
9507
9417
  log.warn(`Missing config for app "${appName}", using defaults`);
@@ -9517,6 +9427,10 @@ async function main(options) {
9517
9427
  };
9518
9428
  }
9519
9429
  }
9430
+ const setupGithubActions = await askForConfirmation(
9431
+ "Set up GitHub Actions CI/CD?",
9432
+ true
9433
+ );
9520
9434
  const s = Y2();
9521
9435
  if (!isMergeMode) {
9522
9436
  s.start("Creating project structure...");
@@ -9528,6 +9442,21 @@ async function main(options) {
9528
9442
  joinPath(entitiesDir, "index.ts"),
9529
9443
  "// entities/index.ts\n// Add your entity files here\n// Entities are shared between frontend and backend\n"
9530
9444
  );
9445
+ const geminiDir = joinPath(projectDirNormalized, ".gemini");
9446
+ await ensureDir(geminiDir);
9447
+ const geminiSettings = {
9448
+ mcpServers: {
9449
+ donotdev: {
9450
+ command: "npx",
9451
+ args: ["-y", "@donotdev/mcp-server@latest"],
9452
+ trust: true
9453
+ }
9454
+ }
9455
+ };
9456
+ await write(joinPath(geminiDir, "settings.json"), geminiSettings, {
9457
+ format: "json",
9458
+ overwrite: true
9459
+ });
9531
9460
  const entitiesPackageJson = generatePackageJson(
9532
9461
  "entities",
9533
9462
  executionMode
@@ -9557,7 +9486,7 @@ async function main(options) {
9557
9486
  projectName,
9558
9487
  appNames: isMergeMode ? allAppNames : appNames,
9559
9488
  includeFunctions: anyAppNeedsBackend,
9560
- setupGithubActions: false,
9489
+ setupGithubActions,
9561
9490
  monorepoRelativePath: relativeMonorepoPath,
9562
9491
  appTemplate: "vite",
9563
9492
  isNextjs: false,
@@ -9566,9 +9495,12 @@ async function main(options) {
9566
9495
  firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
9567
9496
  YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
9568
9497
  YOUR_REGION: firebaseRegion,
9569
- needsAuth,
9570
- needsOAuth,
9571
- needsBilling
9498
+ needsAuth: false,
9499
+ // Determined by agent in WAI-WAY Phase 0
9500
+ needsOAuth: false,
9501
+ // Determined by agent in WAI-WAY Phase 0
9502
+ needsBilling: false
9503
+ // Determined by agent in WAI-WAY Phase 0
9572
9504
  };
9573
9505
  const firebaseRootFiles = /* @__PURE__ */ new Set([
9574
9506
  "firebase.json.example",
@@ -9597,6 +9529,10 @@ async function main(options) {
9597
9529
  await replacePlaceholders(destPath, rootReplacements);
9598
9530
  }
9599
9531
  }
9532
+ if (setupGithubActions) {
9533
+ const ciTemplateDir = joinPath(templatesRoot, "github-consumer");
9534
+ await copyTemplateFiles(ciTemplateDir, projectDirNormalized, rootReplacements);
9535
+ }
9600
9536
  s.stop("Project structure created");
9601
9537
  } else {
9602
9538
  s.start("Merging root files...");
@@ -9620,9 +9556,9 @@ async function main(options) {
9620
9556
  }
9621
9557
  const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "../../packages/tooling";
9622
9558
  await mergeRootPackageJson(projectDirNormalized, allAppNames, {
9623
- needsAuth,
9624
- needsOAuth,
9625
- needsBilling,
9559
+ needsAuth: false,
9560
+ needsOAuth: false,
9561
+ needsBilling: false,
9626
9562
  monorepoRelativePath: relativeMonorepoPath
9627
9563
  });
9628
9564
  await mergeRootTsConfig(
@@ -9704,14 +9640,20 @@ async function main(options) {
9704
9640
  Se("\u{1F389} Project created successfully!");
9705
9641
  const cdCommand = executionMode === "development" ? `cd ../${projectName}` : `cd ${projectName}`;
9706
9642
  Me(
9707
- `Next steps:
9708
-
9709
- 1. ${cdCommand}
9643
+ `1. ${cdCommand}
9710
9644
  2. bun install
9711
- 3. dndev dev
9712
- ` + (anyAppNeedsBackend ? `4. dndev emu (to run with emulators)
9645
+ 3. Open the project in your IDE
9646
+ 4. Tell your AI agent:
9647
+
9648
+ "Read AI.md and build my app"
9649
+
9650
+ The AI agent will use the MCP server automatically.
9651
+ It handles everything: spec, scaffold, entities, pages.
9652
+
9653
+ Cursor users: enable MCP in Settings > Tools & MCP > toggle "donotdev" ON
9654
+ Claude Code / Windsurf: MCP auto-connects, nothing to do
9713
9655
 
9714
- ` : "\n") + `Enjoy the ride!`,
9656
+ ` + (anyAppNeedsBackend ? `Dev server: dndev dev | With emulators: dndev emu` : `Dev server: dndev dev`),
9715
9657
  "\u{1F4CB} Next Steps"
9716
9658
  );
9717
9659
  } catch (error2) {