0101-agents 0.1.7 → 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.
Files changed (2) hide show
  1. package/bin/cli.js +284 -80
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
- // 0101-agents CLI — installs and updates curated Claude Code agents.
2
+ // 0101-agents CLI — installs and updates 0101 skillsets and agent templates.
3
3
  //
4
4
  // Commands:
5
5
  // 0101-agents login [<license-key>]
6
6
  // 0101-agents logout
7
7
  // 0101-agents whoami
8
- // 0101-agents install <agent> [--force]
9
- // 0101-agents update <agent> [-f]
8
+ // 0101-agents install <set> --to <agent> install a skillset into an agent
9
+ // 0101-agents install base --as <name> create a new agent from the base template
10
+ // 0101-agents update <set> --to <agent> update a skillset inside an agent
11
+ // 0101-agents update <agent> [-f] update an agent's template (preserves data/)
10
12
  // 0101-agents list
11
13
  // 0101-agents help
12
14
 
@@ -81,9 +83,14 @@ async function fetchManifest(agent) {
81
83
  if (res.status === 401) die('License invalid. Run: 0101-agents login')
82
84
  if (res.status === 403) {
83
85
  const body = await res.json().catch(() => ({}))
84
- die(body.error || 'License does not cover this agent.')
86
+ die((body.error || 'License does not cover this artifact.') +
87
+ '\n Skillsets must be added to your account first: https://0101.fyi/catalog')
88
+ }
89
+ if (res.status === 404) {
90
+ die(`Not found: ${agent}\n` +
91
+ ' Available skillsets: https://0101.fyi/catalog\n' +
92
+ ' New agent: 0101-agents install base --as <name>')
85
93
  }
86
- if (res.status === 404) die(`Agent not found: ${agent}`)
87
94
  if (!res.ok) die(`Manifest fetch failed: ${res.status} ${res.statusText}`)
88
95
  return res.json()
89
96
  }
@@ -199,6 +206,138 @@ async function prompt(question) {
199
206
  try { return (await rl.question(question)).trim() } finally { rl.close() }
200
207
  }
201
208
 
