xtrm-tools 0.7.1 → 0.7.3

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 CHANGED
@@ -7,13 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
- ## [0.7.1] - 2026-04-01
10
+ ## [0.7.1] - 2026-04-02
11
11
 
12
12
  ### Added
13
13
  - **`docs/skills-tier-architecture.md`**: New reference document covering three-tier skills model (default/optional/user), state.json schema, PACK.json schema, runtime active views, and xt skills CLI commands.
14
14
  - **`docs/xtrm-directory.md`**: New reference document for centralized `.xtrm/` directory layout — skills, hooks, extensions, worktrees, reports, registry.json.
15
+ - **`docs/bash-tools.md`**: New reference for specialist bash CLIs (`ghgrep`, `ctx7`, `deepwiki`) including install source, usage examples, and CLI-vs-MCP guidance; README now links and surfaces `ghgrep` under capabilities.
15
16
 
16
17
  ### Changed
18
+ - **Optional packs install behavior docs**: Updated README + skills docs to reflect that `xt install` now pre-populates `.xtrm/skills/optional/`; packs are activated with `xt skills enable <pack>`.
19
+ - **Pi core resolution path docs**: Updated Pi architecture docs to reflect the new symlink location at `.xtrm/extensions/node_modules/@xtrm/pi-core` (replacing legacy `.pi/node_modules/@xtrm/pi-core`).
20
+ - **Default skills catalog docs**: Added `deepwiki`, `specialists-creator`, and `using-specialists` to default-skill listings in README and skills documentation.
17
21
  - **`docs/skills.md`**: Rewritten to cover tier architecture, xt skills CLI, and updated skill catalog (v2.0.0).
18
22
  - **`docs/cli-architecture.md`**: Updated skills.ts section — enable/disable/create-pack now fully implemented, added runtime flags documentation (v1.5.0).
19
23
  - **`docs/skills-registry-exploration.md`**: Updated implementation status — Phase v0.9 pack lifecycle delivered, enable/disable/create-pack implemented (v1.2.0).
