@kybernesis/create 0.5.1 → 0.6.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/dist/cli.js CHANGED
@@ -22,6 +22,7 @@ function initOptions(rest) {
22
22
  const subs = flag(rest, 'subagents');
23
23
  return {
24
24
  engineer: rest.includes('--engineer'),
25
+ studio: rest.includes('--studio'),
25
26
  channel: flag(rest, "channel"),
26
27
  host: flag(rest, "host"),
27
28
  subagents: subs === undefined ? undefined : subs.split(',').map((s) => s.trim()).filter(Boolean),
@@ -59,6 +60,7 @@ ${bold("kyb")} — Kybernesis agent scaffolder & FDE toolkit
59
60
  --host=<kind> ${dim("vercel|exe (default: vercel)")}
60
61
  --subagents=a,b ${dim("department subagents (default: none)")}
61
62
  --engineer ${dim("add the engineer layer: workshop sandbox + vision dev loop")}
63
+ --studio ${dim("wire for KYBER Studio: local execution + management routes")}
62
64
  --yes ${dim("no prompts; take flags and defaults")}
63
65
  ${bold("kyb doctor")} preflight checks (keys, issuer, envs, discovery)
64
66
  ${bold("kyb skills")} install/refresh the FDE skill suite for Claude Code
package/dist/doctor.js CHANGED
@@ -238,6 +238,31 @@ export async function doctor() {
238
238
  }
239
239
  }
240
240
  }
241
+ // ── KYBER Studio wiring ────────────────────────────────────────────────
242
+ const hasLocal = existsSync(join(cwd, "agent/tools/local_shell.ts"));
243
+ const hasManage = existsSync(join(cwd, "agent/channels/kyb.ts"));
244
+ if (hasLocal) {
245
+ // Without the relay secret the tools compile, appear in the tool list, and
246
+ // fail at the moment the user asks for something — the worst time to learn
247
+ // a deployment is incomplete.
248
+ if (process.env.LOCAL_EXEC_AGENT_SECRET) {
249
+ add("pass", "local execution is configured (LOCAL_EXEC_AGENT_SECRET set)");
250
+ }
251
+ else {
252
+ add("fail", "local execution has no LOCAL_EXEC_AGENT_SECRET", "the local_* tools will be offered to the model and fail on first use; set the shared secret the control-plane relay expects");
253
+ }
254
+ }
255
+ if (hasManage) {
256
+ // manage authorizes with the caller's control-plane grant, so it needs to
257
+ // know which agent it IS before it can check one.
258
+ if (process.env.KYBERNESIS_AGENT) {
259
+ add("pass", "management routes can resolve this agent's grants");
260
+ }
261
+ else {
262
+ add("fail", "management routes have no KYBERNESIS_AGENT", "KYBER Studio cannot install or write routines here: the agent cannot check a grant for a name it does not know");
263
+ }
264
+ add("warn", "management routes need a writable working copy", "installing edits this repo and rebuilds; on a read-only serverless bundle the routes refuse. Set restartCommand in agent/channels/kyb.ts or an install will not take effect");
265
+ }
241
266
  // ── engineer subagent (build capability scoped to a subagent) ──────────
242
267
  const builderDir = join(cwd, "agent/subagents/builder");