209
+ // ─── sets ────────────────────────────────────────────────────────────────────
210
+
211
+ function getFlag(args, name) {
212
+ const i = args.indexOf(name)
213
+ return i !== -1 && args[i + 1] && !args[i + 1].startsWith('-') ? args[i + 1] : null
214
+ }
215
+
216
+ // Per-agent record of installed sets: ~/0101/<agent>/.0101-sets.json
217
+ // { "<set-slug>": { "version": "0.0.2", "skills": ["ad-creative", ...] } }
218
+ // (Older entries may be plain version strings — normalized on read.)
219
+ function readSetsFile(agent) {
220
+ try {
221
+ const raw = JSON.parse(readFileSync(join(agentInstallDir(agent), '.0101-sets.json'), 'utf8'))
222
+ for (const [k, v] of Object.entries(raw)) {
223
+ if (typeof v === 'string') raw[k] = { version: v, skills: [] }
224
+ }
225
+ return raw
226
+ } catch {
227
+ return {}
228
+ }
229
+ }
230
+
231
+ function setVersion(sets, slug) {
232
+ return sets[slug]?.version ?? null
233
+ }
234
+
235
+ function writeSetsFile(agent, sets) {
236
+ writeFileSync(
237
+ join(agentInstallDir(agent), '.0101-sets.json'),
238
+ JSON.stringify(sets, null, 2) + '\n',
239
+ )
240
+ }
241
+
242
+ // Fetch a set artifact and install its skills into the agent's .claude/skills/.
243
+ //
244
+ // Safety model:
245
+ // - Each skillset OWNS the skill folders it shipped (recorded per-set in
246
+ // .0101-sets.json). On install/update those folders are clean-replaced
247
+ // (delete + copy), so files removed upstream don't linger.
248
+ // - Skill folders the set DOESN'T ship are never touched — the agent's own
249
+ // skills and other skillsets are safe.
250
+ // - Name collision (a folder exists that this set didn't previously own,
251
+ // e.g. a hand-made skill with the same name): backed up to
252
+ // ~/0101/.backups/ first, then replaced, with a warning.
253
+ // - A skill the set used to ship but no longer does is removed (it was ours).
254
+ async function installSetInto(setSlug, agent) {
255
+ const agentDir = agentInstallDir(agent)
256
+ if (!existsSync(agentDir)) {
257
+ die(`${agent} is not installed at ${agentDir}.\n` +
258
+ ` Create it first: 0101-agents install base --as ${agent}`)
259
+ }
260
+
261
+ const manifest = await fetchManifest(setSlug)
262
+ const zipPath = join(tmpdir(), `0101-set-${setSlug}-${manifest.latest}.zip`)
263
+ await downloadZip(manifest.download_url, zipPath)
264
+
265
+ const tmpDir = join(tmpdir(), `0101-set-${setSlug}-${Date.now()}`)
266
+ unzipInto(zipPath, tmpDir)
267
+ rmSync(zipPath, { force: true })
268
+
269
+ const skillsSrc = join(tmpDir, '.claude', 'skills')
270
+ if (!existsSync(skillsSrc)) {
271
+ rmSync(tmpDir, { recursive: true, force: true })
272
+ die(`${setSlug} is not a skillset (no .claude/skills/ in the artifact).`)
273
+ }
274
+
275
+ const newSkills = readdirSync(skillsSrc)
276
+ .filter(d => statSync(join(skillsSrc, d)).isDirectory())
277
+ const skillsDest = join(agentDir, '.claude', 'skills')
278
+ mkdirSync(skillsDest, { recursive: true })
279
+
280
+ const sets = readSetsFile(agent)
281
+ const prevSkills = sets[setSlug]?.skills ?? []
282
+
283
+ // Collisions: folders that exist but weren't shipped by this set before.
284
+ const foreign = newSkills.filter(
285
+ s => existsSync(join(skillsDest, s)) && !prevSkills.includes(s),
286
+ )
287
+ // Skills this set used to ship but no longer does (removed upstream).
288
+ const dropped = prevSkills.filter(
289
+ s => !newSkills.includes(s) && existsSync(join(skillsDest, s)),
290
+ )
291
+ // Back up anything we're about to replace-with-different or delete, so a
292
+ // hand-made collision or an upstream removal is always recoverable.
293
+ const toBackup = [...foreign, ...dropped]
294
+ if (toBackup.length) {
295
+ mkdirSync(BACKUPS_DIR, { recursive: true })
296
+ const ts = new Date().toISOString().replace(/[:.]/g, '-')
297
+ const backupPath = join(BACKUPS_DIR, `${agent}-skills-${ts}.tar.gz`)
298
+ execSync(
299
+ `tar -czf "${backupPath}" -C "${skillsDest}" ${toBackup.map(s => `"${s}"`).join(' ')}`,
300
+ { stdio: 'inherit' },
301
+ )
302
+ if (foreign.length) {
303
+ console.log(dim(` ⚠ Replacing existing skill(s) ${foreign.join(', ')} ` +
304
+ `(backed up → ${backupPath})`))
305
+ }
306
+ if (dropped.length) {
307
+ console.log(dim(` Backup of removed skill(s) → ${backupPath}`))
308
+ }
309
+ }
310
+
311
+ // Clean-replace every skill this set ships.
312
+ for (const s of newSkills) {
313
+ rmSync(join(skillsDest, s), { recursive: true, force: true })
314
+ execSync(`cp -R "${join(skillsSrc, s)}" "${join(skillsDest, s)}"`)
315
+ }
316
+ // Remove skills this set used to ship but no longer does.
317
+ for (const s of prevSkills.filter(s => !newSkills.includes(s))) {
318
+ rmSync(join(skillsDest, s), { recursive: true, force: true })
319
+ console.log(dim(` − removed ${s} (no longer part of ${setSlug})`))
320
+ }
321
+ rmSync(tmpDir, { recursive: true, force: true })
322
+
323
+ sets[setSlug] = { version: manifest.latest, skills: newSkills }
324
+ writeSetsFile(agent, sets)
325
+ return manifest.latest
326
+ }
327
+
328
+ // The 0101 agent manages itself (its own update skill) and is downloaded from
329
+ // the website — it is deliberately NOT installable or updatable via this CLI,
330
+ // so there's exactly one update mechanism per artifact.
331
+ const SELF_MANAGED = new Set(['0101'])
332
+
333
+ function rejectSelfManaged(agent, action) {
334
+ if (SELF_MANAGED.has(agent)) {
335
+ die(`The 0101 agent manages itself — it can't be ${action} via this CLI.\n` +
336
+ ` Download it at https://0101.fyi and open the folder in Claude Code;\n` +
337
+ ` it updates itself from inside.`)
338
+ }
339
+ }
340
+
202
341
  // ─── commands ────────────────────────────────────────────────────────────────