package/README.md CHANGED
@@ -28,7 +28,7 @@ Native integration with the [specialists](https://github.com/Jaggerxtrm/speciali
28
28
 
29
29
  ---
30
30
 
31
- **Version 0.5.30** | [Complete Guide](XTRM-GUIDE.md) | [Changelog](CHANGELOG.md)
31
+ **Version 0.7.1** | [Complete Guide](XTRM-GUIDE.md) | [Changelog](CHANGELOG.md)
32
32
 
33
33
  ---
34
34
 
@@ -43,6 +43,7 @@ Native integration with the [specialists](https://github.com/Jaggerxtrm/speciali
43
43
  | [docs/pi-extensions.md](docs/pi-extensions.md) | Pi extensions — managed sync, authoring, parity notes |
44
44
  | [docs/worktrees.md](docs/worktrees.md) | xt worktrees — `xt claude/pi`, `xt attach`, `xt end`, isolation model |
45
45
  | [docs/mcp-servers.md](docs/mcp-servers.md) | MCP servers — gitnexus, github-grep, deepwiki, official plugins |
46
+ | [docs/bash-tools.md](docs/bash-tools.md) | Bash-native specialist CLIs — ghgrep, ctx7, deepwiki |
46
47
  | [docs/cli-architecture.md](docs/cli-architecture.md) | CLI internals — install flow, diff/sync engine, config merge |
47
48
  | [docs/docs-commands.md](docs/docs-commands.md) | Docs command suite — `show`, `list`, `cross-check`, output modes, drift checks |
48
49
  | [docs/project-skills.md](docs/project-skills.md) | Legacy project-skill migration notes and current asset location |
@@ -62,7 +63,7 @@ xtrm init
62
63
 
63
64
  # Verify
64
65
  claude plugin list
65
- # → xtrm-tools@xtrm-tools Version: 0.5.30 Status: enabled
66
+ # → xtrm-tools@xtrm-tools Version: 0.7.1 Status: enabled
66
67
  ```
67
68
 
68
69
  **One-line run:**
@@ -103,7 +104,7 @@ xt merge
103
104
 
104
105
  ### Skills
105
106
 
106
- Skills are resolved through a three-tier registry in `.xtrm/skills/` (`default` + `optional` + `user`). Optional packs are installed on demand; today’s catalog additions are `research-methods`, `code-quality`, `security-ops`, `data-engineering`, and `architecture-design`.
107
+ Skills are resolved through a three-tier registry in `.xtrm/skills/` (`default` + `optional` + `user`). Optional packs are installed by default during `xt install`; activate any pack with `xt skills enable <pack>`. Current optional pack catalog: `research-methods`, `code-quality`, `security-ops`, `data-engineering`, and `architecture-design`.
107
108
 
108
109
  Skills are organized into two categories: **xtrm workflow** skills built specifically for the xtrm stack, and **general-purpose** expert skills that work in any project.
109
110
 
@@ -123,10 +124,12 @@ These skills implement the xtrm-specific development workflow — session manage
123
124
  | `planning` | Structured issue board from any spec, with phases and deps |
124
125
  | `test-planning` | Test coverage planning alongside implementation work |
125
126
  | `delegating` | Cost-optimized task delegation to background agents |
127
+ | `using-specialists` | Specialist routing and execution workflow (`specialists run/feed/result`) |
126
128
  | `orchestrating-agents` | Multi-model orchestration (Gemini, Qwen handshake) |
127
129
  | `documenting` | SSOT doc maintenance with drift detection |
128
130
  | `sync-docs` | Doc audit and structural sync across a sprint |
129
131
  | `skill-creator` | Create, improve, and evaluate skills |
132
+ | `specialists-creator` | Create and validate `.specialist.yaml` definitions |
130
133
  | `find-skills` | Discover and install skills on demand |
131
134
  | `creating-service-skills` | Generate operational service skill packages |
132
135
  | `scoping-service-skills` | Task intake and service routing |
@@ -152,6 +155,7 @@ Domain expert skills that can be used in any project, independent of the xtrm wo
152
155
  | `gitnexus-debugging` | Trace bugs through call chains |
153
156
  | `gitnexus-refactoring` | Plan safe refactors via dependency mapping |
154
157
  | `obsidian-cli` | Interact with Obsidian vaults via CLI |
158
+ | `deepwiki` | Query repository/library docs via DeepWiki |
155
159
 
156
160
  ---
157
161
 
@@ -225,6 +229,16 @@ Official Claude plugins installed by `xtrm init`: `serena`, `context7`, `github`
225
229
 
226
230
  See [docs/mcp-servers.md](docs/mcp-servers.md) for configuration details.
227
231
 
232
+ ## Specialist Bash Tools
233
+
234
+ | Tool | Purpose | Install source |
235
+ |------|---------|----------------|
236
+ | `ghgrep` | GitHub code search CLI wrapper over `mcp.grep.app` | Ships as `bin` in `xtrm-tools` |
237
+ | `ctx7` | Context7 docs + skills CLI | Installed by machine-bootstrap (`xt install` / `xt init`) |
238
+ | `deepwiki` | Repo documentation Q&A CLI | Installed by machine-bootstrap (`xt install` / `xt init`) |
239
+
240
+ See [docs/bash-tools.md](docs/bash-tools.md) for usage examples and when to use CLIs vs MCP equivalents.
241
+
228
242
  ---
229
243
 
230
244
  ## Issue Tracking (Beads)
@@ -243,6 +257,7 @@ See [XTRM-GUIDE.md](XTRM-GUIDE.md) for the full `bd` command reference.
243
257
 
244
258
  | Version | Date | Highlights |
245
259
  |---------|------|------------|
260
+ | 0.7.1 | 2026-04-02 | Optional packs pre-populated on install; Pi core symlink path fix; new default skills (`deepwiki`, `specialists-creator`, `using-specialists`) |
246
261
  | 0.5.30 | 2026-03-22 | Fix statusline on fresh installs; `xt end --dry-run` |
247
262
  | 0.5.29 | 2026-03-22 | Statusline truecolor gradient; `--no-verify` autocommit; xt-merge skill |
248
263
  | 0.5.24 | 2026-03-21 | Hash-based docs drift detection; CLI docs cleanup |
@@ -43977,6 +43977,10 @@ function resolvePkgRoot() {
43977
43977
  return candidates[0];
43978
43978
  }
43979
43979
  var PI_AGENT_DIR = process.env.PI_AGENT_DIR || import_path3.default.join((0, import_node_os.homedir)(), ".pi", "agent");
43980
+ var PI_MCP_ADAPTER_OVERRIDE_DIR = import_path3.default.join(PI_AGENT_DIR, "extensions", "pi-mcp-adapter");
43981
+ var PI_MCP_ADAPTER_REQUIRED_ENTRY = "commands.js";
43982
+ var PROJECT_EXTENSIONS_ENTRY = "../.xtrm/extensions";
43983
+ var PROJECT_SKILLS_ENTRY = "../.xtrm/skills/active/pi";
43980
43984
  var MANAGED_EXTENSIONS = [
43981
43985
  { id: "core", displayName: "@xtrm/pi-core", isLibrary: true, required: true },
43982
43986
  { id: "auto-session-name", displayName: "auto-session-name", required: false },
@@ -44136,20 +44140,150 @@ function renderPiRuntimePlan(plan) {
44136
44140
  console.log(kleur_default.yellow(" \u26A0 Missing required items.\n"));
44137
44141
  }
44138
44142
  }
44143
+ function mergePiSyncResults(base, incoming) {
44144
+ return {
44145
+ extensionsAdded: [...base.extensionsAdded, ...incoming.extensionsAdded],
44146
+ extensionsUpdated: [...base.extensionsUpdated, ...incoming.extensionsUpdated],
44147
+ extensionsRemoved: [...base.extensionsRemoved, ...incoming.extensionsRemoved],
44148
+ packagesInstalled: [...base.packagesInstalled, ...incoming.packagesInstalled],
44149
+ failed: [...base.failed, ...incoming.failed]
44150
+ };
44151
+ }
44139
44152
  async function ensureCorePackageSymlink(coreSrcDir, projectRoot, dryRun, log) {
44140
- if (!await import_fs_extra7.default.pathExists(coreSrcDir)) return;
44141
- const nodeModulesDir = import_path3.default.join(projectRoot, ".pi", "node_modules", "@xtrm");
44153
+ if (!await import_fs_extra7.default.pathExists(coreSrcDir)) return "missing-source";
44154
+ const extensionsDir = import_path3.default.join(projectRoot, ".xtrm", "extensions");
44155
+ const nodeModulesDir = import_path3.default.join(extensionsDir, "node_modules", "@xtrm");
44142
44156
  const symlinkPath = import_path3.default.join(nodeModulesDir, "pi-core");
44157
+ const expectedTarget = import_path3.default.resolve(coreSrcDir);
44143
44158
  const existing = await import_fs_extra7.default.lstat(symlinkPath).catch(() => null);
44144
- if (existing) return;
44159
+ if (existing) {
44160
+ if (existing.isSymbolicLink()) {
44161
+ const currentLinkTarget = await import_fs_extra7.default.readlink(symlinkPath);
44162
+ const resolvedTarget = import_path3.default.resolve(import_path3.default.dirname(symlinkPath), currentLinkTarget);
44163
+ if (resolvedTarget === expectedTarget) {
44164
+ return "ok";
44165
+ }
44166
+ }
44167
+ if (dryRun) {
44168
+ log?.(kleur_default.dim("[DRY RUN] would repair @xtrm/pi-core symlink target"));
44169
+ return "would-repair";
44170
+ }
44171
+ await import_fs_extra7.default.remove(symlinkPath);
44172
+ await import_fs_extra7.default.ensureDir(nodeModulesDir);
44173
+ const relTarget2 = import_path3.default.relative(nodeModulesDir, coreSrcDir);
44174
+ await import_fs_extra7.default.symlink(relTarget2, symlinkPath);
44175
+ log?.(kleur_default.dim("Repaired @xtrm/pi-core symlink \u2192 .xtrm/extensions/node_modules/@xtrm/pi-core"));
44176
+ return "repaired";
44177
+ }
44145
44178
  if (dryRun) {
44146
- log?.(kleur_default.dim(`[DRY RUN] would create @xtrm/pi-core symlink`));
44147
- return;
44179
+ log?.(kleur_default.dim("[DRY RUN] would create @xtrm/pi-core symlink"));
44180
+ return "would-create";
44148
44181
  }
44149
44182
  await import_fs_extra7.default.ensureDir(nodeModulesDir);
44150
44183
  const relTarget = import_path3.default.relative(nodeModulesDir, coreSrcDir);
44151
44184
  await import_fs_extra7.default.symlink(relTarget, symlinkPath);
44152
- log?.(kleur_default.dim(`Created @xtrm/pi-core symlink for module resolution`));
44185
+ log?.(kleur_default.dim("Created @xtrm/pi-core symlink \u2192 .xtrm/extensions/node_modules/@xtrm/pi-core"));
44186
+ return "created";
44187
+ }
44188
+ async function remediateStalePiMcpAdapterOverride(dryRun, log) {
44189
+ const stat = await import_fs_extra7.default.lstat(PI_MCP_ADAPTER_OVERRIDE_DIR).catch(() => null);
44190
+ if (!stat) {
44191
+ return {
44192
+ path: PI_MCP_ADAPTER_OVERRIDE_DIR,
44193
+ found: false,
44194
+ stale: false,
44195
+ remediated: false
44196
+ };
44197
+ }
44198
+ if (stat.isSymbolicLink()) {
44199
+ return {
44200
+ path: PI_MCP_ADAPTER_OVERRIDE_DIR,
44201
+ found: true,
44202
+ stale: false,
44203
+ remediated: false
44204
+ };
44205
+ }
44206
+ const hasRequiredEntry = await import_fs_extra7.default.pathExists(import_path3.default.join(PI_MCP_ADAPTER_OVERRIDE_DIR, PI_MCP_ADAPTER_REQUIRED_ENTRY));
44207
+ if (stat.isDirectory() && hasRequiredEntry) {
44208
+ return {
44209
+ path: PI_MCP_ADAPTER_OVERRIDE_DIR,
44210
+ found: true,
44211
+ stale: false,
44212
+ remediated: false
44213
+ };
44214
+ }
44215
+ const reason = stat.isDirectory() ? `missing ${PI_MCP_ADAPTER_REQUIRED_ENTRY}` : "not a directory/symlink";
44216
+ if (dryRun) {
44217
+ log?.(kleur_default.dim(`[DRY RUN] would remove stale pi-mcp-adapter override (${reason})`));
44218
+ return {
44219
+ path: PI_MCP_ADAPTER_OVERRIDE_DIR,
44220
+ found: true,
44221
+ stale: true,
44222
+ remediated: false,
44223
+ reason
44224
+ };
44225
+ }
44226
+ await import_fs_extra7.default.remove(PI_MCP_ADAPTER_OVERRIDE_DIR);
44227
+ log?.(kleur_default.dim(`Removed stale pi-mcp-adapter override (${reason})`));
44228
+ return {
44229
+ path: PI_MCP_ADAPTER_OVERRIDE_DIR,
44230
+ found: true,
44231
+ stale: true,
44232
+ remediated: true,
44233
+ reason
44234
+ };
44235
+ }
44236
+ async function runPiLaunchPreflight(projectRoot, dryRun, log) {
44237
+ const staleOverride = await remediateStalePiMcpAdapterOverride(dryRun, log);
44238
+ const coreSymlinkStatus = await ensureCorePackageSymlink(
44239
+ import_path3.default.join(projectRoot, ".xtrm", "extensions", "core"),
44240
+ projectRoot,
44241
+ dryRun,
44242
+ log
44243
+ );
44244
+ return {
44245
+ coreSymlinkStatus,
44246
+ staleOverride
44247
+ };
44248
+ }
44249
+ function isXtrmExtensionsSetting(entry) {
44250
+ const normalizedEntry = entry.replaceAll("\\", "/").replace(/\/$/, "");
44251
+ return normalizedEntry === PROJECT_EXTENSIONS_ENTRY || normalizedEntry === ".xtrm/extensions";
44252
+ }
44253
+ async function cleanupLegacyProjectExtensionCopies(projectRoot, dryRun, log) {
44254
+ const piSettingsPath = import_path3.default.join(projectRoot, ".pi", "settings.json");
44255
+ let existingSettings = {};
44256
+ try {
44257
+ existingSettings = await import_fs_extra7.default.readJson(piSettingsPath);
44258
+ } catch {
44259
+ return { removed: [], failed: [] };
44260
+ }
44261
+ const pointsToXtrmExtensions = (existingSettings.extensions ?? []).some(isXtrmExtensionsSetting);
44262
+ if (!pointsToXtrmExtensions) return { removed: [], failed: [] };
44263
+ const legacyExtensionsDir = import_path3.default.join(projectRoot, ".pi", "extensions");
44264
+ if (!await import_fs_extra7.default.pathExists(legacyExtensionsDir)) return { removed: [], failed: [] };
44265
+ const removed = [];
44266
+ const failed = [];
44267
+ for (const ext of MANAGED_EXTENSIONS) {
44268
+ const legacyExtPath = import_path3.default.join(legacyExtensionsDir, ext.id);
44269
+ const legacyStat = await import_fs_extra7.default.lstat(legacyExtPath).catch(() => null);
44270
+ if (!legacyStat || legacyStat.isSymbolicLink() || !legacyStat.isDirectory()) {
44271
+ continue;
44272
+ }
44273
+ if (dryRun) {
44274
+ log?.(kleur_default.dim(`[DRY RUN] - .pi/extensions/${ext.id} (legacy copy)`));
44275
+ continue;
44276
+ }
44277
+ try {
44278
+ await import_fs_extra7.default.remove(legacyExtPath);
44279
+ removed.push(ext.id);
44280
+ log?.(kleur_default.dim(`Removed legacy .pi/extensions/${ext.id}`));
44281
+ } catch (err) {
44282
+ failed.push(ext.id);
44283
+ log?.(kleur_default.red(`\u2717 Failed to remove legacy .pi/extensions/${ext.id}: ${err}`));
44284
+ }
44285
+ }
44286
+ return { removed, failed };
44153
44287
  }
44154
44288
  async function updatePiSettings(projectRoot, dryRun, log) {
44155
44289
  const piSettingsPath = import_path3.default.join(projectRoot, ".pi", "settings.json");
@@ -44162,16 +44296,14 @@ async function updatePiSettings(projectRoot, dryRun, log) {
44162
44296
  existingSettings = await import_fs_extra7.default.readJson(piSettingsPath);
44163
44297
  } catch {
44164
44298
  }
44165
- const extensionsEntry = "../.xtrm/extensions";
44166
- const skillsEntry = "../.xtrm/skills/active/pi";
44167
44299
  const existingPackages = (existingSettings.packages ?? []).filter(
44168
44300
  (p) => !p.startsWith("./extensions/")
44169
44301
  );
44170
44302
  await import_fs_extra7.default.ensureDir(import_path3.default.join(projectRoot, ".pi"));
44171
44303
  await import_fs_extra7.default.writeJson(piSettingsPath, {
44172
44304
  ...existingSettings,
44173
- extensions: [extensionsEntry],
44174
- skills: [skillsEntry],
44305
+ extensions: [PROJECT_EXTENSIONS_ENTRY],
44306
+ skills: [PROJECT_SKILLS_ENTRY],
44175
44307
  packages: existingPackages
44176
44308
  }, { spaces: 2 });
44177
44309
  log?.(kleur_default.dim(`Updated .pi/settings.json \u2192 .xtrm/extensions + .xtrm/skills/active/pi`));
@@ -44272,20 +44404,26 @@ async function runPiRuntimeSync(opts = {}) {
44272
44404
  packagesInstalled: [],
44273
44405
  failed: []
44274
44406
  };
44407
+ const result = { ...emptyResult };
44275
44408
  if (!await import_fs_extra7.default.pathExists(sourceDir)) {
44276
44409
  console.log(kleur_default.dim("\n Managed extensions: skipped (not bundled in npm package)\n"));
44277
- return emptyResult;
44410
+ return result;
44411
+ }
44412
+ const preflight = await runPiLaunchPreflight(resolvedProjectRoot, dryRun, log);
44413
+ if (preflight.staleOverride.remediated) {
44414
+ result.extensionsRemoved.push("pi-mcp-adapter");
44278
44415
  }
44279
44416
  if (isGlobal) {
44280
44417
  const targetDir = import_path3.default.join(PI_AGENT_DIR, "extensions");
44281
44418
  const plan = await inventoryPiRuntime(sourceDir, targetDir);
44282
44419
  renderPiRuntimePlan(plan);
44283
- if (plan.allPresent) return emptyResult;
44284
- return await executePiSync(plan, sourceDir, targetDir, {
44420
+ if (plan.allPresent) return result;
44421
+ const synced = await executePiSync(plan, sourceDir, targetDir, {
44285
44422
  dryRun,
44286
44423
  isGlobal: true,
44287
44424
  removeOrphaned: true
44288
44425
  });
44426
+ return mergePiSyncResults(result, synced);
44289
44427
  }
44290
44428
  const installedPkgIds = getInstalledPiPackages();
44291
44429
  const packageStatuses = [];
@@ -44306,7 +44444,9 @@ async function runPiRuntimeSync(opts = {}) {
44306
44444
  console.log(kleur_default.yellow(` Missing: ${names}`));
44307
44445
  }
44308
44446
  console.log(kleur_default.dim(" " + "-".repeat(50)));
44309
- const result = { ...emptyResult };
44447
+ const legacyCleanup = await cleanupLegacyProjectExtensionCopies(resolvedProjectRoot, dryRun, log);
44448
+ result.extensionsRemoved.push(...legacyCleanup.removed);
44449
+ result.failed.push(...legacyCleanup.failed);
44310
44450
  for (const status of missingPackages) {
44311
44451
  const { pkg } = status;
44312
44452
  if (dryRun) {
@@ -44339,7 +44479,6 @@ async function runPiRuntimeSync(opts = {}) {
44339
44479
  }
44340
44480
  }
44341
44481
  await updatePiSettings(resolvedProjectRoot, dryRun, log);
44342
- await ensureCorePackageSymlink(import_path3.default.join(sourceDir, "core"), resolvedProjectRoot, dryRun, log);
44343
44482
  const requiredFailed = missingPackages.filter(
44344
44483
  (s) => s.pkg.required && result.failed.includes(s.pkg.id)
44345
44484
  );
@@ -44541,12 +44680,11 @@ async function launchWorktreeSession(opts) {
44541
44680
  } catch {
44542
44681
  }
44543
44682
  }
44544
- const worktreeExtensionsDir = import_node_path5.default.join(worktreePiDir, "extensions");
44545
44683
  try {
44546
- await ensureCorePackageSymlink(worktreeExtensionsDir, worktreePath, false);
44684
+ await runPiLaunchPreflight(worktreePath, false);
44547
44685
  } catch (error48) {
44548
44686
  const message = error48 instanceof Error ? error48.message : String(error48);
44549
- console.log(kleur_default.dim(` warning: could not ensure @xtrm/pi-core symlink (${message})`));
44687
+ console.log(kleur_default.dim(` warning: pi launch preflight failed (${message})`));
44550
44688
  }
44551
44689
  }
44552
44690
  if (runtime === "claude") {
@@ -44718,6 +44856,17 @@ var MANAGED_DEPS = [
44718
44856
  install: {
44719
44857
  default: [{ cmd: "npm", args: ["install", "-g", "@seflless/deepwiki"] }]
44720
44858
  }
44859
+ },
44860
+ {
44861
+ id: "ctx7",
44862
+ cli: "ctx7",
44863
+ versionFlag: "--version",
44864
+ displayName: "ctx7",
44865
+ description: "Context7 CLI \u2014 library docs lookup for specialists",
44866
+ required: false,
44867
+ install: {
44868
+ default: [{ cmd: "npm", args: ["install", "-g", "ctx7"] }]
44869
+ }
44721
44870
  }
44722
44871
  ];
44723
44872
  function checkDep(dep) {
@@ -45424,6 +45573,33 @@ function createPiCommand() {
45424
45573
  const bundleRoot = await findRepoRoot();
45425
45574
  const sourceDir = import_path7.default.join(bundleRoot, ".xtrm", "extensions");
45426
45575
  const globalTargetDir = import_path7.default.join(PI_AGENT_DIR4, "extensions");
45576
+ try {
45577
+ const staleOverride = await remediateStalePiMcpAdapterOverride(false);
45578
+ if (staleOverride.stale && staleOverride.remediated) {
45579
+ console.log(t.success(" \u2713 removed stale ~/.pi/agent/extensions/pi-mcp-adapter override"));
45580
+ } else if (staleOverride.stale) {
45581
+ console.log(kleur_default.yellow(" \u26A0 stale ~/.pi/agent/extensions/pi-mcp-adapter override detected"));
45582
+ allOk = false;
45583
+ } else {
45584
+ console.log(t.success(" \u2713 pi-mcp-adapter override check passed"));
45585
+ }
45586
+ } catch (error48) {
45587
+ console.log(kleur_default.yellow(` \u26A0 failed to remediate pi-mcp-adapter override: ${error48}`));
45588
+ allOk = false;
45589
+ }
45590
+ try {
45591
+ const coreStatus = await ensureCorePackageSymlink(import_path7.default.join(sourceDir, "core"), projectRoot, false);
45592
+ if (coreStatus === "repaired" || coreStatus === "created") {
45593
+ console.log(t.success(" \u2713 repaired .xtrm/extensions/node_modules/@xtrm/pi-core symlink"));
45594
+ } else if (coreStatus === "ok") {
45595
+ console.log(t.success(" \u2713 @xtrm/pi-core symlink is healthy"));
45596
+ } else if (coreStatus === "missing-source") {
45597
+ console.log(kleur_default.dim(" \u25CB @xtrm/pi-core source not bundled in this install"));
45598
+ }
45599
+ } catch (error48) {
45600
+ console.log(kleur_default.yellow(` \u26A0 failed to ensure @xtrm/pi-core symlink: ${error48}`));
45601
+ allOk = false;
45602
+ }
45427
45603
  if (!await import_fs_extra11.default.pathExists(sourceDir)) {
45428
45604
  console.log(kleur_default.dim(" \u25CB managed extensions not bundled in this install"));
45429
45605
  } else {
@@ -50500,6 +50676,14 @@ function createAttachCommand() {
50500
50676
  console.log(kleur_default.dim(` runtime: ${runtime} (resuming session)`));
50501
50677
  console.log(kleur_default.dim(` path: ${target.path}
50502
50678
  `));
50679
+ if (runtime === "pi") {
50680
+ try {
50681
+ await runPiLaunchPreflight(target.path, false);
50682
+ } catch (error48) {
50683
+ const message = error48 instanceof Error ? error48.message : String(error48);
50684
+ console.log(kleur_default.dim(` warning: pi launch preflight failed (${message})`));
50685
+ }
50686
+ }
50503
50687
  const result = (0, import_node_child_process8.spawnSync)(runtime, resumeArgs, {
50504
50688
  cwd: target.path,
50505
50689
  stdio: "inherit"
@@ -52462,6 +52646,7 @@ var ART = [
52462
52646
  " \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
52463
52647
  ];
52464
52648
  var ART_WIDTH = 84;
52649
+ var TAGLINE = "agent infrastructure layer \u2014 runtimes, skills,\n hooks, extensions, packages";
52465
52650
  function isTTY2() {
52466
52651
  return Boolean(process.stdout.isTTY);
52467
52652
  }
@@ -52508,12 +52693,14 @@ async function typewriterTagline(text) {
52508
52693
  const CHAR_DELAY = 42;
52509
52694
  const prefix = ` \x1B[2m\u2014\x1B[0m \x1B[1m\x1B[37m`;
52510
52695
  const suffix = `\x1B[0m \x1B[2m\u2014\x1B[0m`;
52511
- process.stdout.write(prefix);
52512
- for (const ch of text) {
52513
- process.stdout.write(ch);
52514
- await delay(CHAR_DELAY);
52696
+ for (const line of text.split("\n")) {
52697
+ process.stdout.write(prefix);
52698
+ for (const ch of line) {
52699
+ process.stdout.write(ch);
52700
+ await delay(CHAR_DELAY);
52701
+ }
52702
+ process.stdout.write(suffix + "\n");
52515
52703
  }
52516
- process.stdout.write(suffix + "\n");
52517
52704
  }
52518
52705
  var HUE_START = 170;
52519
52706
  var HUE_END = 230;
@@ -52547,7 +52734,7 @@ async function renderTier0(version3) {
52547
52734
  }
52548
52735
  process.stdout.write(rule + "\n");
52549
52736
  process.stdout.write(" \x1B[2mv" + version3 + "\x1B[0m\n");
52550
- await typewriterTagline("Sync agent tools across AI environments");
52737
+ await typewriterTagline(TAGLINE);
52551
52738
  }
52552
52739
  function renderTier1(version3) {
52553
52740
  console.log("");
@@ -52557,7 +52744,7 @@ function renderTier1(version3) {
52557
52744
  console.log(kleur_default.dim(" " + "\u2500".repeat(ART_WIDTH - 1)));
52558
52745
  console.log(kleur_default.dim(" v" + version3));
52559
52746
  console.log(
52560
- " " + kleur_default.dim("\u2014") + " " + kleur_default.bold().white("Sync agent tools across AI environments") + " " + kleur_default.dim("\u2014")
52747
+ " " + kleur_default.dim("\u2014") + " " + kleur_default.bold().white(TAGLINE) + " " + kleur_default.dim("\u2014")
52561
52748
  );
52562
52749
  console.log("");
52563
52750
  }
@@ -52566,19 +52753,19 @@ function renderTier2(version3) {
52566
52753
  console.log(
52567
52754
  kleur_default.cyan(" \u25C8 ") + kleur_default.bold().white("xtrm-tools") + kleur_default.dim(" v" + version3)
52568
52755
  );
52569
- console.log(kleur_default.dim(" Sync agent tools across AI environments"));
52756
+ console.log(kleur_default.dim(` ${TAGLINE}`));
52570
52757
  console.log("");
52571
52758
  }
52572
52759
  function renderTier3(version3) {
52573
52760
  console.log("");
52574
52761
  console.log(kleur_default.bold(" xtrm-tools") + kleur_default.dim(" v" + version3));
52575
- console.log(kleur_default.dim(" Sync agent tools across AI environments"));
52762
+ console.log(kleur_default.dim(` ${TAGLINE}`));
52576
52763
  console.log("");
52577
52764
  }
52578
52765
  function renderTier4(version3) {
52579
52766
  console.log("");
52580
52767
  console.log("xtrm-tools v" + version3);
52581
- console.log("Sync agent tools across AI environments");
52768
+ console.log(TAGLINE);
52582
52769
  console.log("");
52583
52770
  }
52584
52771
  async function printBanner(version3) {
@@ -52609,7 +52796,7 @@ try {
52609
52796
  } catch {
52610
52797
  }
52611
52798
  var program2 = new Command();
52612
- program2.name("xtrm").description("Dual-runtime workflow system for Claude Code and Pi agents").version(version2);
52799
+ program2.name("xtrm").description("Agent infrastructure layer for runtimes, skills, hooks, extensions, and packages").version(version2);
52613
52800
  program2.exitOverride((err) => {
52614
52801
  if (err.code === "commander.unknownCommand") {
52615
52802
  console.error(kleur_default.red(`