@pugi/cli 0.1.0-beta.4 → 0.1.0-beta.5

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.
@@ -577,18 +577,6 @@ export class ReplSession {
577
577
  await this.dispatchStop(verdict.persona);
578
578
  return verdict;
579
579
  }
580
- case 'delegate': {
581
- // α7.5 Phase 1: surface the dispatch intent inline. The actual
582
- // wire shape (POST /api/pugi/sessions/:id/delegate) requires the
583
- // SDK transport extension that ships alongside this PR; the
584
- // REPL session module wires the call when the matching transport
585
- // method lands (paired CLI follow-up). Today we surface the
586
- // delegation intent in the transcript so the operator sees the
587
- // verdict echo for muscle-memory before the round-trip lights up.
588
- this.appendSystemLine(`delegate ${verdict.persona}: ${verdict.brief.length > 80 ? `${verdict.brief.slice(0, 77)}...` : verdict.brief}`);
589
- this.appendSystemLine('Run `pugi delegate <slug> "<brief>"` from a fresh shell while the REPL transport wiring lands.');
590
- return verdict;
591
- }
592
580
  case 'dispatch': {
593
581
  await this.dispatchBrief(verdict.brief);
594
582
  return verdict;
@@ -1394,8 +1382,21 @@ export class ReplSession {
1394
1382
  void this.recreateSessionSilently();
1395
1383
  return;
1396
1384
  }
1385
+ // α6.14.4 CEO dogfood 2026-05-25 (parity with Claude Code):
1386
+ // collapse the repeated "Stream interrupted (fetch failed).
1387
+ // Reconnecting." spam. The status bar already shows
1388
+ // connection='reconnecting' AND the attempt counter; pushing
1389
+ // a fresh transcript row per attempt fills the screen with
1390
+ // noise. Only emit the system line for the FIRST drop of a
1391
+ // run; subsequent reconnects update the status bar silently
1392
+ // until either success (clears the connection state) or the
1393
+ // give-up path in scheduleReconnect prints the final hint.
1394
+ const wasOnline = this.state.connection === 'on_watch'
1395
+ || this.state.connection === 'connecting';
1397
1396
  this.patch({ connection: 'reconnecting' });
1398
- this.appendSystemLine(`Stream interrupted (${this.errorMessage(error)}). Reconnecting.`);
1397
+ if (wasOnline) {
1398
+ this.appendSystemLine(`Stream interrupted (${this.errorMessage(error)}). Reconnecting...`);
1399
+ }
1399
1400
  this.scheduleReconnect();
1400
1401
  },
1401
1402
  });