243
268
  if (existsSync(builderDir)) {
package/dist/init.d.ts CHANGED
@@ -1,6 +1,15 @@
1
1
  import { type ChannelKind, type HostKind } from "./templates.js";
2
2
  export interface InitOptions {
3
3
  engineer?: boolean;
4
+ /**
5
+ * Wire this agent for KYBER Studio: local execution on the user's own machine,
6
+ * and management routes so Studio can install capabilities and write routines.
7
+ *
8
+ * Off by default. Both let a client reach further than chat does — one onto
9
+ * the user's laptop, one into the agent's own repository — so they are a
10
+ * deliberate choice rather than something an engagement gets by accident.
11
+ */
12
+ studio?: boolean;
4
13
  /** Chat surface. Default "none" — add later with `kyb add channel`. */
5
14
  channel?: ChannelKind;
6
15
  /** Where the agent runs. Default "vercel". */
package/dist/init.js CHANGED
@@ -17,6 +17,7 @@ const ENGINEER_ITEMS_VERCEL = ["connection/vercel"];
17
17
  const DEFAULT_MODEL = "anthropic/claude-sonnet-5";
18
18
  export async function init(rawName, options = {}) {
19
19
  const engineer = options.engineer === true;
20
+ const studio = options.studio === true;
20
21
  const nonInteractive = options.yes === true;
21
22
  const name = slug(rawName ?? (await ask("Agent name (kebab-case)?", "acme-agent")));
22
23
  if (!name) {
@@ -70,6 +71,18 @@ export async function init(rawName, options = {}) {
70
71
  for (const item of plan.registryItems) {
71
72
  run("npx", ["eve", "add", item, "--overwrite"], { cwd: dir, allowFail: true });
72
73
  }
74
+ if (studio) {
75
+ // Two separate items on purpose: `local` lets the agent act on the USER'S
76
+ // machine (consent per effect, granted on the desktop); `manage` lets a
77
+ // client change THIS AGENT — its dependencies and its source. Different
78
+ // blast radius, so an agent can have one without the other.
79
+ console.log(bold("\n2b2 KYBER Studio: local execution + management routes …"));
80
+ for (const item of ["local", "manage"]) {
81
+ const ok = run("npx", ["eve", "add", item, "--overwrite"], { cwd: dir, allowFail: true });
82
+ if (!ok)
83
+ console.log(yellow(` ! ${item} did not install cleanly — re-run: npx eve add ${item}`));
84
+ }
85
+ }
73
86
  const engPlan = engineer ? engineerPlan(host, DEFAULT_MODEL) : null;
74
87
  if (engPlan) {
75
88
  console.log(bold("\n2c Engineer subagent: workshop sandbox + vision dev loop …"));
@@ -131,7 +144,7 @@ export async function init(rawName, options = {}) {
131
144
  }
132
145
  }
133
146
  console.log(bold("\n5/6 Env template + hermetic eval script …"));
134
- writeFileSync(join(dir, ".env.example"), envExample(name, depts, issuer, plan.env));
147
+ writeFileSync(join(dir, ".env.example"), envExample(name, depts, issuer, plan.env, host, DEFAULT_MODEL));
135
148
  const pkgPath = join(dir, "package.json");
136
149
  const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
137
150
  pkg.scripts = { ...pkg.scripts, eval: evalScript(name, depts) };
@@ -148,6 +161,7 @@ export async function init(rawName, options = {}) {
148
161
  "self-testing (evals)",
149
162
  channel === "none" ? null : `${channel} channel`,
150
163
  host === "exe" ? "exe.dev host" : null,
164
+ studio ? "KYBER Studio (local execution + management routes)" : null,
151
165
  engineer ? "engineer subagent (workshop + vision loop)" : null,
152
166
  depts.length ? `${depts.length} dept subagent(s)` : null,
153
167
  ].filter(Boolean);
@@ -7,7 +7,7 @@ export declare function subagentInstructionsMd(dept: string): string;
7
7
  export declare function subagentArcanaTs(dept: string): string;
8
8
  export declare function rootArcanaTs(): string;
9
9
  export declare function evalFileTs(displayName: string, depts: string[]): string;
10
- export declare function envExample(name: string, depts: string[], issuer: string, channelEnv?: string[]): string;
10
+ export declare function envExample(name: string, depts: string[], issuer: string, channelEnv?: string[], host?: "vercel" | "exe", model?: string): string;
11
11
  export declare function evalScript(name: string, depts: string[]): string;
12
12
  export type ChannelKind = "none" | "slack" | "imessage" | "telegram" | "discord" | "web";
13
13
  export declare const CHANNEL_KINDS: ChannelKind[];
package/dist/templates.js CHANGED
@@ -120,22 +120,46 @@ export default kybernesisBaseline({
120
120
  ${depts.length ? ` routing: [\n${routing}\n ],\n` : ""}});
121
121
  `;
122
122
  }
123
- export function envExample(name, depts, issuer, channelEnv = []) {
123
+ /**
124
+ * Env every self-hosted agent needs and cannot infer.
125
+ *
126
+ * Both of these have bitten a real deployment. EXE_MODEL must match the LLM
127
+ * integration actually attached — a ChatGPT subscription serves OpenAI models,
128
+ * so an Anthropic code default fails against it. EXE_VM_NAME has no default at
129
+ * all by design: guessing a host would hand a user a working link into another
130
+ * agent's machine.
131
+ */
132
+ function exeEnvBlock(name, model) {
133
+ return `# Self-hosted host + model (@kybernesis/exe)
134
+ # EXE_MODEL must match the LLM integration you attached to the VM. A ChatGPT
135
+ # subscription serves OpenAI models; the code default will fail against one.
136
+ # Set it explicitly rather than relying on ${model}.
137
+ EXE_MODEL="${model}"
138
+ # Preview URLs are built from this. There is no default on purpose.
139
+ EXE_VM_NAME="${name}"
140
+
141
+ `;
142
+ }
143
+ export function envExample(name, depts, issuer, channelEnv = [], host = "vercel", model = "") {
124
144
  const deptVars = depts
125
145
  .map((d) => {
126
146
  const upper = d.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
127
147
  return `# ARCANA_${upper}_API_KEY="kb_..."\n# ARCANA_${upper}_WORKSPACE="${name}-${d}"`;
128
148
  })
129
149
  .join("\n");
150
+ const header = host === "exe"
151
+ ? `# Real values live in .env.local ON THE HOST. \`eve start\` does NOT read it the
152
+ # way \`eve dev\` does — scripts/eve-server.sh exports it into the process.`
153
+ : `# Real values belong in Vercel envs (prod/preview Sensitive); \`eve deploy\`
154
+ # overwrites .env.local from the development environment on every deploy.`;
130
155
  return `# ── Kybernesis agent environment ─────────────────────────────────────
131
- # Real values belong in Vercel envs (prod/preview Sensitive); \`eve deploy\`
132
- # overwrites .env.local from the development environment on every deploy.
156
+ ${header}
133
157
 
134
158
  # Control-plane governance (@kybernesis/enterprise)
135
159
  KYBERNESIS_ISSUER="${issuer}"
136
160
  KYBERNESIS_AGENT="${name}"
137
161
 
138
- ${channelEnv.length ? `# Channel\n${channelEnv.join("\n")}\n\n` : ""}# Arcana memory (@kybernesis/arcana) — one workspace + scoped kb_ key per brain
162
+ ${host === "exe" ? exeEnvBlock(name, model) : ""}${channelEnv.length ? `# Channel\n${channelEnv.join("\n")}\n\n` : ""}# Arcana memory (@kybernesis/arcana) — one workspace + scoped kb_ key per brain
139
163
  # ARCANA_API_KEY="kb_..."
140
164
  # ARCANA_COMPANY_WORKSPACE="${name}-company"
141
165
  # ARCANA_DM_WORKSPACE="${name}-company"
@@ -360,8 +384,11 @@ export default defineSandbox({
360
384
  revalidationKey: () => "kybernesis-workshop-v5-docker",
361
385
  async bootstrap({ use }) {
362
386
  const sandbox = await use();
387
+ // Base image is Debian-family; refresh indexes before installing browser deps.
363
388
  await sandbox.run({ command: "apt-get update" });
364
389
  await sandbox.run({ command: "npm install -g pnpm" });
390
+ // Explicit package.json rather than \`npm init -y\`: init derives the name from
391
+ // the directory, and npm rejects names starting with a dot (".shot").
365
392
  await sandbox.run({
366
393
  command:
367
394
  "mkdir -p /workspace/.shot && cd /workspace/.shot && echo '{\\"name\\":\\"kyb-shot\\",\\"private\\":true}' > package.json && npm install playwright",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kybernesis/create",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent — plus doctor and upgrade.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -44,6 +44,9 @@ npm create @kybernesis acme-atlas -- --engineer
44
44
  # ChatGPT/LLM subscription paying for inference. See section 11:
45
45
  npm create @kybernesis acme-atlas -- --host=exe --engineer
46
46
 
47
+ # …or, when the client wants the desktop app (KYBER Studio) — see section 12:
48
+ npm create @kybernesis acme-atlas -- --studio
49
+
47
50
  # 3. (Optional, for repeated use) put `kyb` on the PATH for the whole engagement:
48
51
  npm install -g @kybernesis/create
49
52
  ```
@@ -1990,7 +1993,91 @@ Nothing here can be borrowed from another agent or another account.
1990
1993
  against the client's `-eval` workspace, and a live turn on the real surface —
1991
1994
  sent from the client's own device, not yours.
1992
1995
 
1993
- ## 12. Known gapsstate these plainly, do not sell around them
1996
+ ## 12. KYBER Studiothe desktop surface
1997
+
1998
+ Slack and iMessage reach an agent where the client already works. KYBER Studio
1999
+ is the third door: a desktop app for people who do not live in a chat tool, and
2000
+ the only surface where an agent can work on the user's own files.
2001
+
2002
+ Reach for it when the client says any of: *"not everyone here uses Slack"*,
2003
+ *"I want it on my laptop"*, *"can it look at our repo"*, or when the pilot
2004
+ involves someone technical who will hand the agent real work.
2005
+
2006
+ ### 12.1 What it is
2007
+
2008
+ - **The same agent.** Studio does not run anything. It talks to the agent you
2009
+ deployed — same memory, same tools, same subagents. Nothing to deploy twice.
2010
+ - **Governed by the same grants.** Sign-in is control-plane device flow, so
2011
+ desktop access is the grant you already manage. Revoke it and the desktop goes
2012
+ with it.
2013
+ - **Optionally hands and eyes.** With `@kybernesis/local` the agent can search,
2014
+ read, edit, write, and run commands on the user's machine, with consent.
2015
+ - **Optionally self-modifying.** With `@kybernesis/manage` the client can
2016
+ install capabilities and write routines from the app instead of asking you.
2017
+
2018
+ ### 12.2 The two packages, and why they are separate
2019
+
2020
+ | | What it lets happen | Installed on |
2021
+ | --- | --- | --- |
2022
+ | `@kybernesis/local` | The agent acts on the USER's machine | the agent |
2023
+ | `@kybernesis/manage` | A client changes THE AGENT — deps and source | the agent |
2024
+
2025
+ Different blast radius, so they are separate items an engagement chooses
2026
+ independently. A reporting agent might want `local` and never `manage`. Neither
2027
+ is installed by default, because both let a client reach further than chat does.
2028
+
2029
+ ```bash
2030
+ kyb init acme-agent --host=exe --studio # both, at scaffold time
2031
+ npx eve add local # or either one, later
2032
+ npx eve add manage
2033
+ ```
2034
+
2035
+ `kyb doctor` checks both: the relay secret for local, and `KYBERNESIS_AGENT` for
2036
+ manage, since it cannot check a grant for a name it does not know.
2037
+
2038
+ ### 12.3 Prerequisites, in order
2039
+
2040
+ 1. **The agent is registered in the control plane** and the pilot users are
2041
+ granted. Studio lists exactly what a user has a grant for — an agent that is
2042
+ registered but ungranted is invisible, which is the correct behaviour and a
2043
+ confusing one if you forget you did it.
2044
+ 2. **The agent has a URL on file.** Studio reads `/api/me/agents`; an agent with
2045
+ no deployment URL appears as unreachable rather than silently missing.
2046
+ 3. **For `manage`: a writable working copy.** Installing edits the repo and
2047
+ rebuilds, so it works on a VM and refuses on a read-only serverless bundle,
2048
+ with that reason. Set `restartCommand` in `agent/channels/kyb.ts` or an
2049
+ install completes without taking effect.
2050
+ 4. **For `local`: the relay secret** (`LOCAL_EXEC_AGENT_SECRET`) matching the
2051
+ control plane.
2052
+
2053
+ ### 12.4 What consent looks like for the user
2054
+
2055
+ Studio asks per **effect** — run a command, read a file, write a file, list a
2056
+ directory — not per tool, and not per turn. Approving `read-file` once covers
2057
+ every tool that reads a file out, which is why adding a tool later cannot dodge
2058
+ a decision the user already made.
2059
+
2060
+ The default is ask. A working folder can be set, but it is a starting directory
2061
+ rather than a fence: permission to act on the machine is granted once, and the
2062
+ agent may work wherever it is asked to. Whether it builds in its own sandbox or
2063
+ on the user's files is decided by the ask, not by a mode — the same way a
2064
+ colleague knows "build me a demo" from "look at my repo".
2065
+
2066
+ ### 12.5 State this plainly to the client
2067
+
2068
+ - **Local execution is not yet a governed capability.** The agent authenticates
2069
+ to the relay with a shared secret, so anyone holding it can reach a connected
2070
+ desktop in that org. It must become its own revocable grant, separate from
2071
+ "may talk to this agent". Do not install `local` at a client who would treat
2072
+ that as a surprise.
2073
+ - **Reading a file sends it to the model.** Execution is local; the reasoning is
2074
+ not. Fine for most work, and a conversation to have before a Studio points at
2075
+ a regulated repository.
2076
+ - **Management routes let a client change the agent.** That is the point, and it
2077
+ means the repository is no longer only yours. Agree who reviews what Studio
2078
+ writes — routines land as source files, so a normal review works.
2079
+
2080
+ ## 13. Known gaps — state these plainly, do not sell around them
1994
2081
 
1995
2082
  Being straight about these is a feature. Clients have met vendors who were not.
1996
2083