@byokit/herdr 0.1.10 → 0.2.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/CHANGELOG.md +9 -0
- package/README.md +46 -1
- package/dist/agents.d.ts +9 -1
- package/dist/agents.js +143 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/kit.d.ts +2 -1
- package/dist/kit.js +3 -0
- package/dist/types.d.ts +20 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.2.0 (2026-09-30)
|
|
6
|
+
|
|
7
|
+
- `HerdrKit.agentStatus(kinds)` (B5): per-kind onboarding readiness — installed plus CLI
|
|
8
|
+
sign-in (`yes`/`no`/`unknown`) from each CLI's own non-secret status command (`claude auth
|
|
9
|
+
status`, Codex `app-server` `account/read`; `unknown` where a CLI has none), install and
|
|
10
|
+
sign-in hint words, and the extra install dirs (mise shims, `~/.local/bin`, Homebrew) moved
|
|
11
|
+
in from muxr's PATH probe. Pi reads `installed: false` with `installs on first start`. The
|
|
12
|
+
command runner is injectable for tests; credential files are never read.
|
|
13
|
+
|
|
5
14
|
## 0.1.10 (2026-09-30)
|
|
6
15
|
|
|
7
16
|
- Dependency update: pins @byokit/relay 0.4.2.
|
package/README.md
CHANGED
|
@@ -149,7 +149,8 @@ persistent grant store, and the phone page above.
|
|
|
149
149
|
|
|
150
150
|
| Export | What it does |
|
|
151
151
|
|---|---|
|
|
152
|
-
| `HerdrKit` (`@byokit/herdr`) | The host-side kit, in `adopt` or `own` mode: `start`/`stop`, `state`, `snapshot`/`onChange`, `startAgent`, `prompt`, `sendKeys`, `wait`, `read`, `blocked`/`onBlocked`/`answer`, `closePane`/`closeTab`/`closeWorkspace`, `agentKinds`, `installedAgentKinds`, `terminal`, `onEvent`, `statusWatchReady`, and the pass-throughs `call`, `subscribe` and `cli` |
|
|
152
|
+
| `HerdrKit` (`@byokit/herdr`) | The host-side kit, in `adopt` or `own` mode: `start`/`stop`, `state`, `snapshot`/`onChange`, `startAgent`, `prompt`, `sendKeys`, `wait`, `read`, `blocked`/`onBlocked`/`answer`, `closePane`/`closeTab`/`closeWorkspace`, `agentKinds`, `installedAgentKinds`, `agentStatus`, `terminal`, `onEvent`, `statusWatchReady`, and the pass-throughs `call`, `subscribe` and `cli` |
|
|
153
|
+
| `agentStatus`, `agentProbePath`, `extraPathDirs`, `runStatusCommand` (`@byokit/herdr`) | Onboarding readiness: per-kind install + CLI sign-in without a Herdr connection (see below) |
|
|
153
154
|
| `HERDR_VERSION`, `HERDR_PROTOCOL` | The pinned Herdr release (`0.9.1`) and the protocol the kit speaks (`22`) |
|
|
154
155
|
| `words`, `agentWords`, `stateWords`, `WORDS` | Plain sentences for agent statuses and kit states |
|
|
155
156
|
| `herdrLink` (`@byokit/herdr/link`) | The host side of the `hd.*` link ops, spread into `Host.open`; scopes each grant to its workspaces and can push sealed approval notices through a relay |
|
|
@@ -168,6 +169,50 @@ Types (`HerdrKitOptions`, `HerdrState`, `StartAgent`, `PromptReceipt`, `BlockedA
|
|
|
168
169
|
- `own` runs the Herdr binary the app names, in an app-owned state directory.
|
|
169
170
|
|
|
170
171
|
Helpers cover the common paths (start an agent, deliver a prompt with a receipt, watch blocked agents, exact closes).
|
|
172
|
+
|
|
173
|
+
## Agent readiness
|
|
174
|
+
|
|
175
|
+
`kit.agentStatus(kinds)` reports, per kind, whether the agent's CLI is installed and whether
|
|
176
|
+
it is signed in — the onboarding agents-and-pickers check. It needs no Herdr connection: it
|
|
177
|
+
probes the local machine. Install detection reuses `installedAgentKinds` over the host PATH plus
|
|
178
|
+
the extra install dirs a service PATH omits (`extraPathDirs`: `~/.local/bin`, the mise shims,
|
|
179
|
+
`~/.npm-global/bin`, Homebrew and the system dirs — the set muxr probed before this kit did).
|
|
180
|
+
Sign-in comes only from each CLI's own documented non-secret status command, with a 10 s timeout;
|
|
181
|
+
a kind whose CLI has none, or whose command gives no answer, reads `unknown`. Credential files
|
|
182
|
+
are never opened, read or statted — only the signed-in boolean is kept. Herdr auto-installs Pi
|
|
183
|
+
via mise on first start, so `pi` always reads `installed: false` with `installs on first start`
|
|
184
|
+
rather than a missing-install error.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { HerdrKit } from '@byokit/herdr';
|
|
188
|
+
|
|
189
|
+
const kit = new HerdrKit({ mode: 'adopt', bin: 'herdr', socketPath: '/tmp/herdr.sock' });
|
|
190
|
+
// Local probe only — the kit need not be started.
|
|
191
|
+
console.log(await kit.agentStatus(['pi', 'claude', 'codex']));
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
[
|
|
196
|
+
{ kind: 'pi', installed: false, signedIn: 'unknown', installHint: 'installs on first start' },
|
|
197
|
+
{ kind: 'claude', installed: true, signedIn: 'yes',
|
|
198
|
+
installHint: 'Install the claude command, then check again.' },
|
|
199
|
+
{ kind: 'codex', installed: true, signedIn: 'no',
|
|
200
|
+
installHint: 'Install the codex command, then check again.',
|
|
201
|
+
signInHint: 'On this computer run `codex`, sign in, then come back.' },
|
|
202
|
+
]
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
| Kind | Status command | Why this one |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `claude` | `claude auth status` (JSON `loggedIn`) | The CLI's own documented status; a signed-out CLI still prints its JSON, so only an empty answer reads `unknown`. |
|
|
208
|
+
| `codex` | `codex app-server` with a pipelined `initialize` + `account/read` round | Codex exposes sign-in only over its app-server protocol; a record `account` in the second answer means signed in. |
|
|
209
|
+
| `pi` | none (Herdr installs it via mise) | No probe: always `installed: false`, `installs on first start`. |
|
|
210
|
+
| any other kind | none | No documented non-secret status command, so `unknown` until the kit covers it. |
|
|
211
|
+
|
|
212
|
+
Options: `{ path, aliases }` as in `installedAgentKinds`; `{ run }` injects the command runner
|
|
213
|
+
(`(command, args, { stdin, timeoutMs }) => Promise<{ stdout } | undefined>`, so tests use fakes);
|
|
214
|
+
`{ timeoutMs }` bounds each probe. `signInHint` rides kinds the kit knows how to check whenever they
|
|
215
|
+
are not signed in; `installHint` always rides along.
|
|
171
216
|
`call` and `subscribe` are typed pass-throughs to the complete socket API, and `cli()` reaches the full CLI.
|
|
172
217
|
|
|
173
218
|
`start()` is non-fatal: if Herdr is down it rejects (state `failed`, e.g. `failed/socket`) and may be called again
|
package/dist/agents.d.ts
CHANGED
|
@@ -5,4 +5,12 @@ export declare function createAgents(ctx: {
|
|
|
5
5
|
call: Call;
|
|
6
6
|
snapshot(): HerdrSnapshot;
|
|
7
7
|
reread(paneId: string): Promise<void>;
|
|
8
|
-
}): Pick<HerdrKit, 'startAgent' | 'prompt' | 'sendKeys' | 'wait' | 'read' | 'agentKinds' | 'installedAgentKinds'>;
|
|
8
|
+
}): Pick<HerdrKit, 'startAgent' | 'prompt' | 'sendKeys' | 'wait' | 'read' | 'agentKinds' | 'installedAgentKinds' | 'agentStatus'>;
|
|
9
|
+
export declare function extraPathDirs(home?: string): string[];
|
|
10
|
+
export declare function agentProbePath(path?: string[], home?: string): string[];
|
|
11
|
+
export declare function runStatusCommand(command: string, args: string[], o?: {
|
|
12
|
+
stdin?: string;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
stdout: string;
|
|
16
|
+
} | undefined>;
|
package/dist/agents.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Exact param spellings come from the generated v0.9.1 table (6.7); where muxr and the schema
|
|
3
3
|
// disagree the schema wins. `pane.split` takes `target_pane_id` (muxr agrees), and `agent.start`
|
|
4
4
|
// has no `env` param — a start's env belongs to the placement create/split call (src/generated/methods.ts).
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
5
6
|
import { accessSync, constants as fsConstants } from 'node:fs';
|
|
6
|
-
import {
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
import { delimiter, join } from 'node:path';
|
|
7
9
|
const PROMPTABLE = ['idle', 'working', 'blocked', 'done'];
|
|
8
10
|
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
9
11
|
// `agent.start` lands while the fresh pane is still at its shell prompt: the server answers
|
|
@@ -190,5 +192,144 @@ export function createAgents(ctx) {
|
|
|
190
192
|
}
|
|
191
193
|
return installed;
|
|
192
194
|
}
|
|
193
|
-
|
|
195
|
+
// B5: the extra install dirs muxr's `executableOnPath` probes past PATH (a GUI daemon's
|
|
196
|
+
// inherited PATH omits them), moved into the kit so the host probe is trusted.
|
|
197
|
+
function installedSet(kinds, o) {
|
|
198
|
+
return new Set(installedAgentKinds(kinds.filter((k) => k !== 'pi'), o));
|
|
199
|
+
}
|
|
200
|
+
async function agentStatus(kinds, o) {
|
|
201
|
+
const path = o?.path ?? agentProbePath();
|
|
202
|
+
const run = o?.run ?? runStatusCommand;
|
|
203
|
+
const timeoutMs = o?.timeoutMs ?? STATUS_TIMEOUT_MS;
|
|
204
|
+
const installed = installedSet(kinds, { path, ...(o?.aliases === undefined ? {} : { aliases: o.aliases }) });
|
|
205
|
+
return Promise.all(kinds.map(async (kind) => {
|
|
206
|
+
// Herdr auto-installs Pi via mise on first start, so PATH presence is not the signal:
|
|
207
|
+
// Pi always reads not-installed with the readiness words instead of a missing-install error.
|
|
208
|
+
if (kind === 'pi')
|
|
209
|
+
return { kind, installed: false, signedIn: 'unknown', installHint: PI_INSTALL_HINT };
|
|
210
|
+
const binary = o?.aliases?.[kind]?.[0] ?? kind;
|
|
211
|
+
const installHint = `Install the ${binary} command, then check again.`;
|
|
212
|
+
if (!installed.has(kind))
|
|
213
|
+
return { kind, installed: false, signedIn: 'unknown', installHint };
|
|
214
|
+
const probe = STATUS_PROBES[kind];
|
|
215
|
+
if (probe === undefined)
|
|
216
|
+
return { kind, installed: true, signedIn: 'unknown', installHint };
|
|
217
|
+
let answer;
|
|
218
|
+
try {
|
|
219
|
+
answer = await run(probe.command, probe.args, { ...(probe.stdin === undefined ? {} : { stdin: probe.stdin }), timeoutMs });
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
answer = undefined;
|
|
223
|
+
}
|
|
224
|
+
const signedIn = answer === undefined ? 'unknown' : probe.parse(answer.stdout);
|
|
225
|
+
return { kind, installed: true, signedIn, installHint,
|
|
226
|
+
...(signedIn === 'yes' ? {} : { signInHint: SIGNIN_HINTS[kind] ?? `Sign in to ${kind} on this computer, then check again.` }) };
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
return { startAgent, prompt, sendKeys, wait, read, agentKinds, installedAgentKinds, agentStatus };
|
|
230
|
+
}
|
|
231
|
+
// Extra install dirs muxr's `executableOnPath`
|
|
232
|
+
// (`apps/host/src/agent/infrastructure/herdrSessionSource.ts`) probes past PATH: user-install
|
|
233
|
+
// dirs a service or GUI daemon's inherited PATH omits — mise shims (Herdr installs Pi through
|
|
234
|
+
// mise), `~/.local/bin`, npm-global, Homebrew and the system dirs.
|
|
235
|
+
export function extraPathDirs(home = homedir()) {
|
|
236
|
+
return [join(home, '.local', 'bin'), join(home, '.local', 'share', 'mise', 'shims'),
|
|
237
|
+
join(home, '.npm-global', 'bin'), '/opt/homebrew/bin', '/usr/local/bin', '/usr/bin', '/bin'];
|
|
238
|
+
}
|
|
239
|
+
// The full install probe: the host's own PATH plus the extra dirs, de-duplicated.
|
|
240
|
+
export function agentProbePath(path = (process.env.PATH ?? '').split(delimiter), home = homedir()) {
|
|
241
|
+
return [...new Set([...path, ...extraPathDirs(home)])].filter((dir) => dir !== '');
|
|
242
|
+
}
|
|
243
|
+
const STATUS_TIMEOUT_MS = 10_000;
|
|
244
|
+
const PI_INSTALL_HINT = 'installs on first start';
|
|
245
|
+
const SIGNIN_HINTS = {
|
|
246
|
+
claude: 'On this computer run `claude`, sign in, then come back.',
|
|
247
|
+
codex: 'On this computer run `codex`, sign in, then come back.',
|
|
248
|
+
};
|
|
249
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
250
|
+
// Per-kind CLI status commands (see the README table for why each one). Every probe asks the
|
|
251
|
+
// CLI itself and keeps only the signed-in boolean — email, plan and everything secret stays out.
|
|
252
|
+
// A kind with no documented non-secret status command has no entry and reads 'unknown'.
|
|
253
|
+
const STATUS_PROBES = {
|
|
254
|
+
// `claude auth status` prints JSON with `loggedIn` (muxr's planIdentity reads the same);
|
|
255
|
+
// a signed-out CLI still prints its JSON, so only an empty answer means 'unknown'.
|
|
256
|
+
claude: { command: 'claude', args: ['auth', 'status'], parse: (stdout) => {
|
|
257
|
+
let status;
|
|
258
|
+
try {
|
|
259
|
+
status = JSON.parse(stdout);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return 'unknown';
|
|
263
|
+
}
|
|
264
|
+
if (!isRecord(status))
|
|
265
|
+
return 'unknown';
|
|
266
|
+
return status.loggedIn === true ? 'yes' : 'no';
|
|
267
|
+
} },
|
|
268
|
+
// Codex exposes sign-in only over its app-server protocol, so the probe pipes a pipelined
|
|
269
|
+
// `initialize` + `account/read` round (same method muxr's planIdentity uses) and reads the
|
|
270
|
+
// second answer: a record `account` means signed in, its absence means signed out.
|
|
271
|
+
codex: { command: 'codex', args: ['app-server'],
|
|
272
|
+
stdin: '{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byokit","version":"1"}}}\n{"id":2,"method":"account/read","params":{}}\n',
|
|
273
|
+
parse: (stdout) => {
|
|
274
|
+
for (const line of stdout.split('\n')) {
|
|
275
|
+
let message;
|
|
276
|
+
try {
|
|
277
|
+
message = JSON.parse(line);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (isRecord(message) && message.id === 2) {
|
|
283
|
+
return isRecord(message.result) && isRecord(message.result.account) ? 'yes' : 'no';
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return 'unknown';
|
|
287
|
+
} },
|
|
288
|
+
};
|
|
289
|
+
// Default runner: one bounded spawn per probe, stdin piped when the protocol needs it (codex).
|
|
290
|
+
// Failures (missing binary, timeout, non-empty stderr, empty stdout) read as no answer — never throw.
|
|
291
|
+
export async function runStatusCommand(command, args, o) {
|
|
292
|
+
return new Promise((resolve) => {
|
|
293
|
+
let done = false;
|
|
294
|
+
const finish = (value) => {
|
|
295
|
+
if (done)
|
|
296
|
+
return;
|
|
297
|
+
done = true;
|
|
298
|
+
clearTimeout(timer);
|
|
299
|
+
resolve(value);
|
|
300
|
+
};
|
|
301
|
+
let child;
|
|
302
|
+
try {
|
|
303
|
+
child = spawn(command, args, { stdio: ['pipe', 'pipe', 'ignore'], timeout: o?.timeoutMs ?? STATUS_TIMEOUT_MS });
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
finish(undefined);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
let out = '';
|
|
310
|
+
const timer = setTimeout(() => { child.kill('SIGKILL'); finish(undefined); }, (o?.timeoutMs ?? STATUS_TIMEOUT_MS) + 500);
|
|
311
|
+
child.on('error', () => finish(undefined));
|
|
312
|
+
const stdout = child.stdout;
|
|
313
|
+
const stdin = child.stdin;
|
|
314
|
+
if (stdout === null || stdin === null) {
|
|
315
|
+
finish(undefined);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
stdout.setEncoding('utf8');
|
|
319
|
+
stdout.on('data', (chunk) => {
|
|
320
|
+
out += chunk;
|
|
321
|
+
if (out.length > 64 * 1024) {
|
|
322
|
+
child.kill('SIGKILL');
|
|
323
|
+
finish(undefined);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
child.on('close', () => finish(out.trim() === '' ? undefined : { stdout: out.slice(0, 64 * 1024) }));
|
|
327
|
+
stdin.on('error', () => { });
|
|
328
|
+
try {
|
|
329
|
+
if (o?.stdin !== undefined)
|
|
330
|
+
stdin.write(o.stdin);
|
|
331
|
+
stdin.end();
|
|
332
|
+
}
|
|
333
|
+
catch { /* a dead stdin settles through close/error */ }
|
|
334
|
+
});
|
|
194
335
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { HERDR_VERSION, HERDR_PROTOCOL } from './constants.ts';
|
|
2
2
|
export { HerdrKit } from './kit.ts';
|
|
3
3
|
export { agentWords, stateWords, words, WORDS, type WordKey } from './words.ts';
|
|
4
|
-
export
|
|
4
|
+
export { agentProbePath, extraPathDirs, runStatusCommand } from './agents.ts';
|
|
5
|
+
export type { AgentCliSignIn, AgentReadiness, AgentStatusOptions, AgentStatusRunner, AgentRef, AgentStatus, BlockedAgent, HerdrEvent, HerdrEventName, HerdrEventOf, HerdrKitOptions, HerdrMethod, HerdrMethods, HerdrParams, HerdrProtocolRange, HerdrResult, HerdrSnapshot, HerdrState, HerdrSubscription, HerdrSubscribeStop, HerdrTransport, PromptReceipt, StartAgent, TerminalSession, } from './types.ts';
|
package/dist/index.js
CHANGED
package/dist/kit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentRef, AgentStatus, BlockedAgent, HerdrEvent, HerdrEventName, HerdrEventOf, HerdrKitOptions, HerdrMethod, HerdrParams, HerdrResult, HerdrSnapshot, HerdrState, HerdrSubscription, HerdrSubscribeStop, PromptReceipt, StartAgent, TerminalSession } from './types.ts';
|
|
1
|
+
import type { AgentReadiness, AgentStatusOptions, AgentRef, AgentStatus, BlockedAgent, HerdrEvent, HerdrEventName, HerdrEventOf, HerdrKitOptions, HerdrMethod, HerdrParams, HerdrResult, HerdrSnapshot, HerdrState, HerdrSubscription, HerdrSubscribeStop, PromptReceipt, StartAgent, TerminalSession } from './types.ts';
|
|
2
2
|
export declare class HerdrKit {
|
|
3
3
|
private readonly supervisor;
|
|
4
4
|
private transport?;
|
|
@@ -98,4 +98,5 @@ export declare class HerdrKit {
|
|
|
98
98
|
path: string[];
|
|
99
99
|
aliases?: Record<string, string[]>;
|
|
100
100
|
}): string[];
|
|
101
|
+
agentStatus(kinds: readonly string[], o?: AgentStatusOptions): Promise<AgentReadiness[]>;
|
|
101
102
|
}
|
package/dist/kit.js
CHANGED
|
@@ -450,4 +450,7 @@ export class HerdrKit {
|
|
|
450
450
|
closeWorkspace(workspaceId) { return closeWorkspace(this.callAny, workspaceId); }
|
|
451
451
|
agentKinds() { return this.agents.agentKinds(); }
|
|
452
452
|
installedAgentKinds(kinds, o) { return this.agents.installedAgentKinds(kinds, o); }
|
|
453
|
+
// Onboarding readiness (B5): a local PATH probe plus each installed CLI's own status
|
|
454
|
+
// command — no Herdr connection needed, credential files never read.
|
|
455
|
+
agentStatus(kinds, o) { return this.agents.agentStatus(kinds, o); }
|
|
453
456
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -47,6 +47,26 @@ export type HerdrEvent = {
|
|
|
47
47
|
export type { HerdrMethods, HerdrMethod, HerdrParams, HerdrResult } from './generated/methods.ts';
|
|
48
48
|
export type { HerdrEvents, HerdrEventName, HerdrEventOf, HerdrSubscription } from './generated/events.ts';
|
|
49
49
|
export type AgentStatus = 'idle' | 'working' | 'blocked' | 'done' | 'unknown';
|
|
50
|
+
export type AgentCliSignIn = 'yes' | 'no' | 'unknown';
|
|
51
|
+
export type AgentReadiness = {
|
|
52
|
+
kind: string;
|
|
53
|
+
installed: boolean;
|
|
54
|
+
signedIn: AgentCliSignIn;
|
|
55
|
+
installHint: string;
|
|
56
|
+
signInHint?: string;
|
|
57
|
+
};
|
|
58
|
+
export type AgentStatusRunner = (command: string, args: string[], o?: {
|
|
59
|
+
stdin?: string;
|
|
60
|
+
timeoutMs?: number;
|
|
61
|
+
}) => Promise<{
|
|
62
|
+
stdout: string;
|
|
63
|
+
} | undefined>;
|
|
64
|
+
export type AgentStatusOptions = {
|
|
65
|
+
path?: string[];
|
|
66
|
+
aliases?: Record<string, string[]>;
|
|
67
|
+
run?: AgentStatusRunner;
|
|
68
|
+
timeoutMs?: number;
|
|
69
|
+
};
|
|
50
70
|
export type AgentRef = {
|
|
51
71
|
paneId: string;
|
|
52
72
|
name?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byokit/herdr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Drive the Herdr on this computer — workspaces, tabs, panes, agents and blocked-approval answers — from an app, or hand it to a phone over @byokit/link.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|