@netnodeag/kraftwerk 0.47.0 → 0.49.0
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/README.md +106 -5
- package/dist/cli/doctor.js +18 -1
- package/dist/cli/init.js +10 -8
- package/dist/cli/kraftwerk.js +16 -2
- package/dist/cli/projects.d.ts +0 -14
- package/dist/cli/projects.js +181 -107
- package/dist/cli/repos.js +1 -1
- package/dist/cli/ui.js +1 -1
- package/dist/cli/vibeables.js +1 -1
- package/dist/cli/workspaces.d.ts +16 -0
- package/dist/cli/workspaces.js +149 -0
- package/dist/config.d.ts +22 -1
- package/dist/config.js +19 -3
- package/dist/dotenv.d.ts +40 -0
- package/dist/dotenv.js +84 -0
- package/dist/inspector/agents.js +2 -2
- package/dist/inspector/channels.d.ts +10 -1
- package/dist/inspector/channels.js +11 -2
- package/dist/inspector/chat/sessions.d.ts +8 -3
- package/dist/inspector/chat/sessions.js +58 -19
- package/dist/inspector/chat/types.d.ts +11 -0
- package/dist/inspector/git.js +5 -3
- package/dist/inspector/instances.d.ts +14 -12
- package/dist/inspector/instances.js +71 -31
- package/dist/inspector/notifications.js +2 -0
- package/dist/inspector/projects.d.ts +167 -0
- package/dist/inspector/projects.js +520 -0
- package/dist/inspector/search.d.ts +1 -1
- package/dist/inspector/search.js +3 -3
- package/dist/inspector/server.js +111 -20
- package/dist/inspector/settings.d.ts +3 -1
- package/dist/inspector/settings.js +14 -3
- package/inspector/dist/assets/{dist-D8pjVMTl.js → dist-B-8ArbIm.js} +1 -1
- package/inspector/dist/assets/{dist-DfAFwiGQ.js → dist-BFJWVdBm.js} +1 -1
- package/inspector/dist/assets/{dist-C2Mu5bT-.js → dist-BIvcKBWo.js} +1 -1
- package/inspector/dist/assets/{dist-CdyUhzAt.js → dist-BgYnJawU.js} +1 -1
- package/inspector/dist/assets/dist-Bl1ogZZM.js +1 -0
- package/inspector/dist/assets/{dist-BNUGzZS7.js → dist-BrgwFqUR.js} +1 -1
- package/inspector/dist/assets/{dist-DnmDnMK2.js → dist-Bz0bwjja.js} +1 -1
- package/inspector/dist/assets/{dist-CjMETDfE.js → dist-CFvGR87v.js} +1 -1
- package/inspector/dist/assets/{dist-CUeUDZ9j.js → dist-CjtxxsZ2.js} +1 -1
- package/inspector/dist/assets/{dist-CmOlZvwa.js → dist-QwwTJ2wk.js} +1 -1
- package/inspector/dist/assets/{dist-BOQhQPN9.js → dist-tfmgozDB.js} +1 -1
- package/inspector/dist/assets/{editor-DJbeG376.js → editor-C6m40u-h.js} +3 -3
- package/inspector/dist/assets/{index-DgEUOA11.js → index-Cvq-RiV2.js} +14 -14
- package/inspector/dist/assets/{index-DQrsXEWt.css → index-DcQwGaV2.css} +1 -1
- package/inspector/dist/index.html +2 -2
- package/package.json +1 -1
- package/schema/kraftwerk.schema.json +18 -0
- package/inspector/dist/assets/dist-rrIMDK_-.js +0 -1
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ newer version is on disk, right after "update now" or after a manual install.
|
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
96
|
npm install -g @netnodeag/kraftwerk@latest
|
|
97
|
-
kraftwerk
|
|
97
|
+
kraftwerk workspaces # every workspace on this machine, running or not
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
## Consume
|
|
@@ -156,7 +156,8 @@ kraftwerk run # interactive: pick workflow, type the r
|
|
|
156
156
|
kraftwerk runs # past runs from output/*/trace.jsonl; runs show <id> for detail
|
|
157
157
|
kraftwerk knowledge # Knowledge: OKF bundles (list/get/put/verify/search/...)
|
|
158
158
|
kraftwerk ui # inspector web UI on http://localhost:1981; --port, --output
|
|
159
|
-
kraftwerk
|
|
159
|
+
kraftwerk workspaces # every workspace on this machine; workspaces start|stop|forget <ref>
|
|
160
|
+
kraftwerk projects # goal-scoped project folders; projects create|show|link|log|remove
|
|
160
161
|
kraftwerk doctor # preflight: harness CLIs, docker, workflows, declared env vars
|
|
161
162
|
kraftwerk validate # all discovered: schema + semantics + files, exit 1 on failure
|
|
162
163
|
kraftwerk validate src/workflows/pitch # specific paths
|
|
@@ -193,6 +194,16 @@ run-artifact directory (default `output/`), `knowledge:` the OKF bundle root
|
|
|
193
194
|
`public:` and `tunnel:` expose the inspector through a
|
|
194
195
|
[Cloudflare Tunnel](#inspector-through-a-cloudflare-tunnel).
|
|
195
196
|
|
|
197
|
+
A `.env` next to kraftwerk.yml (`KEY=value` lines, `#` comments, quotes)
|
|
198
|
+
is loaded into every kraftwerk process at start: `kraftwerk ui` and the
|
|
199
|
+
server it supervises, so a restart from the UI re-reads the file; the chat
|
|
200
|
+
agents, routines and workflow runs the inspector spawns; the tunnel
|
|
201
|
+
(`TUNNEL_TOKEN`); `requires:` checks in `run` and `doctor`. A variable the
|
|
202
|
+
shell already sets wins over the file. A project started from another
|
|
203
|
+
workspace's inspector gets its own `.env`, not the other one's. The file is
|
|
204
|
+
never synced (it is on the workspace git's deny list and in the .gitignore
|
|
205
|
+
`kraftwerk init` writes); `kraftwerk doctor` lists the names it loaded.
|
|
206
|
+
|
|
196
207
|
`switcher:` links other kraftwerk workspaces from the inspector header. The
|
|
197
208
|
workspace name becomes a dropdown listing them:
|
|
198
209
|
|
|
@@ -207,8 +218,8 @@ switcher:
|
|
|
207
218
|
letters of an agent's or channel's name, description or workspace and hit
|
|
208
219
|
enter to jump to it. It lists the active agents and the channels of every
|
|
209
220
|
workspace on this machine, grouped by workspace and running or not (a
|
|
210
|
-
stopped one is started on the way), read from the
|
|
211
|
-
`~/.kraftwerk/
|
|
221
|
+
stopped one is started on the way), read from the workspace registry under
|
|
222
|
+
`~/.kraftwerk/workspaces`, which every inspector keeps current with its
|
|
212
223
|
roster and channel list.
|
|
213
224
|
|
|
214
225
|
### Triggering from CI, cron, or webhooks
|
|
@@ -370,7 +381,7 @@ working without a login. `kraftwerk doctor` reports the tunnel, the Access
|
|
|
370
381
|
block and whether cloudflared is installed.
|
|
371
382
|
|
|
372
383
|
**Variants.** `kraftwerk tunnel` runs the configured tunnel alone, for an
|
|
373
|
-
inspector that already runs elsewhere (started by `kraftwerk
|
|
384
|
+
inspector that already runs elsewhere (started by `kraftwerk workspaces
|
|
374
385
|
start`, or in a container). For a tunnel created in the Zero Trust
|
|
375
386
|
dashboard instead (Networks → Tunnels), leave `name` out, route the
|
|
376
387
|
hostname to `http://localhost:<port>` there and export its token as
|
|
@@ -393,6 +404,96 @@ Quick tunnels (`trycloudflare.com`) are deliberately not supported: Access
|
|
|
393
404
|
cannot be attached to them, which would leave the UI open to anyone with
|
|
394
405
|
the URL.
|
|
395
406
|
|
|
407
|
+
## Projects
|
|
408
|
+
|
|
409
|
+
Turn on `projects:` in `kraftwerk.yml` (or the checkbox in settings) and
|
|
410
|
+
the workspace gets one folder per project — a goal with everything the
|
|
411
|
+
agents need to reach it:
|
|
412
|
+
|
|
413
|
+
```yaml
|
|
414
|
+
projects:
|
|
415
|
+
root: kraftwerk-data/projects # default; part of the workspace, synced like agents and knowledge
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
```
|
|
419
|
+
kraftwerk-data/projects/<slug>/
|
|
420
|
+
project.yml # title, status, goal, records, links
|
|
421
|
+
brief.md # the goal in full: what done looks like, constraints, stakeholders
|
|
422
|
+
state.md # current state, rewritten at the end of a session
|
|
423
|
+
log.md # append-only, newest first: decisions and milestones, dated and attributed
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
`project.yml` holds the one-line goal, a status (`active`, `paused`, `done`,
|
|
427
|
+
`archived`), the harness, model and effort its chats run on (the same three
|
|
428
|
+
fields an agent has; the harness decides, not the caller), the **systems of
|
|
429
|
+
record** and the **links**:
|
|
430
|
+
|
|
431
|
+
```yaml
|
|
432
|
+
title: Relaunch netnode.ch
|
|
433
|
+
status: active
|
|
434
|
+
goal: Ship the new site on NodeHive by 2026-11-30
|
|
435
|
+
harness: claude # claude | codex | pi — every chat in the project runs on it
|
|
436
|
+
model: sonnet # optional, like an agent's
|
|
437
|
+
effort: high # optional: low | medium | high | xhigh | max
|
|
438
|
+
records:
|
|
439
|
+
- kind: my-netnode # my-netnode | google-drive | github | bitbucket | notion | slack | url | anything
|
|
440
|
+
workspace: 22
|
|
441
|
+
url: https://my.netnode.ch/workspace/22
|
|
442
|
+
note: tickets, roadmap and meetings
|
|
443
|
+
- kind: google-drive
|
|
444
|
+
title: Contracts and briefs
|
|
445
|
+
url: https://drive.google.com/drive/folders/…
|
|
446
|
+
knowledge: [netnode-helpdesk] # OKF bundle names
|
|
447
|
+
vibeables: [launch-tracker] # folders under the vibeables root
|
|
448
|
+
repos: [netnode-frontend] # folders under the repos root
|
|
449
|
+
workflows: [website-check] # workflow slugs
|
|
450
|
+
agents: [max] # agent slugs
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
A system of record says where the truth of the project is managed outside
|
|
454
|
+
kraftwerk and what usually lives there. It is context, not a credential and
|
|
455
|
+
not a grant: the agent reaches it through the tools its harness already has
|
|
456
|
+
(a CLI, an MCP server, the browser), and the harness decides what it may
|
|
457
|
+
call. Kraftwerk knows a few kinds only to label them and phrase the context
|
|
458
|
+
better; any other kind passes through as a link with a note.
|
|
459
|
+
|
|
460
|
+
Links are one-directional lists of slugs. A target that does not exist is
|
|
461
|
+
shown as "not found" on the project page and told to the agent, never an
|
|
462
|
+
error — the same rule an agent's knowledge list follows.
|
|
463
|
+
|
|
464
|
+
**Working in a project is chat.** The Projects screen lists the projects,
|
|
465
|
+
the chats of the selected one, and the thread; opening a project opens its
|
|
466
|
+
latest chat. A session scoped to a project starts with the brief, the
|
|
467
|
+
current state, the records, every link with how to reach it, and the rule
|
|
468
|
+
for keeping the project current: `state.md` is rewritten at the end of a
|
|
469
|
+
session that changed something, so the next session (by anyone) continues
|
|
470
|
+
without the transcript; `log.md` is appended through
|
|
471
|
+
`kraftwerk projects log <slug> "<line>" --actor <who>` so every line is
|
|
472
|
+
dated and attributed; `brief.md` belongs to the user. The working
|
|
473
|
+
directory stays the workspace root, so linked repositories and knowledge
|
|
474
|
+
are reachable by path; opening a vibeable moves it into the app folder as
|
|
475
|
+
in any chat.
|
|
476
|
+
|
|
477
|
+
**Coworkers.** "Add coworker" on a project chat works as on an agent
|
|
478
|
+
session: the chat becomes a channel whose members are the agents you pick,
|
|
479
|
+
with everything said so far and the project's brief, state, records and
|
|
480
|
+
links as context for every member (`project:` in `channel.yml`). The
|
|
481
|
+
channel lives on the channels screen and stays listed under the project.
|
|
482
|
+
The first agent picked answers messages that mention nobody.
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
kraftwerk projects # list: title, status, goal, links
|
|
486
|
+
kraftwerk projects create "Relaunch netnode.ch" --goal "Ship by November"
|
|
487
|
+
kraftwerk projects show relaunch-netnode-ch # definition, records, link states, state, log
|
|
488
|
+
kraftwerk projects set relaunch-netnode-ch --harness codex --model gpt-5.6-sol --effort high
|
|
489
|
+
kraftwerk projects link relaunch-netnode-ch workflows website-check
|
|
490
|
+
kraftwerk projects log relaunch-netnode-ch "Decided on NodeHive." --actor human:lukas
|
|
491
|
+
kraftwerk projects remove relaunch-netnode-ch
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
The registry of workspaces on this machine, which answered to
|
|
495
|
+
`kraftwerk projects` until 0.48, is `kraftwerk workspaces` now.
|
|
496
|
+
|
|
396
497
|
## Persistent agents
|
|
397
498
|
|
|
398
499
|
The inspector's "agents" screen turns chat agents into persistent teammates. An
|
package/dist/cli/doctor.js
CHANGED
|
@@ -5,6 +5,7 @@ import chalk from "chalk";
|
|
|
5
5
|
import { ignoreEntryFor, isDir, publicHostFor, reposRootFor, resolveProject, tunnelFor } from "../config.js";
|
|
6
6
|
import { discoverWorkflows } from "../discover.js";
|
|
7
7
|
import { missingEnv } from "../yaml.js";
|
|
8
|
+
import { applyDotenv, DOTENV_FILE } from "../dotenv.js";
|
|
8
9
|
const ICONS = {
|
|
9
10
|
ok: chalk.green("✔"),
|
|
10
11
|
warn: chalk.yellow("⚠"),
|
|
@@ -87,7 +88,13 @@ export async function runDoctor(cwd) {
|
|
|
87
88
|
else {
|
|
88
89
|
const cfg = project.config;
|
|
89
90
|
const keys = Object.keys(cfg);
|
|
90
|
-
|
|
91
|
+
// Blocks (git, repos, vibeables, projects, tunnel) print as their keys, not [object Object].
|
|
92
|
+
const show = (v) => typeof v === "object" && v !== null
|
|
93
|
+
? Array.isArray(v)
|
|
94
|
+
? `[${v.length}]`
|
|
95
|
+
: `{${Object.entries(v).map(([k, x]) => `${k}: ${show(x)}`).join(", ") || " "}}`
|
|
96
|
+
: String(v);
|
|
97
|
+
report("ok", `${path.basename(project.configPath)} well-formed`, keys.length ? keys.map((k) => `${k}: ${show(cfg[k])}`).join(", ") : "empty — defaults apply");
|
|
91
98
|
if (!cfg.name)
|
|
92
99
|
report("info", "name not set in kraftwerk.yml", "inspector header falls back to the folder name");
|
|
93
100
|
for (const key of ["workflows", "knowledge", "agents", "output"]) {
|
|
@@ -106,6 +113,16 @@ export async function runDoctor(cwd) {
|
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
}
|
|
116
|
+
// .env next to kraftwerk.yml: already applied by the CLI hook; this call
|
|
117
|
+
// only reports what it holds (names, never values).
|
|
118
|
+
const dotenv = await applyDotenv(project.root);
|
|
119
|
+
if (dotenv.file) {
|
|
120
|
+
const names = [...dotenv.applied, ...dotenv.kept.map((k) => `${k} (shell wins)`)];
|
|
121
|
+
report("ok", `${DOTENV_FILE}: ${names.length} variable(s) loaded`, names.join(", ") || "empty");
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
report("info", `no ${DOTENV_FILE}`, "variables for agents, workflows and the tunnel can live there — loaded on every start and restart");
|
|
125
|
+
}
|
|
109
126
|
// Repositories: the clones root must stay out of the workspace git. git
|
|
110
127
|
// itself decides — that covers worktrees (.git is a file), a workspace
|
|
111
128
|
// nested in a larger repo, a .gitignore at the toplevel, global excludes.
|
package/dist/cli/init.js
CHANGED
|
@@ -2,6 +2,7 @@ import { appendFile, mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { CONFIG_SCHEMA_URL, gitignoreHas, SCHEMA_URL } from "../config.js";
|
|
5
|
+
import { DOTENV_FILE } from "../dotenv.js";
|
|
5
6
|
import { initBundle, writeConcept } from "../okf.js";
|
|
6
7
|
/**
|
|
7
8
|
* `kraftwerk init` — make any repository a kraftwerk consumer in one
|
|
@@ -25,6 +26,7 @@ skills: ${DATA_DIR}/skills # workspace skills (shared instruction packag
|
|
|
25
26
|
# repos: # git repositories the agents work on (uncomment both lines to enable)
|
|
26
27
|
# root: ${DATA_DIR}/repos # clones land here (git-ignored); a bare \`repos:\` uses repos/ instead
|
|
27
28
|
# vibeables: # small apps built live in a chat with a preview pane (uncomment to enable; one folder per app under ${DATA_DIR}/vibeables, versioned with the workspace)
|
|
29
|
+
# projects: # goal-scoped folders — brief, systems of record, links to knowledge/vibeables/repos/workflows/agents — that chats work in (uncomment to enable; one folder per project under ${DATA_DIR}/projects)
|
|
28
30
|
# public: https://kw.example.com # hostname the inspector is reached at through a tunnel or reverse proxy
|
|
29
31
|
# tunnel: # Cloudflare Tunnel run by \`kraftwerk ui\` (needs public:; put a Cloudflare Access policy on the hostname — the UI has no login of its own)
|
|
30
32
|
# name: kraftwerk # locally-managed tunnel (cloudflared tunnel create/route dns); omit and export TUNNEL_TOKEN for a dashboard-managed one
|
|
@@ -133,24 +135,24 @@ export async function runInit(cwd) {
|
|
|
133
135
|
await writeConcept(knowledgeRoot, DEMO_BUNDLE, "playbooks/refunds", DEMO_CONCEPT, "kraftwerk-init");
|
|
134
136
|
created.push(bundleRel);
|
|
135
137
|
}
|
|
136
|
-
// .gitignore: the output dir
|
|
137
|
-
// gitlinks of the workspace repo). A missing file gets
|
|
138
|
-
// an existing one only the entries it lacks.
|
|
138
|
+
// .gitignore: the output dir, the repos root (clones must never become
|
|
139
|
+
// gitlinks of the workspace repo) and .env (secrets). A missing file gets
|
|
140
|
+
// all in one write; an existing one only the entries it lacks.
|
|
139
141
|
const gitignorePath = path.join(cwd, ".gitignore");
|
|
140
142
|
const gitignore = (await readFile(gitignorePath, "utf8").catch(() => null)) ?? null;
|
|
141
|
-
const entries = [`${DATA_DIR}/output
|
|
143
|
+
const entries = [`${DATA_DIR}/output/`, `${DATA_DIR}/repos/`, DOTENV_FILE];
|
|
142
144
|
if (gitignore === null) {
|
|
143
|
-
await writeFile(gitignorePath, entries.map((e) => `${e}
|
|
145
|
+
await writeFile(gitignorePath, entries.map((e) => `${e}\n`).join(""));
|
|
144
146
|
created.push(".gitignore");
|
|
145
147
|
}
|
|
146
148
|
else {
|
|
147
|
-
const missing = entries.filter((e) => !gitignoreHas(gitignore, e));
|
|
149
|
+
const missing = entries.filter((e) => !gitignoreHas(gitignore, e.replace(/\/$/, "")));
|
|
148
150
|
if (missing.length === 0) {
|
|
149
151
|
skipped.push(".gitignore");
|
|
150
152
|
}
|
|
151
153
|
else {
|
|
152
|
-
await appendFile(gitignorePath, `${gitignore.endsWith("\n") ? "" : "\n"}${missing.map((e) => `${e}
|
|
153
|
-
created.push(`.gitignore (${missing.
|
|
154
|
+
await appendFile(gitignorePath, `${gitignore.endsWith("\n") ? "" : "\n"}${missing.map((e) => `${e}\n`).join("")}`);
|
|
155
|
+
created.push(`.gitignore (${missing.join(", ")} added)`);
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
for (const f of created)
|
package/dist/cli/kraftwerk.js
CHANGED
|
@@ -13,9 +13,12 @@ import { runDoctor } from "./doctor.js";
|
|
|
13
13
|
import { runInit } from "./init.js";
|
|
14
14
|
import { registerKnowledgeCommands } from "./knowledge.js";
|
|
15
15
|
import { registerProjectCommands } from "./projects.js";
|
|
16
|
+
import { registerWorkspaceCommands } from "./workspaces.js";
|
|
16
17
|
import { registerRepoCommands } from "./repos.js";
|
|
17
18
|
import { registerVibeableCommands } from "./vibeables.js";
|
|
18
19
|
import { registerTunnelCommands } from "./tunnel.js";
|
|
20
|
+
import { applyDotenv } from "../dotenv.js";
|
|
21
|
+
import { resolveProject } from "../config.js";
|
|
19
22
|
import { registerRoutineCommands } from "./routines.js";
|
|
20
23
|
import { listRuns, showRun } from "./runs.js";
|
|
21
24
|
import { runUi } from "./ui.js";
|
|
@@ -29,7 +32,9 @@ import { runUi } from "./ui.js";
|
|
|
29
32
|
* kraftwerk knowledge ... Knowledge: OKF bundles (list/get/put/verify/...)
|
|
30
33
|
* kraftwerk routines ... per-agent scheduled prompts (list/add/remove/enable/run)
|
|
31
34
|
* kraftwerk ui start the inspector web UI (localhost:1981)
|
|
32
|
-
* kraftwerk
|
|
35
|
+
* kraftwerk workspaces ... known workspaces on this machine (list/start/stop/forget)
|
|
36
|
+
* kraftwerk projects ... goal-scoped project folders (list/create/show/link/log/remove)
|
|
37
|
+
* kraftwerk vibeables ... small apps built live in a chat (list/create/remove)
|
|
33
38
|
* kraftwerk repos ... repositories the agents work on (list/add/update/remove)
|
|
34
39
|
* kraftwerk tunnel [setup <host>] Cloudflare Tunnel to the inspector: run it alone, or set one up
|
|
35
40
|
* kraftwerk doctor preflight: harness CLIs, docker, workflows, env
|
|
@@ -61,7 +66,15 @@ const pkg = JSON.parse(await readFile(new URL("../../package.json", import.meta.
|
|
|
61
66
|
const program = new Command()
|
|
62
67
|
.name("kraftwerk")
|
|
63
68
|
.description("kraftwerk — agentic workspace for teams: agents, skills, knowledge, workflows, and the inspector UI")
|
|
64
|
-
.version(pkg.version)
|
|
69
|
+
.version(pkg.version)
|
|
70
|
+
// The project's .env, before any command runs (and so before `kraftwerk
|
|
71
|
+
// ui` spawns its server, and again in that server on every restart). A
|
|
72
|
+
// broken kraftwerk.yml is the command's own error to report, not the hook's.
|
|
73
|
+
.hook("preAction", async () => {
|
|
74
|
+
const project = await resolveProject(process.cwd()).catch(() => null);
|
|
75
|
+
if (project)
|
|
76
|
+
await applyDotenv(project.root);
|
|
77
|
+
});
|
|
65
78
|
const agentLabel = (workflow) => workflow.meta.agents
|
|
66
79
|
.map((a) => {
|
|
67
80
|
const where = [a.harness && a.harness !== "claude" ? a.harness : "", a.protocol === "acp" ? "acp" : ""]
|
|
@@ -269,6 +282,7 @@ runs
|
|
|
269
282
|
});
|
|
270
283
|
registerKnowledgeCommands(program);
|
|
271
284
|
registerRoutineCommands(program);
|
|
285
|
+
registerWorkspaceCommands(program);
|
|
272
286
|
registerProjectCommands(program);
|
|
273
287
|
registerRepoCommands(program);
|
|
274
288
|
registerVibeableCommands(program);
|
package/dist/cli/projects.d.ts
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
|
-
/**
|
|
3
|
-
* `kraftwerk projects` — every project that ever ran the inspector on this
|
|
4
|
-
* machine (~/.kraftwerk/projects), joined with what is running right now.
|
|
5
|
-
* The answer to "where did I start that UI, and how do I get it back":
|
|
6
|
-
*
|
|
7
|
-
* kraftwerk projects list: name, root, running/stopped
|
|
8
|
-
* kraftwerk projects start <ref> relaunch `kraftwerk ui` in that root, detached
|
|
9
|
-
* kraftwerk projects stop <ref> SIGTERM a running UI (also ones started in a terminal)
|
|
10
|
-
* kraftwerk projects forget <ref> drop the record (the folder stays)
|
|
11
|
-
*
|
|
12
|
-
* <ref> is a project name, the root's folder name, the root path, or a
|
|
13
|
-
* port / localhost:port for running instances that recorded no root.
|
|
14
|
-
*/
|
|
15
|
-
export declare const fmtAgo: (iso?: string) => string;
|
|
16
2
|
export declare function registerProjectCommands(program: Command): void;
|