@descix/cli 1.0.16 → 1.0.18
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/agent-assets/guides/README.md +2 -1
- package/agent-assets/guides/dynamic-site-pattern.md +6 -10
- package/agent-assets/guides/knowledge-only-pattern.md +12 -11
- package/agent-assets/guides/microservice-pattern.md +13 -16
- package/agent-assets/guides/static-site-pattern.md +6 -7
- package/agent-assets/instructions/app-asset-validation.md +61 -59
- package/agent-assets/instructions/onboarding-flow.md +57 -73
- package/agent-assets/instructions/standard-folder-structure.md +39 -36
- package/agent-assets/reference/app-creation.md +27 -33
- package/agent-assets/reference/architecture.md +85 -148
- package/agent-assets/reference/local-dev.md +5 -83
- package/agent-assets/reference/mcp-integration.md +32 -39
- package/agent-assets/reference/workspace-config.md +9 -10
- package/bin/descix.js +30 -133
- package/lib/commands/appInit.js +154 -0
- package/lib/commands/init.js +14 -54
- package/lib/help-guard.js +85 -0
- package/lib/verb-invokes.generated.json +5 -1
- package/package.json +1 -1
- package/templates/agent-claude.md +14 -9
- package/templates/agent-cline.md +7 -7
- package/templates/agent-copilot.md +7 -7
- package/templates/agent-cursor.md +7 -7
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A COMMAND THAT DOES NOT EXIST MUST NOT APPEAR TO HAVE HELP.
|
|
3
|
+
*
|
|
4
|
+
* Commander resolves `--help` before it resolves the command, so `descix update --help` printed the
|
|
5
|
+
* TOP-LEVEL help and exited 0 — indistinguishable, to a reader or a script, from a real verb with
|
|
6
|
+
* help. `descix update` alone correctly says `error: unknown command 'update'`.
|
|
7
|
+
*
|
|
8
|
+
* That exit 0 is not only wrong, it TAUGHT something wrong: the daita-sdk docs tell readers that
|
|
9
|
+
* `site upload --help` "silently prints top-level help" and to use `help <sub>` instead. It does no
|
|
10
|
+
* such thing for a real command; the author had been probing a command that did not exist (devx
|
|
11
|
+
* review 2026-09-19, I2 → S5).
|
|
12
|
+
*
|
|
13
|
+
* This guard runs ONLY when a help flag is present, so every other path keeps Commander's own
|
|
14
|
+
* behaviour (it already exits non-zero for an unknown command without `--help`).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const HELP_FLAGS = new Set(['-h', '--help']);
|
|
18
|
+
|
|
19
|
+
/** Does this option consume the next argv token as its value? */
|
|
20
|
+
function takesValue(option) {
|
|
21
|
+
return Boolean(option && option.required);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function findOption(command, token) {
|
|
25
|
+
const name = token.split('=')[0];
|
|
26
|
+
return command.options.find((o) => o.short === name || o.long === name);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function findSubcommand(command, token) {
|
|
30
|
+
return command.commands.find(
|
|
31
|
+
(c) => c.name() === token || (typeof c.aliases === 'function' && c.aliases().includes(token)),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Walk argv down the command tree and return the first token that should name a subcommand but does
|
|
37
|
+
* not. Returns null when every command token resolves — including when a command takes positional
|
|
38
|
+
* arguments (a command with no subcommands ends the walk, so `descix chat hello` is not "unknown").
|
|
39
|
+
*
|
|
40
|
+
* @param {import('commander').Command} program
|
|
41
|
+
* @param {string[]} argv arguments after the node binary and script (process.argv.slice(2))
|
|
42
|
+
* @returns {{token: string, parent: import('commander').Command}|null}
|
|
43
|
+
*/
|
|
44
|
+
export function findUnknownCommand(program, argv) {
|
|
45
|
+
let command = program;
|
|
46
|
+
for (let i = 0; i < argv.length; i++) {
|
|
47
|
+
const token = argv[i];
|
|
48
|
+
if (token === '--') break;
|
|
49
|
+
if (token.startsWith('-')) {
|
|
50
|
+
if (takesValue(findOption(command, token)) && !token.includes('=')) i++;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// A command with no subcommands takes positional arguments from here on.
|
|
54
|
+
if (command.commands.length === 0) break;
|
|
55
|
+
const sub = findSubcommand(command, token);
|
|
56
|
+
if (!sub) return { token, parent: command };
|
|
57
|
+
command = sub;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The command names `parent` actually has, for the "did you mean" line. */
|
|
63
|
+
function nameList(parent) {
|
|
64
|
+
return parent.commands.map((c) => c.name()).sort();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* When argv asks for help on a command that does not exist, refuse by name and exit 1.
|
|
69
|
+
*
|
|
70
|
+
* @param {import('commander').Command} program
|
|
71
|
+
* @param {string[]} argv
|
|
72
|
+
* @param {{ error: (msg: string) => void, exit: (code: number) => void }} io
|
|
73
|
+
*/
|
|
74
|
+
export function assertKnownCommandForHelp(program, argv, io = { error: console.error, exit: process.exit }) {
|
|
75
|
+
if (!argv.some((a) => HELP_FLAGS.has(a))) return;
|
|
76
|
+
const unknown = findUnknownCommand(program, argv);
|
|
77
|
+
if (!unknown) return;
|
|
78
|
+
|
|
79
|
+
const path = [];
|
|
80
|
+
for (let c = unknown.parent; c && c.parent; c = c.parent) path.unshift(c.name());
|
|
81
|
+
const where = path.length ? `'descix ${path.join(' ')}'` : 'descix';
|
|
82
|
+
io.error(`error: unknown command '${unknown.token}'`);
|
|
83
|
+
io.error(`${where} has: ${nameList(unknown.parent).join(', ')}`);
|
|
84
|
+
io.exit(1);
|
|
85
|
+
}
|
|
@@ -190,11 +190,15 @@
|
|
|
190
190
|
"fetch_my_purchases"
|
|
191
191
|
],
|
|
192
192
|
"quickstart": [
|
|
193
|
+
"create_app_for_community",
|
|
193
194
|
"device_check_status",
|
|
194
195
|
"device_request_login",
|
|
195
196
|
"find_communities",
|
|
197
|
+
"get_product_context",
|
|
198
|
+
"init_git_mode_kb",
|
|
196
199
|
"resolve_invite",
|
|
197
|
-
"sync_auto_purchases"
|
|
200
|
+
"sync_auto_purchases",
|
|
201
|
+
"update_community_metadata"
|
|
198
202
|
],
|
|
199
203
|
"reconnect": [
|
|
200
204
|
"reconnect_by_wallet"
|
package/package.json
CHANGED
|
@@ -84,15 +84,18 @@ Use `find_communities` and `list_apps_for_community` to show options, then ask:
|
|
|
84
84
|
> "Which community and app should this project target?"
|
|
85
85
|
|
|
86
86
|
### Checkpoint 3: Environment
|
|
87
|
-
> "Should this
|
|
87
|
+
> "Should this app be built against DEV (https://dev.descix.net) or production?"
|
|
88
|
+
|
|
89
|
+
Pin the choice before anything else; every later command reads it from the workspace.
|
|
88
90
|
|
|
89
91
|
### Canonical Setup Commands (run in terminal after checkpoints)
|
|
90
92
|
```bash
|
|
91
|
-
descix
|
|
92
|
-
descix
|
|
93
|
-
descix init -
|
|
94
|
-
descix app init -a <app> -c <community> # register app on platform
|
|
93
|
+
descix --env dev config init # pin the environment (omit --env dev for production)
|
|
94
|
+
descix login # sign in
|
|
95
|
+
descix app init -a <name> -c <community> # create the app; the platform issues its id
|
|
95
96
|
```
|
|
97
|
+
`app init` prints the app id the platform issued (with `-c` it is `<community>-<name>`). Use that
|
|
98
|
+
id, not the name, as `-a` in every later command.
|
|
96
99
|
|
|
97
100
|
### Checkpoint 4: Content Strategy
|
|
98
101
|
> "Should I create a starter KB doc now, or wait for your domain docs?"
|
|
@@ -223,8 +226,9 @@ const user = await powch.auth();
|
|
|
223
226
|
### KB Integration
|
|
224
227
|
|
|
225
228
|
If docs already exist (`docs/`, `README.md`, SDK reference files):
|
|
226
|
-
-
|
|
227
|
-
|
|
229
|
+
- Name the docs' folder as a source in a corpus manifest (`.descix/manifests/<KB>.json`), then run
|
|
230
|
+
`descix kb corpus sync`. The docs stay exactly where they are — there is no copy step and no
|
|
231
|
+
required KB folder.
|
|
228
232
|
- Ask: "I see docs in `docs/`. Want me to use those as your knowledge base?"
|
|
229
233
|
|
|
230
234
|
### Decision Guide
|
|
@@ -233,7 +237,7 @@ If docs already exist (`docs/`, `README.md`, SDK reference files):
|
|
|
233
237
|
|-----------------|---------------|-------------|
|
|
234
238
|
| HTML/JS app with `index.html` | Serve as-is, add DeSciXAppSDK.js | Use any `docs/` or `*.md` files |
|
|
235
239
|
| React/Vite app | Wrap root in `<AppShell>` | Use `docs/` or README |
|
|
236
|
-
| SDK package with docs + demo | Serve the SDK's demo page |
|
|
240
|
+
| SDK package with docs + demo | Serve the SDK's demo page | Name docs folder in a corpus manifest |
|
|
237
241
|
| Docs only (no frontend) | Skip or create minimal site | Docs ARE the KB |
|
|
238
242
|
| Empty repo | Scaffold from scratch | Create starter KB doc |
|
|
239
243
|
|
|
@@ -241,7 +245,8 @@ If docs already exist (`docs/`, `README.md`, SDK reference files):
|
|
|
241
245
|
|
|
242
246
|
Every app has three parts:
|
|
243
247
|
- `site/` — Frontend (any framework: React, VitePress, vanilla HTML)
|
|
244
|
-
- `
|
|
248
|
+
- A corpus manifest (`.descix/manifests/<KB>.json`) — names the git-tracked docs `descix kb corpus
|
|
249
|
+
sync` publishes; there is no required KB folder
|
|
245
250
|
- `microservice/` — Backend service (optional)
|
|
246
251
|
|
|
247
252
|
## App Context
|
package/templates/agent-cline.md
CHANGED
|
@@ -56,15 +56,15 @@ Ask the user at each checkpoint — don't assume:
|
|
|
56
56
|
|
|
57
57
|
1. **Objective:** "Explore existing apps or build something new?"
|
|
58
58
|
2. **Community/App:** Use `find_communities` + `list_apps_for_community`, then ask which to target
|
|
59
|
-
3. **Environment:** "
|
|
59
|
+
3. **Environment:** "Build against DEV (https://dev.descix.net) or production?" Pin it first.
|
|
60
60
|
|
|
61
61
|
Canonical setup commands:
|
|
62
62
|
```bash
|
|
63
|
-
descix
|
|
64
|
-
descix
|
|
65
|
-
descix init -
|
|
66
|
-
descix app init -a <app> -c <community> # register app on platform
|
|
63
|
+
descix --env dev config init # pin the environment (omit --env dev for production)
|
|
64
|
+
descix login # sign in
|
|
65
|
+
descix app init -a <name> -c <community> # create the app; the platform issues its id
|
|
67
66
|
```
|
|
67
|
+
`app init` prints the issued id (`<community>-<name>` with `-c`); use it as `-a` from then on.
|
|
68
68
|
|
|
69
69
|
4. **Content strategy:** "Create starter KB now or wait for your docs?"
|
|
70
70
|
5. **Frontend scope:** "Plain HTML or a framework (React, VitePress)?"
|
|
@@ -165,13 +165,13 @@ unverified step — see `.descix/sdk-assets/reference/local-dev.md` §3.3.
|
|
|
165
165
|
`DeSciXAppSDK.js` is GENERATED (from `descix-app-sdk/templates/DeSciXAppSDK.template.js`, with a `--check` drift gate) — copy it in, never hand-edit it; a local patch forks the bridge and stops inheriting its fixes.
|
|
166
166
|
- **React/Vite app:** Wrap root in `<AppShell appId="{{appId}}">` from `@descix/app-sdk/AppShell`.
|
|
167
167
|
- **Auth only (no DeSciX UI):** Use `PowchClient` from `@descix/app-sdk/powch-client`.
|
|
168
|
-
- **Existing docs:**
|
|
168
|
+
- **Existing docs:** Name the docs' folder as a source in a corpus manifest (`.descix/manifests/<KB>.json`), then `descix kb corpus sync`. Docs stay where they are — no copy step.
|
|
169
169
|
- **Empty repo:** Scaffold from scratch.
|
|
170
170
|
|
|
171
171
|
## App Structure
|
|
172
172
|
|
|
173
173
|
- `site/` — Frontend (any framework)
|
|
174
|
-
- `
|
|
174
|
+
- A corpus manifest (`.descix/manifests/<KB>.json`) — names the git-tracked docs `descix kb corpus sync` publishes (no required folder)
|
|
175
175
|
- `microservice/` — Backend service (optional)
|
|
176
176
|
|
|
177
177
|
## Context
|
|
@@ -56,15 +56,15 @@ Ask the user at each checkpoint — don't assume:
|
|
|
56
56
|
|
|
57
57
|
1. **Objective:** "Explore existing apps or build something new?"
|
|
58
58
|
2. **Community/App:** Use `find_communities` + `list_apps_for_community`, then ask which to target
|
|
59
|
-
3. **Environment:** "
|
|
59
|
+
3. **Environment:** "Build against DEV (https://dev.descix.net) or production?" Pin it first.
|
|
60
60
|
|
|
61
61
|
Canonical setup commands:
|
|
62
62
|
```bash
|
|
63
|
-
descix
|
|
64
|
-
descix
|
|
65
|
-
descix init -
|
|
66
|
-
descix app init -a <app> -c <community> # register app on platform
|
|
63
|
+
descix --env dev config init # pin the environment (omit --env dev for production)
|
|
64
|
+
descix login # sign in
|
|
65
|
+
descix app init -a <name> -c <community> # create the app; the platform issues its id
|
|
67
66
|
```
|
|
67
|
+
`app init` prints the issued id (`<community>-<name>` with `-c`); use it as `-a` from then on.
|
|
68
68
|
|
|
69
69
|
4. **Content strategy:** "Create starter KB now or wait for your docs?"
|
|
70
70
|
5. **Frontend scope:** "Plain HTML or a framework (React, VitePress)?"
|
|
@@ -165,13 +165,13 @@ unverified step — see `.descix/sdk-assets/reference/local-dev.md` §3.3.
|
|
|
165
165
|
`DeSciXAppSDK.js` is GENERATED (from `descix-app-sdk/templates/DeSciXAppSDK.template.js`, with a `--check` drift gate) — copy it in, never hand-edit it; a local patch forks the bridge and stops inheriting its fixes.
|
|
166
166
|
- **React/Vite app:** Wrap root in `<AppShell appId="{{appId}}">` from `@descix/app-sdk/AppShell`.
|
|
167
167
|
- **Auth only (no DeSciX UI):** Use `PowchClient` from `@descix/app-sdk/powch-client`.
|
|
168
|
-
- **Existing docs:**
|
|
168
|
+
- **Existing docs:** Name the docs' folder as a source in a corpus manifest (`.descix/manifests/<KB>.json`), then `descix kb corpus sync`. Docs stay where they are — no copy step.
|
|
169
169
|
- **Empty repo:** Scaffold from scratch.
|
|
170
170
|
|
|
171
171
|
## App Structure
|
|
172
172
|
|
|
173
173
|
- `site/` — Frontend (any framework)
|
|
174
|
-
- `
|
|
174
|
+
- A corpus manifest (`.descix/manifests/<KB>.json`) — names the git-tracked docs `descix kb corpus sync` publishes (no required folder)
|
|
175
175
|
- `microservice/` — Backend service (optional)
|
|
176
176
|
|
|
177
177
|
## Context
|
|
@@ -56,15 +56,15 @@ Ask the user at each checkpoint — don't assume:
|
|
|
56
56
|
|
|
57
57
|
1. **Objective:** "Explore existing apps or build something new?"
|
|
58
58
|
2. **Community/App:** Use `find_communities` + `list_apps_for_community`, then ask which to target
|
|
59
|
-
3. **Environment:** "
|
|
59
|
+
3. **Environment:** "Build against DEV (https://dev.descix.net) or production?" Pin it first.
|
|
60
60
|
|
|
61
61
|
Canonical setup commands:
|
|
62
62
|
```bash
|
|
63
|
-
descix
|
|
64
|
-
descix
|
|
65
|
-
descix init -
|
|
66
|
-
descix app init -a <app> -c <community> # register app on platform
|
|
63
|
+
descix --env dev config init # pin the environment (omit --env dev for production)
|
|
64
|
+
descix login # sign in
|
|
65
|
+
descix app init -a <name> -c <community> # create the app; the platform issues its id
|
|
67
66
|
```
|
|
67
|
+
`app init` prints the issued id (`<community>-<name>` with `-c`); use it as `-a` from then on.
|
|
68
68
|
|
|
69
69
|
4. **Content strategy:** "Create starter KB now or wait for your docs?"
|
|
70
70
|
5. **Frontend scope:** "Plain HTML or a framework (React, VitePress)?"
|
|
@@ -165,13 +165,13 @@ unverified step — see `.descix/sdk-assets/reference/local-dev.md` §3.3.
|
|
|
165
165
|
`DeSciXAppSDK.js` is GENERATED (from `descix-app-sdk/templates/DeSciXAppSDK.template.js`, with a `--check` drift gate) — copy it in, never hand-edit it; a local patch forks the bridge and stops inheriting its fixes.
|
|
166
166
|
- **React/Vite app:** Wrap root in `<AppShell appId="{{appId}}">` from `@descix/app-sdk/AppShell`.
|
|
167
167
|
- **Auth only (no DeSciX UI):** Use `PowchClient` from `@descix/app-sdk/powch-client`.
|
|
168
|
-
- **Existing docs:**
|
|
168
|
+
- **Existing docs:** Name the docs' folder as a source in a corpus manifest (`.descix/manifests/<KB>.json`), then `descix kb corpus sync`. Docs stay where they are — no copy step.
|
|
169
169
|
- **Empty repo:** Scaffold from scratch.
|
|
170
170
|
|
|
171
171
|
## App Structure
|
|
172
172
|
|
|
173
173
|
- `site/` — Frontend (any framework)
|
|
174
|
-
- `
|
|
174
|
+
- A corpus manifest (`.descix/manifests/<KB>.json`) — names the git-tracked docs `descix kb corpus sync` publishes (no required folder)
|
|
175
175
|
- `microservice/` — Backend service (optional)
|
|
176
176
|
|
|
177
177
|
## Context
|