@@ -52,7 +52,6 @@ export const SLASH_COMMAND_HELP = Object.freeze([
52
52
  // Workforce dispatch
53
53
  { name: 'brief', args: '<text>', gloss: 'Dispatch a brief to the workforce', group: 'Workforce dispatch' },
54
54
  { name: 'agents', args: '', gloss: 'List the on-watch agent roster', group: 'Workforce dispatch' },
55
- { name: 'delegate', args: '<slug> <brief>', gloss: 'Dispatch a brief to one Tier 1 specialist (α7.5)', group: 'Workforce dispatch' },
56
55
  { name: 'stop', args: '<persona>', gloss: 'Stop one agent by persona slug', group: 'Workforce dispatch' },
57
56
  { name: 'jobs', args: '', gloss: 'List background jobs', group: 'Workforce dispatch' },
58
57
  { name: 'ask', args: '<question>', gloss: 'Surface a yes/no modal locally (α6.3 forcing question)', group: 'Workforce dispatch' },
@@ -136,35 +135,6 @@ export function parseSlashCommand(input) {
136
135
  case 'roster': {
137
136
  return { kind: 'roster' };
138
137
  }
139
- case 'delegate': {
140
- // tail must start with the persona slug followed by the brief.
141
- // Slug accepts only the closed-set lowercase ASCII pattern the
142
- // server-side persona registry enforces; anything else surfaces
143
- // as a usage error so the operator sees the typo before the
144
- // round-trip.
145
- const space = tail.indexOf(' ');
146
- if (space === -1 || space === 0) {
147
- return {
148
- kind: 'error',
149
- message: 'Usage: /delegate <slug> <one-sentence brief>',
150
- };
151
- }
152
- const persona = tail.slice(0, space).toLowerCase();
153
- const brief = tail.slice(space + 1).trim();
154
- if (!/^[a-z_]+$/.test(persona)) {
155
- return {
156
- kind: 'error',
157
- message: `/delegate slug must be lowercase ASCII; got '${persona}'`,
158
- };
159
- }
160
- if (brief.length === 0) {
161
- return {
162
- kind: 'error',
163
- message: 'Usage: /delegate <slug> <one-sentence brief>',
164
- };
165
- }
166
- return { kind: 'delegate', persona, brief };
167
- }
168
138
  case 'stop':
169
139
  case 'kill': {
170
140
  if (tail.length === 0) {
@@ -17,10 +17,8 @@ import { toolRegistry, toolSchemaBundleHashInput } from '../tools/registry.js';
17
17
  import { webFetchTool } from '../tools/web-fetch.js';
18
18
  import { emptyIndex, rebuildIndex, readIndex, upsertArtifact, writeIndex, } from '../core/index-store.js';
19
19
  import { signatureForPlanReview } from '../core/repl/ask.js';
20
- import { buildRuntimeConfig, fetchPersonaRoster, loadRuntimeConfig, openPugiSession, pollDeviceFlow, pugiHandoffBundleSchema, pugiSyncDryRunPlanSchema, pugiSyncPrivacyModeSchema, pugiSyncRequestSchema, pugiSyncUploadPlanSchema, pugiTripleReviewRequestSchema, startDeviceFlow, submitDelegate, submitSync, submitTripleReview, } from '@pugi/sdk';
20
+ import { buildRuntimeConfig, loadRuntimeConfig, pollDeviceFlow, pugiHandoffBundleSchema, pugiSyncDryRunPlanSchema, pugiSyncPrivacyModeSchema, pugiSyncRequestSchema, pugiSyncUploadPlanSchema, pugiTripleReviewRequestSchema, startDeviceFlow, submitSync, submitTripleReview, } from '@pugi/sdk';
21
21
  import { PUGI_TAGLINE } from '@pugi/personas';
22
- import { resolveRoster, renderRosterTable } from './commands/roster.js';
23
- import { runDelegateCommand } from './commands/delegate.js';
24
22
  import { clearApiKey, DEFAULT_API_URL, listStoredCredentials, maskApiKey, normalizeApiUrl, purgeAllCredentials, readCredentialsFile, resolveActiveCredential, storeApiKey, switchActiveAccount, } from '../core/credentials.js';
25
23
  import { runDeployCommand } from '../commands/deploy.js';
26
24
  import { runJobsCommand } from '../commands/jobs.js';
@@ -30,6 +28,11 @@ import { runUndoCommand } from './commands/undo.js';
30
28
  import { runBudgetCommand } from './commands/budget.js';
31
29
  import { runSkillsCommand } from './commands/skills.js';
32
30
  import { runAgentsCommand } from './commands/agents.js';
31
+ // α7.7 lsp/patch/worktree command modules ship behind the α7.7
32
+ // implementer PR (in-flight). The dispatchers below print a clean
33
+ // "deferred" message so `pugi --help` still lists them without the
34
+ // REPL crashing at module load. When α7.7 lands, restore the real
35
+ // imports + delete the inline stubs.
33
36
  import { resolveWorkspaceLabel } from '../core/repl/workspace-context.js';
34
37
  import { runReviewConsensus } from './commands/review-consensus.js';
35
38
  import { FtsSyntaxError, SqliteSessionStore, resolveProjectStoreDir } from '../core/repl/store/index.js';
@@ -46,7 +49,7 @@ import { dispatchEdit, } from '../core/edits/index.js';
46
49
  * packages/pugi-sdk/package.json); the publish workflow validates the
47
50
  * three are in lockstep.
48
51
  */
49
- const PUGI_CLI_VERSION = "0.1.0-beta.4";
52
+ const PUGI_CLI_VERSION = "0.1.0-beta.5";
50
53
  const handlers = {
51
54
  accounts,
52
55
  agents: dispatchAgents,
@@ -55,7 +58,6 @@ const handlers = {
55
58
  budget: dispatchBudget,
56
59
  code: runEngineTask('code'),
57
60
  config: dispatchConfig,
58
- delegate: dispatchDelegate,
59
61
  deploy: dispatchDeploy,
60
62
  doctor,
61
63
  explain: runEngineTask('explain'),
@@ -67,12 +69,13 @@ const handlers = {
67
69
  jobs,
68
70
  login,
69
71
  logout,
72
+ lsp: dispatchLsp,
73
+ patch: dispatchPatch,
70
74
  plan: runEngineTask('plan'),
71
75
  'plan-review': dispatchPlanReview,
72
76
  privacy: dispatchPrivacy,
73
77
  review,
74
78
  resume,
75
- roster: dispatchRoster,
76
79
  sessions,
77
80
  skills: dispatchSkills,
78
81
  sync,
@@ -80,6 +83,7 @@ const handlers = {
80
83
  version,
81
84
  web: dispatchWeb,
82
85
  whoami,
86
+ worktree: dispatchWorktree,
83
87
  };
84
88
  /**
85
89
  * α6.3 `pugi ask "<question>"` — surface the office-hours forcing-question
@@ -250,59 +254,6 @@ async function dispatchPrivacy(args, flags, _session) {
250
254
  writeOutput: (payload, text) => writeOutput(flags, payload, text),
251
255
  });
252
256
  }
253
- /**
254
- * `pugi roster` - α7.5 Phase 1.
255
- *
256
- * List the live Tier 1 personas with display name, role, and routing
257
- * tag. Walks the remote /api/pugi/sessions/roster endpoint when a
258
- * credential is available; falls back to the local @pugi/personas
259
- * roster when offline so the operator can still see who is on the team.
260
- */
261
- async function dispatchRoster(_args, flags, _session) {
262
- const credential = resolveActiveCredential();
263
- const config = credential
264
- ? buildRuntimeConfig({ apiUrl: credential.apiUrl, apiKey: credential.apiKey })
265
- : null;
266
- const { rows, warning } = await resolveRoster(config);
267
- const payload = {
268
- ok: true,
269
- personas: rows,
270
- warning,
271
- };
272
- const text = (warning ? `# warning: ${warning}\n\n` : '') +
273
- renderRosterTable(rows);
274
- writeOutput(flags, payload, text);
275
- }
276
- /**
277
- * `pugi delegate <slug> "<brief>"` - α7.5 Phase 1.
278
- *
279
- * Open a fresh REPL session and POST the brief to one Tier 1 persona,
280
- * bypassing Mira's coordinator pass. Non-interactive: the CLI prints
281
- * the dispatch id on success and exits; the operator (or a script) can
282
- * subscribe to the session stream separately if they want the live
283
- * lifecycle. Interactive operators use `/delegate` from inside the REPL
284
- * instead so the dispatch lifecycle surfaces inline.
285
- */
286
- async function dispatchDelegate(args, flags, _session) {
287
- await runDelegateCommand(args, {
288
- workspaceCwd: process.cwd(),
289
- writeOutput: (payload, text) => writeOutput(flags, payload, text),
290
- resolveConfig: () => {
291
- const credential = resolveActiveCredential();
292
- if (!credential)
293
- return null;
294
- return buildRuntimeConfig({ apiUrl: credential.apiUrl, apiKey: credential.apiKey });
295
- },
296
- fetchRoster: fetchPersonaRoster,
297
- submitDelegate,
298
- openSession: async (config, workspaceCwd) => {
299
- const result = await openPugiSession(config, { workspaceCwd });
300
- if (result.status === 'ok')
301
- return { sessionId: result.response.sessionId };
302
- return { error: `${result.status}: ${result.message}` };
303
- },
304
- });
305
- }
306
257
  async function dispatchUndo(args, flags, session) {
307
258
  await runUndoCommand(args, {
308
259
  workspaceRoot: process.cwd(),
@@ -371,6 +322,49 @@ async function dispatchWeb(args, flags, _session) {
371
322
  }
372
323
  writeOutput(flags, result, `# ${result.title}\n# ${result.url}\n# fetched ${result.fetched_at}\n\n${result.content_md}`);
373
324
  }
325
+ /**
326
+ * α7.7: `pugi lsp <op> <file> [args]` — direct LSP queries. Delegated
327
+ * to the standalone runner in `./commands/lsp.ts` so the giant cli.ts
328
+ * dispatch table stays narrow. The runner spawns + tears down the LSP
329
+ * server per invocation (no daemon yet — that ships in α7.7b).
330
+ */
331
+ async function dispatchLsp(_args, flags, _session) {
332
+ const msg = 'pugi lsp ships in alpha 7.7 (in-flight). Run `pugi --help` for current surface.';
333
+ if (flags.json)
334
+ console.log(JSON.stringify({ ok: false, code: 'deferred', message: msg }));
335
+ else
336
+ console.log(msg);
337
+ process.exitCode = 6;
338
+ }
339
+ /**
340
+ * α7.7: `pugi patch` — apply a unified-diff patch from stdin or a file.
341
+ * Routes through the same security gate as the Layer A/B/C applicators
342
+ * (see `src/core/edits/security-gate.ts`). Exit codes mirror the
343
+ * security taxonomy so CI loops can alert on hostile patches without
344
+ * confusing them with operator typos.
345
+ */
346
+ async function dispatchPatch(_args, flags, _session) {
347
+ const msg = 'pugi patch ships in alpha 7.7 (in-flight). Run `pugi --help` for current surface.';
348
+ if (flags.json)
349
+ console.log(JSON.stringify({ ok: false, code: 'deferred', message: msg }));
350
+ else
351
+ console.log(msg);
352
+ process.exitCode = 6;
353
+ }
354
+ /**
355
+ * α7.7: `pugi worktree <op>` — manual scratch worktree management.
356
+ * The `pugi build` and `pugi review --consensus` paths use the same
357
+ * primitives internally (`createWorktree` / `promoteWorktree`); this
358
+ * surface is the operator escape hatch for debug + experiment flows.
359
+ */
360
+ async function dispatchWorktree(_args, flags, _session) {
361
+ const msg = 'pugi worktree ships in alpha 7.7 (in-flight). Run `pugi --help` for current surface.';
362
+ if (flags.json)
363
+ console.log(JSON.stringify({ ok: false, code: 'deferred', message: msg }));
364
+ else
365
+ console.log(msg);
366
+ process.exitCode = 6;
367
+ }
374
368
  export async function runCli(argv) {
375
369
  const { command, args, flags, isBareInvocation } = parseArgs(argv);
376
370
  // Bare `pugi` on a TTY enters the REPL-by-default agentic session
@@ -584,10 +578,6 @@ async function help(_args, flags, _session) {
584
578
  ' pugi ask "<question>" Surface a yes/no question modal locally.',
585
579
  ' pugi plan-review <task> Generate + present a plan-review modal.',
586
580
  '',
587
- 'Persona dispatch (α7.5):',
588
- ' pugi roster List the live Tier 1 personas + roles.',
589
- ' pugi delegate <slug> "<brief>" Dispatch a brief to one specialist.',
590
- '',
591
581
  'Deploy:',
592
582
  ' pugi deploy --target vercel <vercelProject> --project <id>',
593
583
  ' Trigger a Vercel deployment from the bound Git source.',
@@ -86,14 +86,30 @@ export async function renderRepl(options) {
86
86
  // Kick off the connect; the Repl renders the connecting state until
87
87
  // the session pushes `connection: 'on_watch'` from the SSE onOpen.
88
88
  void session.start();
89
+ // α6.14.4 CEO dogfood 2026-05-25 (parity with Claude Code): enter
90
+ // the terminal's alternate screen buffer so the REPL renders on a
91
+ // fresh "screen" the operator cannot scroll above. On exit, leave
92
+ // restores the previous terminal contents - the conversation does
93
+ // not pollute the operator's shell history. Skipped under --no-tty
94
+ // and when stdout is not a TTY (pipe/CI), where the escapes would
95
+ // appear as literal characters.
96
+ // ORDER MATTERS (beta.2 follow-up): alt-screen enter MUST happen
97
+ // BEFORE the chafa mascot pre-print. Reversed, the alt-screen clear
98
+ // wiped the freshly-painted pug and the operator saw nothing.
99
+ const supportsAltScreen = process.stdout.isTTY === true;
100
+ if (supportsAltScreen) {
101
+ process.stdout.write('\x1b[?1049h');
102
+ process.stdout.write('\x1b[H');
103
+ }
89
104
  // α6.14.2 wave 5: paint the chafa-baked brand-pug ANSI render to
90
- // stdout BEFORE Ink mounts. Ink's layout engine would mis-measure
91
- // the truecolor escape sequences, so the pug must land verbatim.
92
- // The flag is passed into <Repl /> so the splash component knows to
93
- // skip its own hand-crafted PUG_MASCOT column — otherwise the
94
- // operator sees both the chafa pug AND the ASCII fallback stacked.
95
- // When skipSplash is true (operator opted out via --no-splash), we
96
- // suppress the pre-print too so the boot stays silent.
105
+ // stdout BEFORE Ink mounts (but AFTER alt-screen enter). Ink's
106
+ // layout engine would mis-measure the truecolor escape sequences,
107
+ // so the pug must land verbatim. The flag is passed into <Repl />
108
+ // so the splash component knows to skip its own hand-crafted
109
+ // PUG_MASCOT column - otherwise the operator sees both the chafa
110
+ // pug AND the ASCII fallback stacked. When skipSplash is true
111
+ // (operator opted out via --no-splash), we suppress the pre-print
112
+ // too so the boot stays silent.
97
113
  const mascotPrePrinted = options.skipSplash === true ? false : printPugMascotPreInk(process.stdout);
98
114
  const instance = render(React.createElement(Repl, {
99
115
  session,
@@ -102,10 +118,26 @@ export async function renderRepl(options) {
102
118
  hideToolStream: options.hideToolStream === true,
103
119
  mascotPrePrinted,
104
120
  }));
121
+ const restoreAltScreen = () => {
122
+ if (supportsAltScreen) {
123
+ try {
124
+ process.stdout.write('\x1b[?1049l');
125
+ }
126
+ catch {
127
+ /* shutdown race — terminal already detached */
128
+ }
129
+ }
130
+ };
131
+ // Make sure we leave the alt screen on abrupt exits too. Without
132
+ // this the operator's shell stays "frozen" on the Pugi splash.
133
+ process.once('exit', restoreAltScreen);
134
+ process.once('SIGINT', restoreAltScreen);
135
+ process.once('SIGTERM', restoreAltScreen);
105
136
  try {
106
137
  await instance.waitUntilExit();
107
138
  }
108
139
  finally {
140
+ restoreAltScreen();
109
141
  session.close();
110
142
  if (store) {
111
143
  try {
package/dist/tui/repl.js CHANGED
@@ -49,7 +49,12 @@ export function Repl(props) {
49
49
  // α6.14 wave 3: boot splash visible until first input, first
50
50
  // `agent.spawned` event, or 10s idle. The host gates the initial
51
51
  // visibility on `--no-splash` / PUGI_SKIP_SPLASH via `skipSplash`.
52
- const [splashVisible, setSplashVisible] = useState(props.skipSplash !== true);
52
+ // α6.14.6 CEO dogfood 2026-05-25: default splash to HIDDEN at boot
53
+ // (parity with Claude Code's minimal one-line banner). Operator can
54
+ // opt back in via `/splash` slash. The chafa pug pre-print + header
55
+ // line already give the brand cue without the multi-row Plan/Model/
56
+ // Tenant block crowding the top.
57
+ const [splashVisible, setSplashVisible] = useState(false);
53
58
  const dismissSplash = useCallback(() => setSplashVisible(false), []);
54
59
  // α6.14 wave 3: workspace context snapshot for the status bar. We
55
60
  // read once at mount and freeze; a brand-new PUGI.md or skill is
@@ -178,16 +183,15 @@ export function Repl(props) {
178
183
  return undefined;
179
184
  return props.session.cancel();
180
185
  }, [props.session, modalActive]);
181
- // α6.14.5 CEO dogfood 2026-05-25 (parity with Claude Code): the
182
- // input box must pin to the BOTTOM of the alt-screen viewport, not
183
- // float right under the conversation. Beta.3 attempt at full-height
184
- // broke keystroke focus (raw echo at row 79). The right pattern is
185
- // minHeight on the root + flexGrow on the conversation pane so the
186
- // empty space sits ABOVE the input, not below it. The input then
187
- // captures all keystrokes because it is the only Ink-focusable
188
- // surface adjacent to the cursor row.
186
+ // α6.14.5 CEO dogfood 2026-05-25 (parity with Claude Code): input
187
+ // box pinned to alt-screen BOTTOM, conversation grows above it.
188
+ // Beta.3's height={rows} fix broke keystroke focus - raw echo at
189
+ // viewport bottom. The right pattern is minHeight on the root +
190
+ // flexGrow=1 on the MainArea Box: empty alt-screen lives ABOVE the
191
+ // input, and the input stays the sole focusable surface adjacent
192
+ // to the cursor row, so all keystrokes route through it.
189
193
  const altScreenRows = process.stdout.rows ?? 24;
190
- return (_jsxs(Box, { flexDirection: "column", paddingX: 1, minHeight: altScreenRows, children: [props.updateBanner ? _jsx(UpdateBanner, { result: props.updateBanner }) : null, splashVisible ? (_jsx(ReplSplash, { cliVersion: state.cliVersion, workspaceLabel: state.workspaceLabel, plan: props.splashPlan, model: props.splashModel, tenant: props.splashTenant, onDismiss: dismissSplash, mascotPrePrinted: props.mascotPrePrinted === true })) : null, _jsx(Header, { state: state }), _jsx(Box, { flexDirection: "column", marginTop: 1, flexGrow: 1, children: overlay === 'help' ? (_jsx(HelpOverlay, {})) : overlay === 'roster' ? (_jsx(RosterOverlay, {})) : overlay === 'farewell' ? (_jsx(FarewellOverlay, {})) : (_jsx(MainArea, { state: state, personaNames: personaNames, nowEpochMs: tickNow, hideToolStream: props.hideToolStream === true, toolStreamCollapsed: toolStreamCollapsed })) }), state.pendingAsk ? (_jsx(Box, { marginTop: 1, children: _jsx(AskModal, { tag: state.pendingAsk, onResolve: handleAskResolve }) })) : null, state.pendingPlanReview ? (_jsx(Box, { marginTop: 1, children: _jsx(PlanReviewModal, { tag: state.pendingPlanReview, onResolve: handlePlanReviewResolve }) })) : null, _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [overlay === 'farewell' || modalActive ? null : (_jsx(InputBox, { onSubmit: handleSubmit, onExit: handleExit, onCancel: handleCancel, now: props.now,
194
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, minHeight: altScreenRows, children: [props.updateBanner ? _jsx(UpdateBanner, { result: props.updateBanner }) : null, splashVisible ? (_jsx(ReplSplash, { cliVersion: state.cliVersion, workspaceLabel: state.workspaceLabel, plan: props.splashPlan, model: props.splashModel, tenant: props.splashTenant, onDismiss: dismissSplash, mascotPrePrinted: props.mascotPrePrinted === true })) : null, _jsx(Header, { state: state }), _jsx(Box, { flexDirection: "column", marginTop: 1, flexGrow: 1, justifyContent: "flex-end", children: overlay === 'help' ? (_jsx(HelpOverlay, {})) : overlay === 'roster' ? (_jsx(RosterOverlay, {})) : overlay === 'farewell' ? (_jsx(FarewellOverlay, {})) : (_jsx(MainArea, { state: state, personaNames: personaNames, nowEpochMs: tickNow, hideToolStream: props.hideToolStream === true, toolStreamCollapsed: toolStreamCollapsed })) }), state.pendingAsk ? (_jsx(Box, { marginTop: 1, children: _jsx(AskModal, { tag: state.pendingAsk, onResolve: handleAskResolve }) })) : null, state.pendingPlanReview ? (_jsx(Box, { marginTop: 1, children: _jsx(PlanReviewModal, { tag: state.pendingPlanReview, onResolve: handlePlanReviewResolve }) })) : null, _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [overlay === 'farewell' || modalActive ? null : (_jsx(InputBox, { onSubmit: handleSubmit, onExit: handleExit, onCancel: handleCancel, now: props.now,
191
195
  // Slug from process.cwd() (full path) so two workspaces with
192
196
  // the same basename do not share history. state.workspaceLabel
193
197
  // is the basename only. Codex review P2.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pugi/cli",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.5",
4
4
  "description": "Pugi CLI - terminal-native software execution system",
5
5
  "homepage": "https://pugi.io",
6
6
  "repository": {
@@ -52,7 +52,7 @@
52
52
  "undici": "^8.3.0",
53
53
  "zod": "^3.23.0",
54
54
  "@pugi/personas": "0.1.2",
55
- "@pugi/sdk": "0.1.0-beta.4"
55
+ "@pugi/sdk": "0.1.0-beta.5"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/node": "^22.0.0",