xtrm-tools 2.1.26 → 2.1.29

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/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtrm-cli",
3
- "version": "2.1.26",
3
+ "version": "2.1.29",
4
4
  "description": "Claude Code tools installer (skills, hooks, MCP servers)",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
package/config/hooks.json CHANGED
@@ -36,6 +36,11 @@
36
36
  }
37
37
  ],
38
38
  "PostToolUse": [
39
+ {
40
+ "matcher": "Bash",
41
+ "script": "beads-claim-sync.mjs",
42
+ "timeout": 5000
43
+ },
39
44
  {
40
45
  "matcher": "Bash",
41
46
  "script": "main-guard-post-push.mjs",
@@ -0,0 +1,30 @@
1
+ # XTRM Agent Workflow (Short)
2
+
3
+ This file is an **agent operating manual** (not a project overview).
4
+
5
+ 1. **Start with scope**
6
+ - Clarify task intent if ambiguous.
7
+ - Prefer semantic discovery (Serena + GitNexus) over broad grep-first exploration.
8
+
9
+ 2. **Track work in `bd`**
10
+ - Use `bd ready --json` / `bd update <id> --claim --json` before edits.
11
+ - Create discovered follow-ups with `--deps discovered-from:<id>`.
12
+
13
+ 3. **Branch per issue (strict)**
14
+ - Create a **new branch for each issue** from latest `main`.
15
+ - Do **not** continue new work on a previously used branch.
16
+ - Branch format: `feature/<issue-id>-<short-description>` (or `fix/...`, `chore/...`).
17
+
18
+ 4. **Edit safely**
19
+ - Use Serena symbol tools for code changes when possible.
20
+ - Run GitNexus impact checks before symbol changes and detect-changes before commit.
21
+
22
+ 5. **PR merge + return to main**
23
+ - Always merge via PR (squash merge preferred).
24
+ - After merge: switch to `main` and sync (`git reset --hard origin/main`).
25
+ - Delete merged branch locally and remotely (`git branch -d <branch>` and `git push origin --delete <branch>`).
26
+
27
+ 6. **Before finishing**
28
+ - Run relevant tests/linters.
29
+ - Close/update bead state.
30
+ - Ensure changes are committed and pushed.
@@ -0,0 +1,30 @@
1
+ # XTRM Agent Workflow (Short)
2
+
3
+ This file is an **agent operating manual** (not a project overview).
4
+
5
+ 1. **Start with scope**
6
+ - Clarify task intent if ambiguous.
7
+ - Prefer semantic discovery (Serena + GitNexus) over broad grep-first exploration.
8
+
9
+ 2. **Track work in `bd`**
10
+ - Use `bd ready --json` / `bd update <id> --claim --json` before edits.
11
+ - Create discovered follow-ups with `--deps discovered-from:<id>`.
12
+
13
+ 3. **Branch per issue (strict)**
14
+ - Create a **new branch for each issue** from latest `main`.
15
+ - Do **not** continue new work on a previously used branch.
16
+ - Branch format: `feature/<issue-id>-<short-description>` (or `fix/...`, `chore/...`).
17
+
18
+ 4. **Edit safely**
19
+ - Use Serena symbol tools for code changes when possible.
20
+ - Run GitNexus impact checks before symbol changes and detect-changes before commit.
21
+
22
+ 5. **PR merge + return to main**
23
+ - Always merge via PR (squash merge preferred).
24
+ - After merge: switch to `main` and sync (`git reset --hard origin/main`).
25
+ - Delete merged branch locally and remotely (`git branch -d <branch>` and `git push origin --delete <branch>`).
26
+
27
+ 6. **Before finishing**
28
+ - Run relevant tests/linters.
29
+ - Close/update bead state.
30
+ - Ensure changes are committed and pushed.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * XTRM Custom Footer Extension
3
3
  *
4
- * Displays: XTRM brand, Turn count, Model, Context%, CWD, Git branch
4
+ * Displays: XTRM brand, Model, Context%, CWD, Git branch, Beads chip
5
5
  */
6
6
 
7
7
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
@@ -12,9 +12,6 @@ import * as fs from "node:fs";
12
12
  import { SubprocessRunner } from "./core/lib";
13
13
 
14
14
  export default function (pi: ExtensionAPI) {
15
- // Pin session to PID — stable for the life of the Pi process, matches beads.ts
16
- const SESSION_KEY = process.pid.toString();
17
-
18
15
  interface BeadState {
19
16
  claimId: string | null;
20
17
  shortId: string | null;
@@ -31,11 +28,12 @@ export default function (pi: ExtensionAPI) {
31
28
  };
32
29
  const STATUS_BG: Record<string, string> = {
33
30
  open: "\x1b[48;5;238m",
34
- in_progress: "\x1b[48;5;28m",
31
+ in_progress: "\x1b[48;5;39m",
35
32
  blocked: "\x1b[48;5;88m",
36
33
  };
37
34
 
38
35
  let capturedCtx: any = null;
36
+ let sessionId: string = "";
39
37
  let beadState: BeadState = { claimId: null, shortId: null, status: null, openCount: 0, lastFetch: 0 };
40
38
  let refreshing = false;
41
39
  let requestRender: (() => void) | null = null;
@@ -49,19 +47,20 @@ export default function (pi: ExtensionAPI) {
49
47
  if (refreshing || Date.now() - beadState.lastFetch < CACHE_TTL) return;
50
48
  const cwd = getCwd();
51
49
  if (!isBeadsProject(cwd)) return;
50
+ if (!sessionId) return;
52
51
  refreshing = true;
53
52
  try {
54
- const claimResult = await SubprocessRunner.run("bd", ["kv", "get", `claimed:${SESSION_KEY}`], { cwd });
53
+ const claimResult = await SubprocessRunner.run("bd", ["kv", "get", `claimed:${sessionId}`], { cwd });
55
54
  const claimId = claimResult.code === 0 ? claimResult.stdout.trim() || null : null;
56
55
 
57
56
  let status: string | null = null;
58
57
  if (claimId) {
59
58
  const showResult = await SubprocessRunner.run("bd", ["show", claimId, "--json"], { cwd });
60
59
  if (showResult.code === 0) {
61
- try { status = JSON.parse(showResult.stdout).status ?? null; } catch {}
60
+ try { status = JSON.parse(showResult.stdout)[0]?.status ?? null; } catch {}
62
61
  }
63
62
  if (status === "closed") {
64
- await SubprocessRunner.run("bd", ["kv", "clear", `claimed:${SESSION_KEY}`], { cwd });
63
+ await SubprocessRunner.run("bd", ["kv", "clear", `claimed:${sessionId}`], { cwd });
65
64
  beadState = { claimId: null, shortId: null, status: null, openCount: beadState.openCount, lastFetch: Date.now() };
66
65
  requestRender?.();
67
66
  return;
@@ -96,6 +95,8 @@ export default function (pi: ExtensionAPI) {
96
95
 
97
96
  pi.on("session_start", async (_event, ctx) => {
98
97
  capturedCtx = ctx;
98
+ // Get session ID from sessionManager (UUID, consistent with hooks)
99
+ sessionId = ctx.sessionManager?.getSessionId?.() ?? process.pid.toString();
99
100
 
100
101
  ctx.ui.setFooter((tui, theme, footerData) => {
101
102
  requestRender = () => tui.requestRender();
@@ -122,15 +123,16 @@ export default function (pi: ExtensionAPI) {
122
123
  const branchStr = branch ? theme.fg("accent", `⎇ ${branch}`) : "";
123
124
 
124
125
  const modelId = ctx.model?.id || "no-model";
125
- const modelStr = theme.fg("accent", modelId);
126
+ const modelChip = `\x1b[48;5;238m\x1b[38;5;15m ${modelId} \x1b[0m`;
126
127
 
127
128
  const sep = theme.fg("dim", " | ");
128
129
 
129
- const leftParts = [brand, modelStr, usageStr, cwdStr];
130
- if (branchStr) leftParts.push(branchStr);
131
-
130
+ const brandModel = `${brand} ${modelChip}`;
131
+ const leftParts = [brandModel, usageStr, cwdStr];
132
+
132
133
  const beadChip = buildBeadChip();
133
- if (beadChip) leftParts.push(beadChip);
134
+ const branchWithChip = branchStr ? `${branchStr} ${beadChip}`.trim() : beadChip;
135
+ if (branchWithChip) leftParts.push(branchWithChip);
134
136
 
135
137
  const left = leftParts.join(sep);
136
138
  return [truncateToWidth(left, width)];
@@ -139,7 +141,7 @@ export default function (pi: ExtensionAPI) {
139
141
  });
140
142
  });
141
143
 
142
- // Bust the bead cache immediately after any bd write so the chip reflects the new state
144
+ // Bust the bead cache immediately after any bd write
143
145
  pi.on("tool_result", async (event: any) => {
144
146
  const cmd = event?.input?.command;
145
147
  if (cmd && /\bbd\s+(close|update|create|claim)\b/.test(cmd)) {
@@ -0,0 +1,6 @@
1
+ {
2
+ "worktree": {
3
+ "parentDir": "../{{project}}.worktrees",
4
+ "onCreate": "npm install 2>/dev/null || true"
5
+ }
6
+ }
@@ -7,7 +7,8 @@
7
7
  "packages": [
8
8
  "npm:@aliou/pi-guardrails",
9
9
  "npm:pi-gitnexus",
10
- "npm:pi-serena-tools"
10
+ "npm:pi-serena-tools",
11
+ "npm:@zenobius/pi-worktrees"
11
12
  ],
12
13
  "steeringMode": "all",
13
14
  "followUpMode": "all",
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ // beads-claim-sync — PostToolUse hook
3
+ // Auto-sets bd kv claim when bd update --claim is detected.
4
+ // Uses session_id from hook input (UUID, matches Pi's sessionManager.getSessionId())
5
+
6
+ import { spawnSync } from 'node:child_process';
7
+ import { readFileSync, existsSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+
10
+ function readInput() {
11
+ try {
12
+ return JSON.parse(readFileSync(0, 'utf-8'));
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+
18
+ function isBeadsProject(cwd) {
19
+ return existsSync(join(cwd, '.beads'));
20
+ }
21
+
22
+ function main() {
23
+ const input = readInput();
24
+ if (!input || input.hook_event_name !== 'PostToolUse') process.exit(0);
25
+ if (input.tool_name !== 'Bash') process.exit(0);
26
+
27
+ const cwd = input.cwd || process.cwd();
28
+ if (!isBeadsProject(cwd)) process.exit(0);
29
+
30
+ const command = input.tool_input?.command || '';
31
+ if (!/\bbd\s+update\b/.test(command) || !/--claim\b/.test(command)) {
32
+ process.exit(0);
33
+ }
34
+
35
+ // Extract issue ID from command
36
+ const match = command.match(/\bbd\s+update\s+(\S+)/);
37
+ if (!match) process.exit(0);
38
+
39
+ const issueId = match[1];
40
+ // Use session_id from hook input (UUID from Pi/Claude Code)
41
+ const sessionId = input.session_id;
42
+
43
+ if (!sessionId) {
44
+ process.stderr.write('Beads claim sync: no session_id in hook input\n');
45
+ process.exit(0);
46
+ }
47
+
48
+ try {
49
+ spawnSync('bd', ['kv', 'set', `claimed:${sessionId}`, issueId], {
50
+ cwd,
51
+ stdio: ['pipe', 'pipe', 'pipe'],
52
+ timeout: 5000,
53
+ });
54
+ process.stdout.write(JSON.stringify({
55
+ additionalContext: `\n✅ **Beads**: Session \`${sessionId}\` claimed issue \`${issueId}\`.`,
56
+ }));
57
+ process.stdout.write('\n');
58
+ } catch (err) {
59
+ process.stderr.write(`Beads claim sync warning: ${err.message}\n`);
60
+ }
61
+
62
+ process.exit(0);
63
+ }
64
+
65
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtrm-tools",
3
- "version": "2.1.26",
3
+ "version": "2.1.29",
4
4
  "description": "Claude Code tools installer (skills, hooks, MCP servers)",
5
5
  "license": "MIT",
6
6
  "type": "module",