@donotdev/cli 0.0.13 → 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.
- package/dependencies-matrix.json +2 -2
- package/dist/bin/commands/agent-setup.d.ts +6 -0
- package/dist/bin/commands/agent-setup.d.ts.map +1 -0
- package/dist/bin/commands/agent-setup.js +623 -0
- package/dist/bin/commands/agent-setup.js.map +1 -0
- package/dist/bin/commands/build.js +13 -12
- package/dist/bin/commands/bump.js +70 -28
- package/dist/bin/commands/cacheout.js +13 -12
- package/dist/bin/commands/create-app.js +53 -151
- package/dist/bin/commands/create-project.js +72 -166
- package/dist/bin/commands/deploy.js +16 -15
- package/dist/bin/commands/dev.js +13 -12
- package/dist/bin/commands/emu.js +13 -12
- package/dist/bin/commands/format.js +13 -12
- package/dist/bin/commands/lint.js +13 -12
- package/dist/bin/commands/preview.js +13 -12
- package/dist/bin/commands/sync-secrets.js +13 -12
- package/dist/bin/commands/wai.js +7397 -11
- package/dist/index.js +74 -55
- package/package.json +1 -1
- package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
- package/templates/root-consumer/.claude/commands/build.md.example +1 -1
- package/templates/root-consumer/.claude/commands/design.md.example +1 -1
- package/templates/root-consumer/.claude/commands/polish.md.example +1 -1
- package/templates/root-consumer/.dndev/args.json.example +6 -0
- package/templates/root-consumer/.gemini/settings.json.example +2 -2
- package/templates/root-consumer/AI.md.example +25 -14
- package/templates/root-consumer/CLAUDE.md.example +10 -4
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +34 -0
- package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
- package/templates/root-consumer/guides/dndev/INDEX.md.example +1 -0
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +12 -7
package/dist/index.js
CHANGED
|
@@ -2214,7 +2214,7 @@ var require_parse = __commonJS({
|
|
|
2214
2214
|
CHAR_NO_BREAK_SPACE,
|
|
2215
2215
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE
|
|
2216
2216
|
} = require_constants();
|
|
2217
|
-
var
|
|
2217
|
+
var parse2 = (input, options = {}) => {
|
|
2218
2218
|
if (typeof input !== "string") {
|
|
2219
2219
|
throw new TypeError("Expected a string");
|
|
2220
2220
|
}
|
|
@@ -2414,7 +2414,7 @@ var require_parse = __commonJS({
|
|
|
2414
2414
|
push({ type: "eos" });
|
|
2415
2415
|
return ast;
|
|
2416
2416
|
};
|
|
2417
|
-
module.exports =
|
|
2417
|
+
module.exports = parse2;
|
|
2418
2418
|
}
|
|
2419
2419
|
});
|
|
2420
2420
|
|
|
@@ -2426,7 +2426,7 @@ var require_braces = __commonJS({
|
|
|
2426
2426
|
var stringify2 = require_stringify();
|
|
2427
2427
|
var compile = require_compile();
|
|
2428
2428
|
var expand = require_expand();
|
|
2429
|
-
var
|
|
2429
|
+
var parse2 = require_parse();
|
|
2430
2430
|
var braces = (input, options = {}) => {
|
|
2431
2431
|
let output = [];
|
|
2432
2432
|
if (Array.isArray(input)) {
|
|
@@ -2446,7 +2446,7 @@ var require_braces = __commonJS({
|
|
|
2446
2446
|
}
|
|
2447
2447
|
return output;
|
|
2448
2448
|
};
|
|
2449
|
-
braces.parse = (input, options = {}) =>
|
|
2449
|
+
braces.parse = (input, options = {}) => parse2(input, options);
|
|
2450
2450
|
braces.stringify = (input, options = {}) => {
|
|
2451
2451
|
if (typeof input === "string") {
|
|
2452
2452
|
return stringify2(braces.parse(input, options), options);
|
|
@@ -3103,7 +3103,7 @@ var require_parse2 = __commonJS({
|
|
|
3103
3103
|
var syntaxError = (type, char) => {
|
|
3104
3104
|
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
|
|
3105
3105
|
};
|
|
3106
|
-
var
|
|
3106
|
+
var parse2 = (input, options) => {
|
|
3107
3107
|
if (typeof input !== "string") {
|
|
3108
3108
|
throw new TypeError("Expected a string");
|
|
3109
3109
|
}
|
|
@@ -3252,7 +3252,7 @@ var require_parse2 = __commonJS({
|
|
|
3252
3252
|
output = token.close = `)$))${extglobStar}`;
|
|
3253
3253
|
}
|
|
3254
3254
|
if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
|
3255
|
-
const expression =
|
|
3255
|
+
const expression = parse2(rest, { ...options, fastpaths: false }).output;
|
|
3256
3256
|
output = token.close = `)${expression})${extglobStar})`;
|
|
3257
3257
|
}
|
|
3258
3258
|
if (token.prev.type === "bos") {
|
|
@@ -3777,7 +3777,7 @@ var require_parse2 = __commonJS({
|
|
|
3777
3777
|
}
|
|
3778
3778
|
return state;
|
|
3779
3779
|
};
|
|
3780
|
-
|
|
3780
|
+
parse2.fastpaths = (input, options) => {
|
|
3781
3781
|
const opts = { ...options };
|
|
3782
3782
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
3783
3783
|
const len = input.length;
|
|
@@ -3843,7 +3843,7 @@ var require_parse2 = __commonJS({
|
|
|
3843
3843
|
}
|
|
3844
3844
|
return source;
|
|
3845
3845
|
};
|
|
3846
|
-
module.exports =
|
|
3846
|
+
module.exports = parse2;
|
|
3847
3847
|
}
|
|
3848
3848
|
});
|
|
3849
3849
|
|
|
@@ -3854,7 +3854,7 @@ var require_picomatch = __commonJS({
|
|
|
3854
3854
|
init_utils();
|
|
3855
3855
|
var path = __require("path");
|
|
3856
3856
|
var scan = require_scan();
|
|
3857
|
-
var
|
|
3857
|
+
var parse2 = require_parse2();
|
|
3858
3858
|
var utils = require_utils2();
|
|
3859
3859
|
var constants2 = require_constants2();
|
|
3860
3860
|
var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
|
|
@@ -3942,7 +3942,7 @@ var require_picomatch = __commonJS({
|
|
|
3942
3942
|
picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
|
|
3943
3943
|
picomatch.parse = (pattern, options) => {
|
|
3944
3944
|
if (Array.isArray(pattern)) return pattern.map((p2) => picomatch.parse(p2, options));
|
|
3945
|
-
return
|
|
3945
|
+
return parse2(pattern, { ...options, fastpaths: false });
|
|
3946
3946
|
};
|
|
3947
3947
|
picomatch.scan = (input, options) => scan(input, options);
|
|
3948
3948
|
picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => {
|
|
@@ -3968,10 +3968,10 @@ var require_picomatch = __commonJS({
|
|
|
3968
3968
|
}
|
|
3969
3969
|
let parsed = { negated: false, fastpaths: true };
|
|
3970
3970
|
if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
|
|
3971
|
-
parsed.output =
|
|
3971
|
+
parsed.output = parse2.fastpaths(input, options);
|
|
3972
3972
|
}
|
|
3973
3973
|
if (!parsed.output) {
|
|
3974
|
-
parsed =
|
|
3974
|
+
parsed = parse2(input, options);
|
|
3975
3975
|
}
|
|
3976
3976
|
return picomatch.compileRe(parsed, options, returnOutput, returnState);
|
|
3977
3977
|
};
|
|
@@ -7959,6 +7959,7 @@ __export(pathResolver_exports, {
|
|
|
7959
7959
|
ensureDirSync: () => ensureDirSync,
|
|
7960
7960
|
findFiles: () => findFiles,
|
|
7961
7961
|
findNodeModulesDir: () => findNodeModulesDir,
|
|
7962
|
+
findPackageRootUp: () => findPackageRootUp,
|
|
7962
7963
|
fromAppRoot: () => fromAppRoot,
|
|
7963
7964
|
getAppRoot: () => getAppRoot,
|
|
7964
7965
|
getBasename: () => getBasename,
|
|
@@ -7975,7 +7976,6 @@ __export(pathResolver_exports, {
|
|
|
7975
7976
|
getRelativePathBetween: () => getRelativePathBetween,
|
|
7976
7977
|
getRepoRoot: () => getRepoRoot,
|
|
7977
7978
|
getTemplatesRoot: () => getTemplatesRoot,
|
|
7978
|
-
getToolingPath: () => getToolingPath,
|
|
7979
7979
|
glob: () => glob,
|
|
7980
7980
|
globSync: () => globSync,
|
|
7981
7981
|
isAbsolute: () => isAbsolute,
|
|
@@ -8014,6 +8014,7 @@ import {
|
|
|
8014
8014
|
extname as extname2,
|
|
8015
8015
|
relative as relative2,
|
|
8016
8016
|
resolve as resolve2,
|
|
8017
|
+
parse,
|
|
8017
8018
|
isAbsolute as pathIsAbsolute
|
|
8018
8019
|
} from "node:path";
|
|
8019
8020
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -8070,37 +8071,19 @@ function getBinPath(binaryName) {
|
|
|
8070
8071
|
}
|
|
8071
8072
|
return binaryName;
|
|
8072
8073
|
}
|
|
8073
|
-
function getToolingPath() {
|
|
8074
|
-
const mode = detectExecutionMode();
|
|
8075
|
-
if (mode === "development") {
|
|
8076
|
-
const repoRoot = getRepoRoot();
|
|
8077
|
-
const packagesToolingPath = normalizePath(repoRoot, PACKAGE_PATHS.TOOLING);
|
|
8078
|
-
if (pathExists(packagesToolingPath)) {
|
|
8079
|
-
return normalizePath(packagesToolingPath);
|
|
8080
|
-
}
|
|
8081
|
-
}
|
|
8082
|
-
throw new DoNotDevError(
|
|
8083
|
-
"Could not find tooling package. This function is only available in development mode.",
|
|
8084
|
-
"path-resolution-error"
|
|
8085
|
-
);
|
|
8086
|
-
}
|
|
8087
8074
|
function detectExecutionMode() {
|
|
8088
|
-
const currentDir = process.cwd();
|
|
8089
|
-
const toolingPath = joinPath(currentDir, PACKAGE_PATHS.TOOLING);
|
|
8090
|
-
if (pathExists(toolingPath)) {
|
|
8091
|
-
return "development";
|
|
8092
|
-
}
|
|
8093
8075
|
const fileUrlPath = new URL(import.meta.url).pathname;
|
|
8094
|
-
if (fileUrlPath.includes("node_modules
|
|
8095
|
-
return "
|
|
8076
|
+
if (!fileUrlPath.includes("node_modules")) {
|
|
8077
|
+
return "development";
|
|
8096
8078
|
}
|
|
8097
8079
|
return "published";
|
|
8098
8080
|
}
|
|
8099
8081
|
function getTemplatesRoot() {
|
|
8100
8082
|
const mode = detectExecutionMode();
|
|
8101
8083
|
if (mode === "development") {
|
|
8102
|
-
const
|
|
8103
|
-
|
|
8084
|
+
const fileUrlPath = new URL(import.meta.url).pathname;
|
|
8085
|
+
const frameworkRoot = normalizePath(dirname2(fileUrlPath), "../../../..");
|
|
8086
|
+
return normalizePath(frameworkRoot, PACKAGE_PATHS.CLI, "templates");
|
|
8104
8087
|
} else {
|
|
8105
8088
|
try {
|
|
8106
8089
|
const cliRoot2 = resolveFrameworkPackage("@donotdev/cli");
|
|
@@ -8122,10 +8105,43 @@ function getTemplatesRoot() {
|
|
|
8122
8105
|
}
|
|
8123
8106
|
} catch {
|
|
8124
8107
|
}
|
|
8108
|
+
try {
|
|
8109
|
+
const currentScriptDir = getDirnameFromUrl(import.meta.url);
|
|
8110
|
+
const packageRoot = findPackageRootUp(currentScriptDir, "@donotdev/cli");
|
|
8111
|
+
if (packageRoot) {
|
|
8112
|
+
const templatesPath = normalizePath(packageRoot, "templates");
|
|
8113
|
+
if (pathExists(templatesPath)) {
|
|
8114
|
+
return templatesPath;
|
|
8115
|
+
}
|
|
8116
|
+
}
|
|
8117
|
+
} catch {
|
|
8118
|
+
}
|
|
8125
8119
|
const cliRoot = getCliRootFromBundle();
|
|
8126
8120
|
return normalizePath(cliRoot, "templates");
|
|
8127
8121
|
}
|
|
8128
8122
|
}
|
|
8123
|
+
function findPackageRootUp(startDir, packageName) {
|
|
8124
|
+
let currentDir = normalizePath(startDir);
|
|
8125
|
+
const root = parse(currentDir).root;
|
|
8126
|
+
const fs2 = createRequire2(import.meta.url)("node:fs");
|
|
8127
|
+
while (currentDir !== root) {
|
|
8128
|
+
const packageJsonPath = joinPath(currentDir, "package.json");
|
|
8129
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
8130
|
+
try {
|
|
8131
|
+
const content = fs2.readFileSync(packageJsonPath, "utf8");
|
|
8132
|
+
const pkg = JSON.parse(content);
|
|
8133
|
+
if (pkg.name === packageName) {
|
|
8134
|
+
return currentDir;
|
|
8135
|
+
}
|
|
8136
|
+
} catch {
|
|
8137
|
+
}
|
|
8138
|
+
}
|
|
8139
|
+
const parentDir = getDirname(currentDir);
|
|
8140
|
+
if (parentDir === currentDir) break;
|
|
8141
|
+
currentDir = parentDir;
|
|
8142
|
+
}
|
|
8143
|
+
return null;
|
|
8144
|
+
}
|
|
8129
8145
|
function getCliRootFromBundle() {
|
|
8130
8146
|
const currentDir = getDirnameFromUrl(import.meta.url);
|
|
8131
8147
|
return normalizePath(currentDir, "..", "..", "..");
|
|
@@ -8245,7 +8261,6 @@ var init_pathResolver = __esm({
|
|
|
8245
8261
|
"use strict";
|
|
8246
8262
|
init_utils();
|
|
8247
8263
|
init_PathResolver();
|
|
8248
|
-
init_errors();
|
|
8249
8264
|
pathResolverInstance = PathResolver.getInstance({ debug: false });
|
|
8250
8265
|
getPathResolver = (options) => PathResolver.getInstance(options);
|
|
8251
8266
|
getRepoRoot = () => pathResolverInstance.getRepoRoot();
|
|
@@ -15606,7 +15621,7 @@ var require_public_api = __commonJS({
|
|
|
15606
15621
|
}
|
|
15607
15622
|
return doc;
|
|
15608
15623
|
}
|
|
15609
|
-
function
|
|
15624
|
+
function parse2(src, reviver, options) {
|
|
15610
15625
|
let _reviver = void 0;
|
|
15611
15626
|
if (typeof reviver === "function") {
|
|
15612
15627
|
_reviver = reviver;
|
|
@@ -15647,7 +15662,7 @@ var require_public_api = __commonJS({
|
|
|
15647
15662
|
return value.toString(options);
|
|
15648
15663
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
15649
15664
|
}
|
|
15650
|
-
exports.parse =
|
|
15665
|
+
exports.parse = parse2;
|
|
15651
15666
|
exports.parseAllDocuments = parseAllDocuments;
|
|
15652
15667
|
exports.parseDocument = parseDocument;
|
|
15653
15668
|
exports.stringify = stringify2;
|
|
@@ -15849,7 +15864,7 @@ async function askForInput(message, defaultValue = "") {
|
|
|
15849
15864
|
const result = await he({
|
|
15850
15865
|
message,
|
|
15851
15866
|
placeholder: defaultValue || void 0,
|
|
15852
|
-
|
|
15867
|
+
defaultValue: defaultValue || void 0
|
|
15853
15868
|
});
|
|
15854
15869
|
if (pD(result)) {
|
|
15855
15870
|
xe("Operation cancelled.");
|
|
@@ -19578,9 +19593,6 @@ async function main9(options) {
|
|
|
19578
19593
|
log.info(
|
|
19579
19594
|
`Creating project "${projectName}" with ${appNames.length} app(s): ${appNames.join(", ")}`
|
|
19580
19595
|
);
|
|
19581
|
-
let needsAuth = false;
|
|
19582
|
-
let needsOAuth = false;
|
|
19583
|
-
let needsBilling = false;
|
|
19584
19596
|
for (const appName of appNames) {
|
|
19585
19597
|
if (!appConfigs[appName]) {
|
|
19586
19598
|
log.warn(`Missing config for app "${appName}", using defaults`);
|
|
@@ -19664,9 +19676,12 @@ async function main9(options) {
|
|
|
19664
19676
|
firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
|
|
19665
19677
|
YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
|
|
19666
19678
|
YOUR_REGION: firebaseRegion,
|
|
19667
|
-
needsAuth,
|
|
19668
|
-
|
|
19669
|
-
|
|
19679
|
+
needsAuth: false,
|
|
19680
|
+
// Determined by agent in WAI-WAY Phase 0
|
|
19681
|
+
needsOAuth: false,
|
|
19682
|
+
// Determined by agent in WAI-WAY Phase 0
|
|
19683
|
+
needsBilling: false
|
|
19684
|
+
// Determined by agent in WAI-WAY Phase 0
|
|
19670
19685
|
};
|
|
19671
19686
|
const firebaseRootFiles = /* @__PURE__ */ new Set([
|
|
19672
19687
|
"firebase.json.example",
|
|
@@ -19722,9 +19737,9 @@ async function main9(options) {
|
|
|
19722
19737
|
}
|
|
19723
19738
|
const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "../../packages/tooling";
|
|
19724
19739
|
await mergeRootPackageJson(projectDirNormalized, allAppNames, {
|
|
19725
|
-
needsAuth,
|
|
19726
|
-
needsOAuth,
|
|
19727
|
-
needsBilling,
|
|
19740
|
+
needsAuth: false,
|
|
19741
|
+
needsOAuth: false,
|
|
19742
|
+
needsBilling: false,
|
|
19728
19743
|
monorepoRelativePath: relativeMonorepoPath
|
|
19729
19744
|
});
|
|
19730
19745
|
await mergeRootTsConfig(
|
|
@@ -19808,14 +19823,18 @@ async function main9(options) {
|
|
|
19808
19823
|
Me(
|
|
19809
19824
|
`1. ${cdCommand}
|
|
19810
19825
|
2. bun install
|
|
19811
|
-
3. Open the project in your IDE
|
|
19812
|
-
4. Tell your AI agent:
|
|
19826
|
+
3. Open the project in your IDE
|
|
19827
|
+
4. Tell your AI agent:
|
|
19828
|
+
|
|
19829
|
+
"Read AI.md and build my app"
|
|
19830
|
+
|
|
19831
|
+
The AI agent will use the MCP server automatically.
|
|
19832
|
+
It handles everything: spec, scaffold, entities, pages.
|
|
19813
19833
|
|
|
19814
|
-
|
|
19834
|
+
Cursor users: enable MCP in Settings > Tools & MCP > toggle "donotdev" ON
|
|
19835
|
+
Claude Code / Windsurf: MCP auto-connects, nothing to do
|
|
19815
19836
|
|
|
19816
|
-
` + (anyAppNeedsBackend ? `Dev server: dndev dev | With emulators: dndev emu
|
|
19817
|
-
` : `Dev server: dndev dev
|
|
19818
|
-
`) + `AI setup: dndev agent (re-configure MCP if needed)`,
|
|
19837
|
+
` + (anyAppNeedsBackend ? `Dev server: dndev dev | With emulators: dndev emu` : `Dev server: dndev dev`),
|
|
19819
19838
|
"\u{1F4CB} Next Steps"
|
|
19820
19839
|
);
|
|
19821
19840
|
} catch (error2) {
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ description: Extract requirements and generate complete HLD through conversation
|
|
|
6
6
|
|
|
7
7
|
**⚠️ MODE CHECK:** This command is for **Consumer App Development** only.
|
|
8
8
|
|
|
9
|
-
**If you're in the framework monorepo (
|
|
9
|
+
**If you're in the framework monorepo (this repo):**
|
|
10
10
|
- ❌ **DO NOT use `/brainstorm`** - framework dev doesn't need requirements extraction
|
|
11
11
|
- ✅ See [Modes Guide](https://github.com/donotdev/framework/blob/main/docs/development/MODES.md) for framework dev workflow
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ description: Two-agent workflow: Prompt Engineer → Coder (AFTER /design)
|
|
|
6
6
|
|
|
7
7
|
**⚠️ MODE CHECK:** This command is for **Consumer App Development** only.
|
|
8
8
|
|
|
9
|
-
**If you're in the framework monorepo (
|
|
9
|
+
**If you're in the framework monorepo (this repo):**
|
|
10
10
|
- ❌ **DO NOT use `/build`** - code directly in `packages/*/src/`
|
|
11
11
|
- ✅ Use direct coding following Architecture Hub patterns
|
|
12
12
|
- ✅ See [Modes Guide](https://github.com/donotdev/framework/blob/main/docs/development/MODES.md) for framework dev workflow
|
|
@@ -6,7 +6,7 @@ description: Design workflow: Architect → Design Document (BEFORE /build)
|
|
|
6
6
|
|
|
7
7
|
**⚠️ MODE CHECK:** This command is for **Consumer App Development** only.
|
|
8
8
|
|
|
9
|
-
**If you're in the framework monorepo (
|
|
9
|
+
**If you're in the framework monorepo (this repo):**
|
|
10
10
|
- ❌ **DO NOT use `/design`** - design directly, then code in `packages/*/src/`
|
|
11
11
|
- ✅ Use Architecture Hub + Development Hub for framework design patterns
|
|
12
12
|
- ✅ See [Modes Guide](https://github.com/donotdev/framework/blob/main/docs/development/MODES.md) for framework dev workflow
|
|
@@ -6,7 +6,7 @@ description: Generate tests, firestore rules, CI/CD, config, fix bugs, i18n (Pha
|
|
|
6
6
|
|
|
7
7
|
**⚠️ MODE CHECK:** This command is for **Consumer App Development** only.
|
|
8
8
|
|
|
9
|
-
**If you're in the framework monorepo (
|
|
9
|
+
**If you're in the framework monorepo (this repo):**
|
|
10
10
|
- ❌ **DO NOT use `/polish`** - framework dev doesn't use this workflow
|
|
11
11
|
- ✅ See [Modes Guide](https://github.com/donotdev/framework/blob/main/docs/development/MODES.md) for framework dev workflow
|
|
12
12
|
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
## What To Do Right Now
|
|
6
6
|
|
|
7
|
-
1. **
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
1. **Verify MCP is working.** Try calling `list_features()`. If it works, you're good. If not:
|
|
8
|
+
- **Cursor:** Settings → Tools & MCP → toggle "donotdev" ON. MCP only works in Composer mode (`Cmd/Ctrl+I`).
|
|
9
|
+
- **Claude Code / Windsurf:** Auto-connects from `.mcp.json`. If broken, check `bun` is in PATH.
|
|
10
|
+
2. **Check environment setup.** Ask the user: "Have you run `bun install`? Run `dndev dev` and open the app — the homepage has setup steps for Git, Firebase, and .env."
|
|
11
|
+
3. Call `start_phase(0)` — begin **Phase 0: BRAINSTORM**
|
|
10
12
|
4. Follow each phase in order. Do not skip phases.
|
|
11
13
|
|
|
12
14
|
## Environment Variables — Where They Go
|
|
@@ -73,21 +75,25 @@ node_modules/@donotdev/core/dist/index.d.ts → Core utilities
|
|
|
73
75
|
|
|
74
76
|
## Supported IDEs
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
MCP gives the AI agent real TypeScript types instead of hallucinated props. Config files are auto-created by `dndev init`.
|
|
77
79
|
|
|
78
|
-
| IDE |
|
|
79
|
-
|
|
80
|
-
| **
|
|
81
|
-
| **
|
|
82
|
-
| **
|
|
83
|
-
| **
|
|
84
|
-
| **Gemini** | Full | `.gemini/settings.json` (auto-configured) |
|
|
80
|
+
| IDE | Config | Setup |
|
|
81
|
+
|-----|--------|-------|
|
|
82
|
+
| **Claude Code** | `.mcp.json` | Auto-connects. Nothing to do. |
|
|
83
|
+
| **Windsurf** | `.mcp.json` | Auto-connects. Nothing to do. |
|
|
84
|
+
| **Cursor** | `.cursor/mcp.json` | Settings → Tools & MCP → toggle "donotdev" ON. **MCP only works in Composer mode** (`Cmd/Ctrl+I`). |
|
|
85
|
+
| **Gemini CLI** | `.gemini/settings.json` | Auto-connects. Nothing to do. |
|
|
85
86
|
|
|
86
|
-
**
|
|
87
|
+
**If MCP tools aren't available**, guide the user:
|
|
88
|
+
1. Check `bun` is in PATH (`which bun`)
|
|
89
|
+
2. **Cursor:** Must be in Composer mode (`Cmd/Ctrl+I`) and server toggled ON
|
|
90
|
+
3. Check MCP logs: `Cmd/Ctrl+Shift+U` → Output → "MCP Logs"
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
**Without MCP (ChatGPT, Copilot, etc.):** Read blueprints from `guides/wai-way/blueprints/` and types from `node_modules/@donotdev/*/dist/*.d.ts`. You lose symbol tracking and convention enforcement.
|
|
89
93
|
|
|
90
|
-
MCP
|
|
94
|
+
## MCP Tools (13 — Pre-Configured)
|
|
95
|
+
|
|
96
|
+
MCP config files are auto-created in `.mcp.json` / `.cursor/mcp.json` / `.gemini/settings.json`. **You must enable the server in your IDE settings** (see "Supported IDEs" above). Once enabled, your IDE connects automatically.
|
|
91
97
|
|
|
92
98
|
| Tool | What It Does |
|
|
93
99
|
|------|-------------|
|
|
@@ -99,7 +105,12 @@ MCP is configured in `.mcp.json` / `.cursor/mcp.json` / `.gemini/settings.json`.
|
|
|
99
105
|
| `get_guide("CRUD")` | Fetch framework setup guides |
|
|
100
106
|
| `get_guideline("styling:colors")` | Fetch architecture guidelines (supports sections) |
|
|
101
107
|
| `search_framework("keyword")` | Search across all guides and type definitions |
|
|
108
|
+
| `list_features()` | List all framework packages with summaries |
|
|
102
109
|
| `record_lesson("text")` | Save to project memory (returned on next start_phase) |
|
|
110
|
+
| `init_implementation({ from_spec: true })` | Create `.dndev/implementation.md` to track progress |
|
|
111
|
+
| `update_progress({ item: "...", done: true })` | Tick/untick items in implementation checklist |
|
|
112
|
+
| `get_progress()` | Read implementation progress stats |
|
|
113
|
+
| `get_project_history()` | Get captain's log with full session history |
|
|
103
114
|
|
|
104
115
|
## Convention Enforcement
|
|
105
116
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- **Creating with framework** (Mode 3): Build new app features
|
|
18
18
|
- **Tweaking framework app** (Mode 4): Modify existing app features
|
|
19
19
|
|
|
20
|
-
**CLI:** `dndev` (public CLI, installed globally)
|
|
20
|
+
**CLI:** `dndev` (public CLI, installed globally via `npm install -g @donotdev/cli`)
|
|
21
21
|
|
|
22
22
|
**Workflow:**
|
|
23
23
|
1. `/design [requirement]` → Architect designs solution
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
**⚠️ IMPORTANT:**
|
|
30
30
|
- Use ONLY published `@donotdev/*` packages
|
|
31
31
|
- Cannot modify framework internals
|
|
32
|
-
- If framework needs changes, work in monorepo (
|
|
32
|
+
- If framework needs changes, work in the framework monorepo (this repo)
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
@@ -116,13 +116,19 @@ If MCP tools unavailable → STOP and tell user to enable MCP.
|
|
|
116
116
|
- `get_guideline` — fetch architecture guidelines
|
|
117
117
|
- `search_framework` — search across all guides and symbols
|
|
118
118
|
|
|
119
|
+
## Project Args & Gotchas
|
|
120
|
+
|
|
121
|
+
- **`.dndev/args.json`** — Per-project config (platform, strictness, features, region). All features ON by default. Phase 0 narrows down. Edit `strictness` to control validation: `enforced` (default) | `warnings` | `permissive`.
|
|
122
|
+
- **`guides/dndev/GOTCHAS.md`** — Common mistakes, phase-tagged. Read directly or loaded by MCP `start_phase()`.
|
|
123
|
+
- **Without MCP:** Both files are plain JSON/markdown — any agent reads them directly. MCP automates filtering + enforcement but is not required.
|
|
124
|
+
|
|
119
125
|
## WAI-WAY Workflow
|
|
120
126
|
|
|
121
127
|
**Read `AI.md` at the project root for the full workflow.**
|
|
122
128
|
|
|
123
129
|
For each phase (0=BRAINSTORM, 1=SCAFFOLD, 2=ENTITIES, 3=COMPOSE, 4=CONFIGURE):
|
|
124
130
|
|
|
125
|
-
1. `mcp:start_phase(N)` — returns blueprint, context, and
|
|
131
|
+
1. `mcp:start_phase(N)` — returns blueprint, context, lessons, project args, and phase-relevant gotchas
|
|
126
132
|
2. Work — follow blueprint, call `lookup_symbol` before using any component
|
|
127
|
-
3. `mcp:complete_phase({ files })` — validates conventions + symbol usage, submits for review
|
|
133
|
+
3. `mcp:complete_phase({ files })` — validates conventions + symbol usage (respects `strictness`), submits for review
|
|
128
134
|
4. `mcp:approve_phase()` — user approves, phase is done
|
|
@@ -63,4 +63,38 @@ Check that the user has completed environment setup:
|
|
|
63
63
|
|
|
64
64
|
If not, coach them: "Run `dndev firebase:setup` first, then follow the prompts." See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md).
|
|
65
65
|
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Project Args (`.dndev/args.json`)
|
|
69
|
+
|
|
70
|
+
Generated by `dndev init`. All features ON by default — Phase 0 narrows down based on what the user actually needs.
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"platform": "firebase",
|
|
75
|
+
"strictness": "enforced",
|
|
76
|
+
"features": ["crud", "auth", "i18n", "billing", "oauth", "functions"],
|
|
77
|
+
"region": "europe-west1"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
| Field | Values | Effect |
|
|
82
|
+
|-------|--------|--------|
|
|
83
|
+
| `platform` | `firebase`, `vercel` | Derived from builder choice |
|
|
84
|
+
| `strictness` | `enforced`, `warnings`, `permissive` | `enforced` = blocks `complete_phase` on convention violations. `warnings` = reports but allows. `permissive` = skips checks. |
|
|
85
|
+
| `features` | `crud`, `auth`, `i18n`, `billing`, `oauth`, `functions` | Filters gotchas — remove features the project doesn't use to reduce noise |
|
|
86
|
+
| `region` | any GCP region | Informational, shown in `start_phase` context |
|
|
87
|
+
|
|
88
|
+
`start_phase()` returns project args + phase-relevant gotchas automatically. `complete_phase()` respects `strictness`.
|
|
89
|
+
|
|
90
|
+
**Without MCP:** `args.json` and `GOTCHAS.md` are plain files. Any agent can read them directly.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Gotchas (`guides/dndev/GOTCHAS.md`)
|
|
95
|
+
|
|
96
|
+
Common mistakes, phase-tagged. `start_phase(N)` automatically filters and returns only the gotchas relevant to phase N and your enabled features. Read the full file for reference: [GOTCHAS.md](../guides/dndev/GOTCHAS.md).
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
66
100
|
**Starting:** Call `list_features()` first, then `get_phase_status()` to see where you are, then `start_phase(0)` to begin.
|