203
342
 
204
343
  async function cmdLogin(args) {
@@ -230,21 +369,44 @@ async function cmdWhoami() {
230
369
  }
231
370
 
232
371
  async function cmdInstall(args) {
233
- const agent = args[0]
234
- if (!agent) die('Usage: 0101-agents install <agent> [--force]')
372
+ const slug = args[0] && !args[0].startsWith('-') ? args[0] : null
373
+ if (!slug) {
374
+ die('Usage: 0101-agents install <set> --to <agent>\n' +
375
+ ' 0101-agents install base --as <name>')
376
+ }
377
+ rejectSelfManaged(slug, 'installed')
378
+ ensureUnzipAvailable()
379
+
380
+ // ── set into an existing agent ──
381
+ const to = getFlag(args, '--to')
382
+ if (to) {
383
+ info(`Installing set ${slug} into ${to}…`)
384
+ const v = await installSetInto(slug, to)
385
+ console.log('')
386
+ ok(`Set ${bold(slug)} ${v} → ${to}`)
387
+ info('New skills load at the agent’s next session start.')
388
+ return
389
+ }
390
+
391
+ // ── whole artifact: the base template (named via --as) or a legacy slug ──
392
+ const as = getFlag(args, '--as')
393
+ if (slug === 'base' && !as) {
394
+ die('The base template needs a name for the new agent:\n' +
395
+ ' 0101-agents install base --as <name>')
396
+ }
397
+ const destName = as || slug
235
398
  const force = args.includes('--force')
236
399
 
237
- ensureUnzipAvailable()
238
- const installDir = agentInstallDir(agent)
400
+ const installDir = agentInstallDir(destName)
239
401
  if (existsSync(installDir) && !force) {
240
402
  die(`${installDir} already exists. Use --force to overwrite (will wipe data/).`)
241
403
  }
242
404
 
243
- info(`Fetching manifest for ${agent}…`)
244
- const manifest = await fetchManifest(agent)
405
+ info(`Fetching manifest for ${slug}…`)
406
+ const manifest = await fetchManifest(slug)
245
407
  info(`Latest: ${manifest.latest}`)
246
408
 
247
- const zipPath = join(tmpdir(), `0101-${agent}-${manifest.latest}.zip`)
409
+ const zipPath = join(tmpdir(), `0101-${slug}-${manifest.latest}.zip`)
248
410
  info(`Downloading…`)
249
411
  await downloadZip(manifest.download_url, zipPath)
250
412
 
@@ -254,32 +416,75 @@ async function cmdInstall(args) {
254
416
  mkdirSync(installDir, { recursive: true })
255
417
  unzipInto(zipPath, installDir)
256
418
  rmSync(zipPath, { force: true })
257
- const localManifest = readManifest(agent)
258
- runPostInstall(agent, localManifest)
259
- writeInstalledVersion(agent, manifest.latest)
419
+ const localManifest = readManifest(destName)
420
+ runPostInstall(destName, localManifest)
421
+ writeInstalledVersion(destName, manifest.latest)
260
422
 
261
423
  console.log('')
262
- ok(`Installed ${bold(agent)} ${manifest.latest} → ${installDir}`)
263
- info(`Start: 0101-agents start ${agent}`)
264
- // The "open in Claude" hint only applies to agent folders. Artifacts with a
265
- // custom launch (manifest.start, e.g. the runner) aren't opened in Claude.
266
- if (!localManifest.start) info(` or: cd ${installDir} && claude`)
424
+ ok(`Installed ${bold(destName)} ${manifest.latest} → ${installDir}`)
425
+ info(`Open it: cd ${installDir} && claude`)
426
+ if (as) info(`Add capabilities: 0101-agents install <set> --to ${destName}`)
267
427
  }
268
428
 
269
429
  async function cmdUpdate(args) {
270
- const agent = args.find((a) => !a.startsWith('-'))
430
+ const slug = args[0] && !args[0].startsWith('-') ? args[0] : null
271
431
  const assumeYes = args.some((a) => ['-f', '--force', '-y', '--yes'].includes(a))
272
- if (!agent) die('Usage: 0101-agents update <agent> [-f]')
273
-
432
+ if (!slug) {
433
+ die('Usage: 0101-agents update <set> --to <agent>\n' +
434
+ ' 0101-agents update <agent> [-f]')
435
+ }
436
+ rejectSelfManaged(slug, 'updated')
274
437
  ensureUnzipAvailable()
438
+
439
+ // ── set inside an agent ──
440
+ const to = getFlag(args, '--to')
441
+ if (to) {
442
+ const sets = readSetsFile(to)
443
+ const current = setVersion(sets, slug)
444
+ if (!current) {
445
+ die(`${slug} is not installed in ${to}.\n` +
446
+ ` Install it: 0101-agents install ${slug} --to ${to}`)
447
+ }
448
+ info(`Installed: ${current}`)
449
+ const manifest = await fetchManifest(slug)
450
+ info(`Latest: ${manifest.latest}`)
451
+ if (current === manifest.latest) {
452
+ ok('Already up to date.')
453
+ return
454
+ }
455
+ const v = await installSetInto(slug, to)
456
+ console.log('')
457
+ ok(`Updated set ${bold(slug)} ${current} → ${v} in ${to}`)
458
+ info('Updated skills load at the agent’s next session start.')
459
+ return
460
+ }
461
+
462
+ // ── whole agent: update its template, preserving data/ ──
463
+ // The remote slug comes from the installed manifest.json (a base-template
464
+ // agent named "ada" still updates from the "base" artifact). Falls back to
465
+ // the folder name for legacy installs.
466
+ //
467
+ // Discontinued persona agents migrate onto the base template on their next
468
+ // update: data/ (all memory) is preserved as always, the persona CLAUDE.md
469
+ // is replaced by the base skeleton, and the agent re-introduces itself in
470
+ // its next conversation. After migration the folder's manifest says "base",
471
+ // so every later update is a normal base update.
472
+ const LEGACY_TO_BASE = new Set(['marketer', 'developer', 'assistant', 'custom'])
473
+ const agent = slug
275
474
  const installDir = agentInstallDir(agent)
276
- if (!existsSync(installDir)) die(`${agent} is not installed. Try: 0101-agents install ${agent}`)
475
+ if (!existsSync(installDir)) die(`${agent} is not installed.`)
476
+ let remoteSlug = readManifest(agent)?.name || agent
477
+ if (LEGACY_TO_BASE.has(remoteSlug)) {
478
+ info(`${remoteSlug} is discontinued — migrating ${agent} to the base template.`)
479
+ info('All memory (data/) is preserved; the agent re-introduces itself next chat.')
480
+ remoteSlug = 'base'
481
+ }
277
482
 
278
483
  const current = installedVersion(agent)
279
- info(`Installed: ${current ?? 'unknown'}`)
484
+ info(`Installed: ${current ?? 'unknown'} (template: ${remoteSlug})`)
280
485
 
281
486
  info(`Fetching manifest…`)
282
- const manifest = await fetchManifest(agent)
487
+ const manifest = await fetchManifest(remoteSlug)
283
488
  info(`Latest: ${manifest.latest}`)
284
489
 
285
490
  if (current === manifest.latest) {
@@ -319,72 +524,75 @@ function cmdList() {
319
524
  const installed = listInstalled()
320
525
  if (installed.length === 0) {
321
526
  info('No agents installed.')
322
- info(`Install one: 0101-agents install <name>`)
527
+ info(`Create one: 0101-agents install base --as <name>`)
323
528
  return
324
529
  }
325
530
  for (const name of installed) {
326
531
  const v = installedVersion(name) ?? dim('?')
327
532
  console.log(` ${bold(name)} ${dim(v)}`)
533
+ const sets = readSetsFile(name)
534
+ for (const [set, rec] of Object.entries(sets)) {
535
+ console.log(` ${dim('· skillset')} ${set} ${dim(rec.version)}`)
536
+ }
328
537
  }
329
538
  }
330
539
 
331
540
  async function cmdStart(args) {
332
541
  const agent = args[0]
333
- if (!agent) die('Usage: 0101-agents start <agent> [-- <claude-args>]')
542
+ if (!agent) die('Usage: 0101-agents start <agent> [--tg] [-- <claude-args>]')
334
543
  const dir = agentInstallDir(agent)
335
544
  if (!existsSync(dir)) {
336
- die(`${agent} is not installed. Try: 0101-agents install ${agent}`)
545
+ die(`${agent} is not installed.`)
337
546
  }
338
547
 
339
- // Best-effort update check. Silently skipped if offline or the server
340
- // misbehaves never blocks the launch.
548
+ // Best-effort update nag. Needs a saved key (the releases API is gated);
549
+ // no key, offline, or any non-200 (revoked, lapsed, artifact not on the
550
+ // server) → skip silently. Launching NEVER depends on this — deliberately
551
+ // not fetchManifest(), whose die() on HTTP errors would kill the launch.
341
552
  try {
342
- const manifest = await fetchManifest(agent)
343
- const current = installedVersion(agent)
344
- if (current && manifest.latest !== current) {
345
- console.log(
346
- dim(`⚠ ${agent} ${manifest.latest} available (run: 0101-agents update ${agent})`),
347
- )
553
+ const key = readConfig().license_key
554
+ if (key) {
555
+ const remoteSlug = readManifest(agent)?.name || agent
556
+ const res = await fetch(`${apiBase()}/api/releases/${encodeURIComponent(remoteSlug)}`, {
557
+ headers: { Authorization: `Bearer ${key}` },
558
+ })
559
+ if (res.ok) {
560
+ const manifest = await res.json()
561
+ const current = installedVersion(agent)
562
+ if (current && manifest.latest !== current) {
563
+ console.log(
564
+ dim(`⚠ ${agent} ${manifest.latest} available (run: 0101-agents update ${agent})`),
565
+ )
566
+ }
567
+ }
348
568
  }
349
569
  } catch {
350
570
  // ignore
351
571
  }
352
572
 
353
573
  // Artifacts can declare how `start` launches via manifest.start. The runner
354
- // sets "npm start"; agents leave it unset and fall through to launching
355
- // Claude Code below.
356
- //
357
- // For the runner specifically we accept an optional `[slug] [cli]` so
358
- // power users can run multiple bots in parallel terminals without touching
359
- // .env. The runner derives STATE_DIR from AGENT_DIR, so per-agent state is
360
- // automatic — we only need to override AGENT_DIR here.
574
+ // (fallback engine) sets "npm start"; agents leave it unset and fall through
575
+ // to launching Claude Code below.
361
576
  //
362
577
  // start runner → npm start (Telegram, AGENT_DIR from .env)
363
- // start runner cli → npm start -- --cli (CLI, AGENT_DIR from .env)
364
- // start runner marketer → npm start (Telegram, AGENT_DIR=~/0101/marketer)
365
- // start runner marketer cli → npm start -- --cli (CLI, AGENT_DIR=~/0101/marketer)
366
- // start runner --cli → same as `start runner cli` (long-form flag)
367
- // start runner -- --cli → same (explicit separator)
578
+ // start runner cli → npm start -- --cli (CLI chat, AGENT_DIR from .env)
579
+ // start runner <name> → npm start (Telegram for that agent)
580
+ // start runner <name> cli → npm start -- --cli
368
581
  const startCmd = readManifest(agent).start
369
582
  if (startCmd) {
370
583
  let extra = args.slice(1)
371
584
  if (extra[0] === '--') extra = extra.slice(1)
372
585
 
373
- // Optional [slug] [mode] positionals — `cli` is a reserved mode keyword
374
- // (no real agent will ever be named "cli"). Anything else that doesn't
375
- // start with `-` is treated as a slug. Verified installed before we spawn.
586
+ // Optional [name] [mode] positionals — `cli` is a reserved mode keyword.
376
587
  let slug = null
377
588
  if (extra[0] && extra[0] !== 'cli' && !extra[0].startsWith('-')) {
378
589
  slug = extra.shift()
379
590
  if (!existsSync(agentInstallDir(slug))) {
380
- die(`${slug} is not installed. Try: 0101-agents install ${slug}`)
591
+ die(`${slug} is not installed.`)
381
592
  }
382
593
  }
383
594
  extra = extra.map(a => (a === 'cli' ? '--cli' : a))
384
595
 
385
- // Override AGENT_DIR per invocation when a slug is given. The runner's
386
- // config.ts derives STATE_DIR from basename(AGENT_DIR), so the per-agent
387
- // state/lockfile/incoming dirs follow automatically.
388
596
  const childEnv = { ...process.env }
389
597
  if (slug) {
390
598
  childEnv.AGENT_DIR = agentInstallDir(slug)
@@ -398,10 +606,7 @@ async function cmdStart(args) {
398
606
  return
399
607
  }
400
608
 
401
- // Everything after the agent name passes through to `claude`. Supports both:
402
- // 0101-agents start marketer --resume
403
- // 0101-agents start marketer -- --resume (explicit separator)
404
- // The `--` is optional; if present, we drop it.
609
+ // Everything after the agent name passes through to `claude`.
405
610
  let rest = args.slice(1)
406
611
  if (rest[0] === '--') rest = rest.slice(1)
407
612
 
@@ -419,8 +624,7 @@ async function cmdStart(args) {
419
624
  ]
420
625
  }
421
626
 
422
- // Hand the terminal over to `claude` with cwd set to the agent dir. When
423
- // claude exits, the user returns to their original shell location.
627
+ // Hand the terminal over to `claude` with cwd set to the agent dir.
424
628
  const child = spawn('claude', claudeArgs, { cwd: dir, stdio: 'inherit' })
425
629
  child.on('error', (e) => {
426
630
  if (e.code === 'ENOENT') {
@@ -432,28 +636,28 @@ async function cmdStart(args) {
432
636
  }
433
637
 
434
638
  function cmdHelp() {
435
- console.log(`0101-agents — install and update Claude Code agents.
639
+ console.log(`0101-agents — install and update 0101 skillsets and agent templates.
436
640
 
437
641
  Commands:
438
- ${bold('login')} [<key>] Save your license key
439
- ${bold('logout')} Forget your license key
440
- ${bold('whoami')} Show current license
441
- ${bold('install')} <agent> [--force] Install an agent
442
- ${bold('update')} <agent> [-f] Update an installed agent (preserves data/). -f skips the prompt
443
- ${bold('start')} <agent> [--tg] [-- args] Open the agent (runs claude in its dir)
444
- --tg adds the right flags to run as a
445
- Telegram channel bot.
446
- ${bold('list')} List installed agents
447
- ${bold('help')} Show this message
642
+ ${bold('login')} [<key>] Save your license key
643
+ ${bold('logout')} Forget your license key
644
+ ${bold('whoami')} Show current license
645
+ ${bold('install')} <set> --to <agent> Install a skillset into an agent
646
+ ${bold('install')} base --as <name> Create a new agent from the base template
647
+ ${bold('update')} <set> --to <agent> Update a skillset inside an agent
648
+ ${bold('update')} <agent> [-f] Update an agent's template (preserves data/)
649
+ ${bold('start')} <agent> [--tg] [-- args] Open the agent (runs claude in its dir);
650
+ --tg runs it as a Telegram channel bot
651
+ ${bold('list')} List installed agents and their skillsets
652
+ ${bold('help')} Show this message
448
653
 
449
654
  Examples:
450
- 0101-agents start marketer Open in Claude Code
451
- 0101-agents start marketer --tg Run as a Telegram channel bot via Claude Code
452
- 0101-agents start marketer --resume Resume the last Claude Code session
453
- 0101-agents start runner Telegram bot via 0101-runner (uses .env)
454
- 0101-agents start runner cli Chat with the agent in this terminal
455
- 0101-agents start runner marketer Run a Telegram bot for marketer (multi-bot)
456
- 0101-agents start runner marketer cli Terminal chat for marketer
655
+ 0101-agents install base --as ada New agent named "ada"
656
+ 0101-agents install website-studio --to ada Teach ada website skills
657
+ 0101-agents update website-studio --to ada Refresh that skillset
658
+ 0101-agents update ada Update ada's base template
659
+
660
+ Open an agent: cd ${INSTALL_ROOT}/<name> && claude
457
661
 
458
662
  Install dir: ${INSTALL_ROOT}
459
663
  Config: ${CONFIG_PATH}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0101-agents",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "0101-agents": "./bin/cli.js"