@tetherto/mdk-cli 0.0.0-stage → 0.12.1
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/LICENSE +202 -0
- package/README.md +446 -2
- package/dist/commands/add.js +61 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/agent.js +42 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/create.js +261 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/inspect.js +171 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/meta.js +12 -0
- package/dist/commands/meta.js.map +1 -0
- package/dist/commands/onboard.js +447 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/run.js +203 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/validate.js +125 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/add-package.js +148 -0
- package/dist/lib/add-package.js.map +1 -0
- package/dist/lib/app-package.js +182 -0
- package/dist/lib/app-package.js.map +1 -0
- package/dist/lib/app-scaffold.js +221 -0
- package/dist/lib/app-scaffold.js.map +1 -0
- package/dist/lib/app-ui-check.js +178 -0
- package/dist/lib/app-ui-check.js.map +1 -0
- package/dist/lib/app-ui-runner.js +122 -0
- package/dist/lib/app-ui-runner.js.map +1 -0
- package/dist/lib/catalog.js +69 -0
- package/dist/lib/catalog.js.map +1 -0
- package/dist/lib/checkout.js +14 -0
- package/dist/lib/checkout.js.map +1 -0
- package/dist/lib/dashboard-apps.js +71 -0
- package/dist/lib/dashboard-apps.js.map +1 -0
- package/dist/lib/dashboard.js +318 -0
- package/dist/lib/dashboard.js.map +1 -0
- package/dist/lib/detect.js +38 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/env-file.js +57 -0
- package/dist/lib/env-file.js.map +1 -0
- package/dist/lib/fetch-template.js +33 -0
- package/dist/lib/fetch-template.js.map +1 -0
- package/dist/lib/help.js +22 -0
- package/dist/lib/help.js.map +1 -0
- package/dist/lib/names.js +36 -0
- package/dist/lib/names.js.map +1 -0
- package/dist/lib/npm.js +113 -0
- package/dist/lib/npm.js.map +1 -0
- package/dist/lib/package-source.js +76 -0
- package/dist/lib/package-source.js.map +1 -0
- package/dist/lib/pkg.js +5 -0
- package/dist/lib/pkg.js.map +1 -0
- package/dist/lib/plugin-setup.js +204 -0
- package/dist/lib/plugin-setup.js.map +1 -0
- package/dist/lib/ports.js +31 -0
- package/dist/lib/ports.js.map +1 -0
- package/dist/lib/project.js +297 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/run-lock.js +188 -0
- package/dist/lib/run-lock.js.map +1 -0
- package/dist/lib/runtime.js +683 -0
- package/dist/lib/runtime.js.map +1 -0
- package/dist/lib/scaffold.js +82 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/shutdown.js +53 -0
- package/dist/lib/shutdown.js.map +1 -0
- package/dist/lib/skill.js +38 -0
- package/dist/lib/skill.js.map +1 -0
- package/dist/lib/spec.js +375 -0
- package/dist/lib/spec.js.map +1 -0
- package/dist/lib/status.js +245 -0
- package/dist/lib/status.js.map +1 -0
- package/dist/lib/theme.js +50 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/worker-package.js +74 -0
- package/dist/lib/worker-package.js.map +1 -0
- package/dist/lib/worker-scaffold.js +122 -0
- package/dist/lib/worker-scaffold.js.map +1 -0
- package/dist/lib/worker-smoke.js +243 -0
- package/dist/lib/worker-smoke.js.map +1 -0
- package/dist/program.js +58 -0
- package/dist/program.js.map +1 -0
- package/package.json +57 -4
- package/templates/app/README.md +66 -0
- package/templates/app/mdk-app.yaml +10 -0
- package/templates/app/package.json +17 -0
- package/templates/app/plugin/controllers/summary.js +36 -0
- package/templates/app/plugin/lib/client.js +11 -0
- package/templates/app/plugin/mdk-plugin.json +16 -0
- package/templates/app-ui/tsconfig.json +29 -0
- package/templates/app-ui/ui-src/components/summary-panel.tsx +24 -0
- package/templates/app-ui/ui-src/data/summary.ts +18 -0
- package/templates/app-ui/ui-src/hooks/use-summary.ts +54 -0
- package/templates/app-ui/ui-src/index.tsx +15 -0
- package/templates/app-ui/ui-src/pages/overview-page.tsx +18 -0
- package/templates/app-ui/ui-src/styles.css +13 -0
- package/templates/app-ui/ui-src/styles.d.ts +3 -0
- package/templates/app-ui/ui-src/vite.config.ts +26 -0
- package/templates/worker/README.md +93 -0
- package/templates/worker/mdk-contract.json +26 -0
- package/templates/worker/mock/server.js +93 -0
- package/templates/worker/package.json +23 -0
- package/templates/worker/smoke.config.js +31 -0
- package/templates/worker/src/client.js +47 -0
- package/templates/worker/src/commands/reboot.js +5 -0
- package/templates/worker/src/commands/set-power-mode.js +10 -0
- package/templates/worker/src/telemetry/hashrate-rt.js +5 -0
- package/templates/worker/src/telemetry/power-mode.js +5 -0
- package/templates/worker/src/telemetry/power.js +5 -0
- package/templates/worker/src/telemetry/temperature.js +5 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright 2026 Tether
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,447 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@tetherto/mdk-cli`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `mdk` command-line tool. Built with Commander.js and `@clack/prompts`; the implemented commands are:
|
|
4
|
+
`mdk onboard` (a guided wizard that detects the environment, asks the setup
|
|
5
|
+
questions and writes `mdk.yaml`), `mdk create` (`worker`, `app`, `dashboard`
|
|
6
|
+
— each self-registering in the spec), `mdk add` (`app`, `worker` from npm or
|
|
7
|
+
GitHub), `mdk validate` (`app`, `worker`), `mdk run` (boots the stack from the
|
|
8
|
+
spec), `mdk status` (environment + component health) and `mdk skill add`
|
|
9
|
+
(installs the `@tetherto/mdk-skill` suite).
|
|
10
|
+
|
|
11
|
+
## Stack
|
|
12
|
+
|
|
13
|
+
- **Runtime:** Node.js >= 24, TypeScript, ESM
|
|
14
|
+
- **Framework:** [Commander.js](https://github.com/tj/commander.js) for the
|
|
15
|
+
command tree, parsing, and help; `[@clack/prompts](https://github.com/bombshell-dev/clack)`
|
|
16
|
+
for interactive wizard steps
|
|
17
|
+
- The `mdk` binary is exposed via the package.json `bin` field pointing at
|
|
18
|
+
`dist/index.js` (which carries a `#!/usr/bin/env node` shebang)
|
|
19
|
+
|
|
20
|
+
## Project layout
|
|
21
|
+
|
|
22
|
+
`onboard` and `create` emit one role-grouped layout, so a path in `mdk.yaml` says
|
|
23
|
+
what it is:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
mdk.yaml the stack spec
|
|
27
|
+
package.json private root manifest; links workers/ and apps/<name>/ by file: deps
|
|
28
|
+
README.md generated: layout + the run commands
|
|
29
|
+
workers/<name>/ worker plugins (mdk create worker)
|
|
30
|
+
apps/<name>/ apps (mdk create app)
|
|
31
|
+
apps/dashboard/ the UI dashboard (mdk create dashboard)
|
|
32
|
+
.mdk/ runtime state written by `mdk run` — gitignored, disposable
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Workers and apps are linked from the root manifest by relative `file:`
|
|
36
|
+
dependencies because the runtime resolves them out of the project's
|
|
37
|
+
`node_modules` — so `create worker` and `create app` run `npm install` **at the
|
|
38
|
+
project root**, not in the package. The dashboard is deliberately not linked: it
|
|
39
|
+
links the MDK UI packages by `file:` path, and hoisting its React through the root
|
|
40
|
+
alongside those links invites a duplicate-React bug, so it installs in place.
|
|
41
|
+
|
|
42
|
+
`.mdk/` gives each component its own data root (`kernel/`, `gateway/`, `mcp/`,
|
|
43
|
+
`workers/<name>/`, `apps/<name>/`) plus the files components in other processes
|
|
44
|
+
find each other by: `kernel.key` (read by the Gateway, apps and the MCP server),
|
|
45
|
+
`keys/` (written by Workers, watched by the Kernel), `gateway.key` (the key app
|
|
46
|
+
runtimes accept), `trusted-keys/` (every caller's key, admitted by the Kernel
|
|
47
|
+
and Workers) and `run/` (one lock per running Kernel, Worker and app). Delete
|
|
48
|
+
the whole directory to reset a stack.
|
|
49
|
+
|
|
50
|
+
## Develop
|
|
51
|
+
|
|
52
|
+
Install once from the packages workspace root (this links `@tetherto/mdk-skill`
|
|
53
|
+
into the CLI), then work from this package:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install --prefix .. # from packages/ — links workspace deps
|
|
57
|
+
npm run dev -- --help # run from source via tsx
|
|
58
|
+
npm run build # compile to dist/
|
|
59
|
+
node dist/index.js --help # run the built CLI
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Link it as a global `mdk` for local testing:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm run build && npm link
|
|
66
|
+
mdk --help
|
|
67
|
+
# when done: npm rm -g @tetherto/mdk-cli
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Run the tests:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm test # unit tests, no network (coverage gate: npm run test:coverage)
|
|
74
|
+
npm run test:e2e:stack # ~1 min, needs network: scaffolds a worker and an app, runs the whole
|
|
75
|
+
# stack, then checks it over HTTP, with `mdk status` and against the
|
|
76
|
+
# app runtime's key allow-list
|
|
77
|
+
npm run test:e2e:scaffold # ~2 min, needs network and a built ui/ (npm --prefix ../../ui run build):
|
|
78
|
+
# scaffolds a worker, an app with its starter UI and the dashboard,
|
|
79
|
+
# builds the UIs, serves the app's UI with `mdk run dashboard` and calls
|
|
80
|
+
# the running stack through the dashboard's Gateway proxy
|
|
81
|
+
npm run test:e2e # both
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Try it out
|
|
85
|
+
|
|
86
|
+
Run the implemented commands against a throwaway project so nothing pollutes the
|
|
87
|
+
repo. From this package after `npm run build`:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
mkdir -p /tmp/mdk-try && cd /tmp/mdk-try
|
|
91
|
+
CLI=/path/to/mdk/packages/cli/dist/index.js
|
|
92
|
+
|
|
93
|
+
# Install the MDK Developer Skill (via the @tetherto/mdk-skill entry point)
|
|
94
|
+
node "$CLI" skill add --client all --dir .
|
|
95
|
+
ls .cursor/skills .claude/skills # mdk, mdk-gateway-plugin, mdk-deployment, mdk-worker-plugin, mdk-ui-component, mdk-site-sizing, mdk-create-app
|
|
96
|
+
|
|
97
|
+
# Scaffold the MDK UI shell into apps/dashboard, named <stack>-dashboard from mdk.yaml
|
|
98
|
+
node "$CLI" create dashboard --dir .
|
|
99
|
+
ls apps/dashboard # src/, vite.config.ts, package.json, ...
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The onboarding wizard needs a real terminal (TTY), so run it directly (not
|
|
103
|
+
piped). It writes `mdk.yaml`, the root [`package.json`](./package.json), `.gitignore` and a project
|
|
104
|
+
[`README.md`](./README.md), optionally installs the skill + scaffolds the UI shell, and prints
|
|
105
|
+
the run commands. Answers to `secret` plugin-setup questions are not written to `mdk.yaml`
|
|
106
|
+
(which you commit): the spec gets a `${MDK_<PLUGIN>_<KEY>}` placeholder and the value goes to
|
|
107
|
+
the project's gitignored, owner-only `.env`. `mdk run` resolves `${VAR}` in
|
|
108
|
+
`spec.gateway.config`, `spec.apps[].config` and `spec.workers[].env` from the
|
|
109
|
+
process environment first, then `.env`:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cd /tmp/mdk-try && node "$CLI" onboard
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Dev mode works the same without building — run from `packages/cli`:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm run dev -- skill add --client cursor --dir /tmp/mdk-try
|
|
119
|
+
npm run dev -- create dashboard --dir /tmp/mdk-try
|
|
120
|
+
npm run dev -- onboard
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Run the stack
|
|
124
|
+
|
|
125
|
+
`mdk run` boots the components declared in `mdk.yaml` against project-local state
|
|
126
|
+
under `.mdk/`. With no target, it boots the Kernel, every Worker, every app
|
|
127
|
+
(see [Apps](#apps)) and the Gateway together (the MCP server is never part of
|
|
128
|
+
`all` — it's always started explicitly, see [Run the MCP server](#run-the-mcp-server)).
|
|
129
|
+
Prefer separate terminals instead? Run each component on its own (`mdk run
|
|
130
|
+
kernel`, `mdk run worker <name>`, `mdk run app <name>`, `mdk run gateway`) —
|
|
131
|
+
that's just which commands you type, not a spec setting.
|
|
132
|
+
|
|
133
|
+
A **Worker** is a plugin package (contract + handlers) that the CLI hosts on
|
|
134
|
+
`WorkerRuntimeV2` — the same "caller hosts the plugin" split the monorepo examples
|
|
135
|
+
use. Reference one in `mdk.yaml` by **local path** (what `mdk create worker`
|
|
136
|
+
writes) or by installed package name (what `mdk add worker` writes), and describe
|
|
137
|
+
its seed devices under the plugin-defined `config`:
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
spec:
|
|
141
|
+
workers:
|
|
142
|
+
- name: miner-a
|
|
143
|
+
package: ./workers/my-miner # local path (or an installed npm name)
|
|
144
|
+
config:
|
|
145
|
+
mock: true # start the plugin's mock/server.js per device
|
|
146
|
+
devices:
|
|
147
|
+
- id: v3-0
|
|
148
|
+
opts: { host: 127.0.0.1, port: 18080, serial: WM3-DEMO-0, hashrateThs: 200, powerW: 3500 }
|
|
149
|
+
- id: v3-1
|
|
150
|
+
opts: { host: 127.0.0.1, port: 18081, serial: WM3-DEMO-1, hashrateThs: 180, powerW: 3300 }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`config.devices[].opts` is the plugin's own per-device config (opaque to the CLI).
|
|
154
|
+
With `mock: true` the CLI starts one simulator from `<package>/mock/server.js` per
|
|
155
|
+
device so the Worker talks to a mock instead of hardware.
|
|
156
|
+
|
|
157
|
+
#### Apps
|
|
158
|
+
|
|
159
|
+
An **app** is declared under `spec.apps[]` as
|
|
160
|
+
`{ name, package, config, mount? }`; the package needs an `mdk-app.yaml` and a
|
|
161
|
+
`mdk-plugin.json` route table in `plugin/` or at its root (`mdk create app` scaffolds both).
|
|
162
|
+
`spec.gateway.plugins` is rejected. That list is the whole of what
|
|
163
|
+
the Gateway serves. A package that ships several apps as subdirectories names
|
|
164
|
+
each by its subpath (`package: "@your-org/apps/ops"`):
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
spec:
|
|
168
|
+
apps:
|
|
169
|
+
- name: agent
|
|
170
|
+
package: "@tetherto/mdk-app-agent" # bundled; the UI calls it at /agent
|
|
171
|
+
mount: / # serve at the root, not /apps/agent
|
|
172
|
+
- name: demo
|
|
173
|
+
package: "@tetherto/mdk-app-demo" # an installed npm name
|
|
174
|
+
- name: site
|
|
175
|
+
package: ./apps/site # or a local path
|
|
176
|
+
config:
|
|
177
|
+
agent: { provider: { kind: qvac } }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`mdk run` starts one runtime child process per app before the Gateway, restarts
|
|
181
|
+
one that exits unexpectedly, and stops them on shutdown; `mdk run app <name>`
|
|
182
|
+
runs a single app in the foreground instead. The Gateway serves each app under
|
|
183
|
+
`/apps/<name>` unless `mount` is set. An app accepts calls only from the key in
|
|
184
|
+
`.mdk/gateway.key`, and publishes its own keys to `.mdk/apps/<name>/runtime.key`
|
|
185
|
+
(read by the Gateway) and `.mdk/trusted-keys/app-<name>.pub` (its Kernel client key, which the Kernel admits).
|
|
186
|
+
|
|
187
|
+
Undeclared means unserved: any path no declared app serves gets `404`. `mdk
|
|
188
|
+
status` reports an app whose package does not resolve (subpath included) and
|
|
189
|
+
whether each app is running.
|
|
190
|
+
|
|
191
|
+
Scaffold a Worker from the bundled template (a device client for an HTTP JSON API, with
|
|
192
|
+
a simulator under `mock/`) — it lands under `workers/<name>`, ready to reference by local path:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
node "$CLI" create worker demo-miner --dir /tmp/mdk-try # → /tmp/mdk-try/workers/demo-miner
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`create worker` also writes the new Worker into the project's `mdk.yaml` under
|
|
199
|
+
`spec.workers` (with a `mock: true` seed device) so it is runnable right away;
|
|
200
|
+
pass `--no-stack-entry` to skip and print the snippet instead. It leaves an
|
|
201
|
+
existing same-named entry untouched.
|
|
202
|
+
|
|
203
|
+
The seed device is given a stack-unique identity — mock port counting up from
|
|
204
|
+
`18080`, and a device id/serial derived from the Worker name — so scaffolding
|
|
205
|
+
several Workers into one project never produces a conflict. Both matter: a
|
|
206
|
+
duplicate port fails the boot, and a duplicate device id is worse, because the
|
|
207
|
+
Kernel registers ids globally and silently keeps only the first. `mdk run`
|
|
208
|
+
rejects a spec that repeats a Worker name or device id, naming both offenders.
|
|
209
|
+
|
|
210
|
+
`mdk run` runs in the foreground and owns Ctrl+C (and `SIGTERM`). Components are
|
|
211
|
+
stopped in reverse boot order — gateway, apps, then Workers and their mocks, then the
|
|
212
|
+
Kernel — but the process exits regardless of how that goes: a stop that throws is
|
|
213
|
+
skipped, a stop that wedges is abandoned after 5s with a forced exit, and a
|
|
214
|
+
second Ctrl+C exits immediately. So the ports a run holds are always released
|
|
215
|
+
when it is stopped. If a port is still busy afterward, the run did not actually
|
|
216
|
+
exit — check for a forgotten foreground `mdk run` in another terminal
|
|
217
|
+
(`ps -o pid,stat,etime,command -p <pid>`; a `+` in `STAT` means it is still the
|
|
218
|
+
foreground job of a live tab).
|
|
219
|
+
|
|
220
|
+
Each Kernel, Worker and app runs once per project. `mdk run` takes a lock for
|
|
221
|
+
every one it starts (`.mdk/run/<component>.pid`) and refuses a second copy with
|
|
222
|
+
the pid of the first: two copies of a Worker or app share its identity keys and
|
|
223
|
+
store, so the second takes over the first one's network key and the first goes
|
|
224
|
+
unreachable. A lock left behind by a process that is gone is taken over. The
|
|
225
|
+
Gateway and the MCP server are covered by their port check instead.
|
|
226
|
+
|
|
227
|
+
### Run the dashboard
|
|
228
|
+
|
|
229
|
+
`mdk run dashboard` starts the scaffolded UI shell's dev server
|
|
230
|
+
(`npm run dev` under `apps/dashboard`, or the first `apps/*` app with a `dev`
|
|
231
|
+
script if the dashboard was created with a custom `--name`). Unlike the Kernel,
|
|
232
|
+
Gateway and Workers — all booted in-process — the dashboard is a separate
|
|
233
|
+
Vite/React app with its own dependency tree (kept out of the project's npm
|
|
234
|
+
workspaces so its React is never hoisted alongside anyone else's, see
|
|
235
|
+
[Project layout](#project-layout)), so it always runs as its own child process.
|
|
236
|
+
It shares `mdk run`'s Ctrl+C/`SIGTERM` handling: the dev server is sent
|
|
237
|
+
`SIGTERM` and the command waits for it to exit before releasing its port.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
node "$CLI" create dashboard --dir /tmp/mdk-try
|
|
241
|
+
node "$CLI" run dashboard --dir /tmp/mdk-try # separate terminal from `mdk run`
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Mock ports are also resolved at boot. The configured port is used whenever it is
|
|
245
|
+
free; when something else already holds it (another stack on the machine, a
|
|
246
|
+
Worker left running) the mock moves to the next free port and says so, since the
|
|
247
|
+
port is a private contract between the simulator and the plugin that dials it.
|
|
248
|
+
Workers step over ports their not-yet-booted neighbours declared, so one squatter
|
|
249
|
+
relocates one Worker rather than shifting all of them. The Gateway port is never
|
|
250
|
+
relocated — it is a published endpoint, so a conflict there is a fast, explicit
|
|
251
|
+
failure before anything boots.
|
|
252
|
+
|
|
253
|
+
Every `create` command installs dependencies by default (`--no-install` to skip):
|
|
254
|
+
a Worker or app installs from the project root, so npm links it through its `file:`
|
|
255
|
+
dependency, while the dashboard installs in place. If the project has no root
|
|
256
|
+
[`package.json`](./package.json) yet, `create worker` and `create app` write one.
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
node "$CLI" run --dir /tmp/mdk-try # everything together: kernel + workers + apps + gateway
|
|
260
|
+
node "$CLI" run worker demo-miner --dir /tmp/mdk-try # just the worker (+ its mocks)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Run the MCP server
|
|
264
|
+
|
|
265
|
+
`mdk run mcp` boots a standalone [`@tetherto/mdk-mcp`](../../backend/core/mcp/README.md)
|
|
266
|
+
server — a separate process from the Gateway, which has no MCP code of its own.
|
|
267
|
+
It requires `mdk.yaml` exactly like every other `run` target, and reads the same
|
|
268
|
+
`spec.apps` the Gateway serves: each declared app's
|
|
269
|
+
`mdk-plugin.json` contract is converted into MCP tools with no separate tool
|
|
270
|
+
authoring. Like the Gateway, it runs no app code: each tool call is forwarded to
|
|
271
|
+
the app's runtime, so an app's tools answer once `mdk run` has started it
|
|
272
|
+
(until then a call returns `ERR_APP_RUNTIME_UNAVAILABLE`). Like `dashboard`,
|
|
273
|
+
`mcp` is never part of the default `all` target — it's always started
|
|
274
|
+
explicitly, and needs the Kernel already reachable (an in-process handle isn't
|
|
275
|
+
available to a standalone `run mcp`, so start the Kernel first: `mdk run kernel`).
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
node "$CLI" run --dir /tmp/mdk-try # first, in its own terminal
|
|
279
|
+
node "$CLI" run mcp --dir /tmp/mdk-try # then, in another terminal
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The server listens on `spec.mcp.port` if set in `mdk.yaml`, else
|
|
283
|
+
`spec.gateway.port + 100`:
|
|
284
|
+
|
|
285
|
+
```yaml
|
|
286
|
+
spec:
|
|
287
|
+
gateway:
|
|
288
|
+
port: 3000
|
|
289
|
+
mcp:
|
|
290
|
+
port: 3100 # optional — defaults to gateway.port + 100
|
|
291
|
+
allowWrite: false # optional — same as `mdk run mcp --allow-write`
|
|
292
|
+
allowTools: [demo.summary] # optional — expose only these tool ids (write tools included)
|
|
293
|
+
token: ${MDK_MCP_TOKEN} # optional — require `Authorization: Bearer <token>` on /mcp; `mdk run mcp` fails if the variable is unset
|
|
294
|
+
identity: { user: agent } # optional — needed to expose `auth: true` Gateway routes
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Tools that are not declared read-only (`"safety": "read-only"` on the route, as the
|
|
298
|
+
`mdk create app` template does for its summary route) stay hidden unless you pass `--allow-write`
|
|
299
|
+
(or set `spec.mcp.allowWrite`) or name them in `allowTools`. The CLI owns
|
|
300
|
+
`Ctrl+C`/`SIGTERM` and closes the server itself.
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
### Check the stack
|
|
304
|
+
|
|
305
|
+
`mdk status` is a one-shot report — it never starts, stops, or repairs
|
|
306
|
+
anything. Its one write is the CLI's own caller key, published to
|
|
307
|
+
`.mdk/trusted-keys/cli.pub` so the fail-closed Kernel answers its probe. It covers
|
|
308
|
+
the **environment** (Node 24 or newer, package manager, `mdk.yaml` validity, and
|
|
309
|
+
whether every declared Worker and app package actually resolves) and the **stack**
|
|
310
|
+
(Kernel, Gateway, each Worker with its state, health, and device count, and each app).
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
node "$CLI" status --dir /tmp/mdk-try
|
|
314
|
+
node "$CLI" status --dir /tmp/mdk-try -o json | jq .health
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Liveness is probed, never inferred from files: `.mdk/kernel.key` and
|
|
318
|
+
`.mdk/keys/*.key` survive a shutdown by design (the keys are stable across
|
|
319
|
+
restarts), so the Kernel is probed over HRPC with that key and the Gateway over
|
|
320
|
+
HTTP on its configured port (any answer below `500` counts). An app runtime accepts
|
|
321
|
+
calls from the Gateway's key only, so an app counts as running while a live
|
|
322
|
+
process holds its run lock.
|
|
323
|
+
|
|
324
|
+
Exit codes make it scriptable (`mdk status && deploy…`):
|
|
325
|
+
|
|
326
|
+
| Exit code | Fires when | Fix |
|
|
327
|
+
| --------- | ---------------------------------------------------------------------- | ----------------------------------- |
|
|
328
|
+
| `0` | Environment checks pass and every component reports `healthy` | None |
|
|
329
|
+
| `1` | `collectStatus` throws while gathering the report, an unexpected error | Check the printed error message and the project directory (`--dir`) |
|
|
330
|
+
| `2` | `--output` names a format outside `table`/`json`/`yaml` | Pass one of `table`, `json`, `yaml` |
|
|
331
|
+
| `4` | An environment precondition fails: old Node, a missing or invalid `mdk.yaml`, or a declared package that doesn't resolve | Fix the precondition the report names |
|
|
332
|
+
| `5` | The stack isn't fully up: Kernel or Gateway unreachable, a declared Worker not registered/serving, or a declared app not running | Check the component the report marks unhealthy |
|
|
333
|
+
|
|
334
|
+
Notes:
|
|
335
|
+
|
|
336
|
+
- `skill add` resolves `@tetherto/mdk-skill` through node/npm (no path walking),
|
|
337
|
+
assembling on demand inside the monorepo and copying the bundled skills once
|
|
338
|
+
published
|
|
339
|
+
- `create dashboard` (and the onboarding UI step) scaffold the MDK UI shell from
|
|
340
|
+
[`examples/mdk-ui-shell-template`](../../examples/mdk-ui-shell-template/README.md) (a real, runnable
|
|
341
|
+
Vite app that doubles as the template). **Inside the monorepo** it copies that template locally (no network)
|
|
342
|
+
and rewrites the template's `file:` MDK deps to absolute links into the
|
|
343
|
+
monorepo's `ui/packages/*`. **Standalone**, it downloads the same subtree from
|
|
344
|
+
GitHub (`tetherto/mdk .../examples/mdk-ui-shell-template`) via `degit`, which
|
|
345
|
+
needs network access, and pins MDK deps to a published range. Either way it
|
|
346
|
+
lands in `apps/dashboard`, takes the package + `APP_NAME` from
|
|
347
|
+
`<stack>-dashboard`, and copies
|
|
348
|
+
`.env.example` → `.env` with `VITE_GATEWAY_URL` pointed at this stack's gateway
|
|
349
|
+
port. Passing a name puts the app in `apps/<name>` instead.
|
|
350
|
+
|
|
351
|
+
| Flag | Status | Type | Default | Description |
|
|
352
|
+
| -------------- | -------- | -------- | -------- | ----------------------------------------------- |
|
|
353
|
+
| `--ref` | Optional | `string` | `v<cli version>` | Branch/tag/SHA to scaffold from; ignored in monorepo (local template always wins), applies only to the standalone GitHub path |
|
|
354
|
+
| `--force` | Optional | `boolean` | `false` | Overwrite the target directory; recursively deletes it first, no confirmation prompt |
|
|
355
|
+
| `--no-install` | Optional | `boolean` | `false` | Skip the post-scaffold dependency install |
|
|
356
|
+
|
|
357
|
+
- The scaffolded dashboard is a normal Vite app: `npm run build` inside it
|
|
358
|
+
produces a `dist/` you serve however you serve static assets. `create dashboard`
|
|
359
|
+
only sets `VITE_GATEWAY_URL`/`VITE_OAUTH_BASE_URL` for local dev against this
|
|
360
|
+
stack — update `apps/dashboard/.env` before building for any other target.
|
|
361
|
+
- Reset a scratch run with `rm -rf /tmp/mdk-try`
|
|
362
|
+
|
|
363
|
+
Or link it as a real `mdk` command (optional; best for testing):
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
cd packages/cli
|
|
367
|
+
npm run build && npm link # exposes a global `mdk`
|
|
368
|
+
|
|
369
|
+
mkdir mdk-try && cd mdk-try
|
|
370
|
+
mdk --help
|
|
371
|
+
mdk skill add --client cursor
|
|
372
|
+
mdk create dashboard
|
|
373
|
+
mdk onboard
|
|
374
|
+
|
|
375
|
+
# when done: npm rm -g @tetherto/mdk-cli
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Adding and validating apps and workers
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
# From npm (a scope, a version range and, for packages that ship several apps, a subpath all work)
|
|
382
|
+
mdk add app @your-org/mdk-app-ops-center@^1
|
|
383
|
+
mdk add worker @your-org/mdk-worker-rig
|
|
384
|
+
# From GitHub: github:owner/repo[#ref], owner/repo or a github.com URL
|
|
385
|
+
mdk add app github:me/my-app#v0.2.0 --name ops
|
|
386
|
+
|
|
387
|
+
mdk validate app ops # the app mdk.yaml lists as `ops` under spec.apps
|
|
388
|
+
mdk validate worker rig --json
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
`mdk add` runs `npm install --ignore-scripts --save-exact <source>` in the project (so npm records the
|
|
392
|
+
exact version in `package.json`, and no install script of an unchecked package runs), checks the installed
|
|
393
|
+
package with the same rules as `mdk validate`, and only then adds it under `spec.apps` / `spec.workers` in
|
|
394
|
+
`mdk.yaml`, keeping the file's comments and formatting. A refused package leaves `mdk.yaml` untouched and
|
|
395
|
+
puts `package.json` and the lockfile back, so it neither stays installed nor replaces a version an app
|
|
396
|
+
already runs. Adding the same package again updates it under the name it already has; giving it another
|
|
397
|
+
`--name` adds it as a second app. A
|
|
398
|
+
GitHub source has to be installed (no `--no-install`), because its package name is only known after
|
|
399
|
+
npm has fetched it. A worker without a bundled mock is added without `mock: true`; fill in its
|
|
400
|
+
`config.devices[].opts`.
|
|
401
|
+
|
|
402
|
+
`mdk validate app <name>` and `mdk validate worker <name>` take the name the component has in `mdk.yaml` (as
|
|
403
|
+
`mdk run app <name>` does), from the project in `--dir` (default `.`), and check the package that entry resolves to.
|
|
404
|
+
`mdk validate app` checks `mdk-app.yaml`, its version against `package.json`, the permission rules and the
|
|
405
|
+
route table (`plugin/mdk-plugin.json`, else `mdk-plugin.json` at the package root), by the same rules the app
|
|
406
|
+
runtime and the Gateway apply at boot: a reverse-DNS `id`, a semver `version`, and handlers that resolve inside
|
|
407
|
+
the plugin directory, paths that start with `/` and appear once per method, and handlers (and `main`) that compile.
|
|
408
|
+
Unknown `mdk-app.yaml` keys are reported, so a typo does not pass silently. `mdk validate worker` checks `package.json`
|
|
409
|
+
and the `mdk-contract.json` Worker Plugin contract: at least one telemetry entry or command, command `params` as lists,
|
|
410
|
+
and handlers resolved on disk and compiling. Nothing is run, so a module that throws when loaded only shows when the
|
|
411
|
+
component starts. Both exit 1 on any error. The UI is not validated yet.
|
|
412
|
+
|
|
413
|
+
`mdk validate worker --path <dir>` checks a package directory that no `mdk.yaml` declares, such as a partner's own
|
|
414
|
+
repo in CI. `--smoke` adds behavioral checks against the package's bundled mock, which `setup()` in its
|
|
415
|
+
`smoke.config.js` starts. While the mock runs, every telemetry channel must return its declared type and every sample
|
|
416
|
+
command in `commands` must succeed. After `teardown()`, every channel and command must fail with an `ERR_*` error code
|
|
417
|
+
within `--timeout`, except a `health` channel reporting a status other than `OK`, and the channels `offlineTelemetry`
|
|
418
|
+
lists because the Worker serves them from its own store. The [Worker testing guide](../../docs/guides/workers/test-a-worker.md#check-the-package)
|
|
419
|
+
lists every `smoke.config.js` field.
|
|
420
|
+
|
|
421
|
+
## Command surface
|
|
422
|
+
|
|
423
|
+
| Group | Commands |
|
|
424
|
+
| ---------------- | ------------------------------------------------------------------------------------- |
|
|
425
|
+
| Onboarding | `mdk onboard` |
|
|
426
|
+
| Scaffold | `mdk create worker <name>`, `mdk create app <name>`, `mdk create dashboard [name]` |
|
|
427
|
+
| Add | `mdk add app <source>`, `mdk add worker <source>` |
|
|
428
|
+
| Validate | `mdk validate app <name>`, `mdk validate worker <name>` |
|
|
429
|
+
| Run & manage | `mdk run [target] [name]` (target: `all`\|`kernel`\|`gateway`\|`mcp`\|`worker <name>`\|`app <name>`\|`dashboard`), `mdk status` |
|
|
430
|
+
| Agent enablement | `mdk skill add` |
|
|
431
|
+
| Meta | `mdk version` |
|
|
432
|
+
|
|
433
|
+
Global flags:
|
|
434
|
+
|
|
435
|
+
| Flag | Status | Type | Default | Description |
|
|
436
|
+
| -------------------- | -------- | --------- | ------- | -------------------------------------------------- |
|
|
437
|
+
| `-o, --output <fmt>` | Optional | `string` | `table` | Output format for data: `table`, `json`, or `yaml` |
|
|
438
|
+
| `-v, --verbose` | Optional | `boolean` | `false` | Increase log detail |
|
|
439
|
+
| `--debug` | Optional | `boolean` | `false` | Print stack traces for unexpected failures |
|
|
440
|
+
| `--version` | Optional | `boolean` | `false` | Print the CLI version and exit |
|
|
441
|
+
| `-h, --help` | Optional | `boolean` | `false` | Print usage help and exit |
|
|
442
|
+
|
|
443
|
+
## Next steps
|
|
444
|
+
|
|
445
|
+
- See [`instruction.md`](instruction.md) for the full guide (conventions, output
|
|
446
|
+
rules, and definition of done). Read it before contributing, especially if you
|
|
447
|
+
are an AI coding agent.
|