@creativeintelligence/abbie 0.1.6 → 0.1.7

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 (141) hide show
  1. package/bin/dev.js +1 -49
  2. package/bin/run.js +42 -49
  3. package/dist/cli/commands/project/add.d.ts +0 -1
  4. package/dist/cli/commands/project/add.js +16 -52
  5. package/dist/cli/commands/project/list.js +13 -93
  6. package/dist/cli/commands/project/remove.d.ts +0 -2
  7. package/dist/cli/commands/project/remove.js +11 -28
  8. package/dist/cli/commands/session/list.js +3 -12
  9. package/dist/cli/commands/session/mark-done.js +1 -7
  10. package/dist/cli/commands/session/start.d.ts +0 -1
  11. package/dist/cli/commands/session/start.js +5 -7
  12. package/dist/lib/active-sessions.d.ts +0 -12
  13. package/dist/lib/active-sessions.js +6 -175
  14. package/dist/lib/project-path.d.ts +6 -0
  15. package/dist/lib/project-path.js +21 -0
  16. package/dist/lib.d.ts +1 -2
  17. package/dist/lib.js +2 -4
  18. package/oclif.manifest.json +2569 -6368
  19. package/package.json +1 -1
  20. package/dist/cli/commands/backlog/add.d.ts +0 -22
  21. package/dist/cli/commands/backlog/add.js +0 -65
  22. package/dist/cli/commands/backlog/claim.d.ts +0 -19
  23. package/dist/cli/commands/backlog/claim.js +0 -45
  24. package/dist/cli/commands/backlog/complete.d.ts +0 -18
  25. package/dist/cli/commands/backlog/complete.js +0 -42
  26. package/dist/cli/commands/backlog/list.d.ts +0 -20
  27. package/dist/cli/commands/backlog/list.js +0 -91
  28. package/dist/cli/commands/backlog/pick.d.ts +0 -18
  29. package/dist/cli/commands/backlog/pick.js +0 -42
  30. package/dist/cli/commands/backlog/sync.d.ts +0 -24
  31. package/dist/cli/commands/backlog/sync.js +0 -109
  32. package/dist/cli/commands/daemon.d.ts +0 -56
  33. package/dist/cli/commands/daemon.js +0 -1465
  34. package/dist/cli/commands/docs/lint.d.ts +0 -18
  35. package/dist/cli/commands/docs/lint.js +0 -82
  36. package/dist/cli/commands/docs/sync.d.ts +0 -19
  37. package/dist/cli/commands/docs/sync.js +0 -76
  38. package/dist/cli/commands/gc.d.ts +0 -29
  39. package/dist/cli/commands/gc.js +0 -211
  40. package/dist/cli/commands/index.d.ts +0 -36
  41. package/dist/cli/commands/index.js +0 -228
  42. package/dist/cli/commands/panes/broker.d.ts +0 -17
  43. package/dist/cli/commands/panes/broker.js +0 -57
  44. package/dist/cli/commands/panes/pipe-sink.d.ts +0 -17
  45. package/dist/cli/commands/panes/pipe-sink.js +0 -90
  46. package/dist/cli/commands/panes/snapshot.d.ts +0 -20
  47. package/dist/cli/commands/panes/snapshot.js +0 -125
  48. package/dist/cli/commands/preview/init.d.ts +0 -25
  49. package/dist/cli/commands/preview/init.js +0 -159
  50. package/dist/cli/commands/preview/sync.d.ts +0 -23
  51. package/dist/cli/commands/preview/sync.js +0 -144
  52. package/dist/cli/commands/preview/watch.d.ts +0 -24
  53. package/dist/cli/commands/preview/watch.js +0 -153
  54. package/dist/cli/commands/resource/acquire.d.ts +0 -21
  55. package/dist/cli/commands/resource/acquire.js +0 -90
  56. package/dist/cli/commands/resource/list.d.ts +0 -15
  57. package/dist/cli/commands/resource/list.js +0 -61
  58. package/dist/cli/commands/resource/release.d.ts +0 -18
  59. package/dist/cli/commands/resource/release.js +0 -50
  60. package/dist/cli/commands/resource/wait.d.ts +0 -21
  61. package/dist/cli/commands/resource/wait.js +0 -73
  62. package/dist/cli/commands/session/view.d.ts +0 -24
  63. package/dist/cli/commands/session/view.js +0 -145
  64. package/dist/cli/commands/start.d.ts +0 -37
  65. package/dist/cli/commands/start.js +0 -234
  66. package/dist/cli/commands/triage/claim.d.ts +0 -23
  67. package/dist/cli/commands/triage/claim.js +0 -186
  68. package/dist/cli/commands/triage/list.d.ts +0 -22
  69. package/dist/cli/commands/triage/list.js +0 -112
  70. package/dist/cli/commands/triage/next.d.ts +0 -18
  71. package/dist/cli/commands/triage/next.js +0 -63
  72. package/dist/cli/commands/triage/pull.d.ts +0 -19
  73. package/dist/cli/commands/triage/pull.js +0 -82
  74. package/dist/cli/commands/triage/stats.d.ts +0 -16
  75. package/dist/cli/commands/triage/stats.js +0 -69
  76. package/dist/cli/commands/tunnel/list.d.ts +0 -16
  77. package/dist/cli/commands/tunnel/list.js +0 -98
  78. package/dist/cli/commands/tunnel/start.d.ts +0 -24
  79. package/dist/cli/commands/tunnel/start.js +0 -107
  80. package/dist/cli/commands/tunnel/stop.d.ts +0 -20
  81. package/dist/cli/commands/tunnel/stop.js +0 -90
  82. package/dist/cli/commands/tunnel/url.d.ts +0 -21
  83. package/dist/cli/commands/tunnel/url.js +0 -70
  84. package/dist/cli/commands/windows/context.d.ts +0 -18
  85. package/dist/cli/commands/windows/context.js +0 -326
  86. package/dist/cli/commands/windows/focus.d.ts +0 -17
  87. package/dist/cli/commands/windows/focus.js +0 -103
  88. package/dist/cli/commands/windows/list.d.ts +0 -21
  89. package/dist/cli/commands/windows/list.js +0 -172
  90. package/dist/cli/commands/windows/map.d.ts +0 -17
  91. package/dist/cli/commands/windows/map.js +0 -168
  92. package/dist/cli/commands/windows/read.d.ts +0 -21
  93. package/dist/cli/commands/windows/read.js +0 -241
  94. package/dist/cli/commands/windows/search.d.ts +0 -24
  95. package/dist/cli/commands/windows/search.js +0 -171
  96. package/dist/cli/commands/windows/show.d.ts +0 -19
  97. package/dist/cli/commands/windows/show.js +0 -165
  98. package/dist/cli/commands/windows/watch.d.ts +0 -19
  99. package/dist/cli/commands/windows/watch.js +0 -241
  100. package/dist/lib/managed-session.d.ts +0 -27
  101. package/dist/lib/managed-session.js +0 -105
  102. package/dist/lib/panes/broker.d.ts +0 -130
  103. package/dist/lib/panes/broker.js +0 -97
  104. package/dist/lib/panes/index.d.ts +0 -2
  105. package/dist/lib/panes/index.js +0 -1
  106. package/dist/lib/panes/server.d.ts +0 -17
  107. package/dist/lib/panes/server.js +0 -308
  108. package/dist/lib/preview/manager.d.ts +0 -77
  109. package/dist/lib/preview/manager.js +0 -369
  110. package/dist/lib/preview/schema.d.ts +0 -2
  111. package/dist/lib/preview/schema.js +0 -32
  112. package/dist/lib/preview/sprite.d.ts +0 -85
  113. package/dist/lib/preview/sprite.js +0 -321
  114. package/dist/lib/preview/watcher.d.ts +0 -63
  115. package/dist/lib/preview/watcher.js +0 -185
  116. package/dist/lib/project-identity.d.ts +0 -16
  117. package/dist/lib/project-identity.js +0 -75
  118. package/dist/lib/tmux/bridge.d.ts +0 -133
  119. package/dist/lib/tmux/bridge.js +0 -315
  120. package/dist/lib/tmux/context.d.ts +0 -82
  121. package/dist/lib/tmux/context.js +0 -239
  122. package/dist/lib/tmux/index.d.ts +0 -8
  123. package/dist/lib/tmux/index.js +0 -11
  124. package/dist/lib/tmux/map.d.ts +0 -57
  125. package/dist/lib/tmux/map.js +0 -198
  126. package/dist/lib/tmux/panes.d.ts +0 -27
  127. package/dist/lib/tmux/panes.js +0 -151
  128. package/dist/lib/tmux/redaction.d.ts +0 -57
  129. package/dist/lib/tmux/redaction.js +0 -152
  130. package/dist/lib/web/analytics.d.ts +0 -63
  131. package/dist/lib/web/analytics.js +0 -168
  132. package/dist/lib/web/server.d.ts +0 -26
  133. package/dist/lib/web/server.js +0 -697
  134. package/dist/lib/web/tmux-bridge.d.ts +0 -7
  135. package/dist/lib/web/tmux-bridge.js +0 -7
  136. package/dist/lib/windows/index.d.ts +0 -3
  137. package/dist/lib/windows/index.js +0 -2
  138. package/dist/lib/windows/inventory.d.ts +0 -21
  139. package/dist/lib/windows/inventory.js +0 -263
  140. package/dist/lib/windows/types.d.ts +0 -46
  141. package/dist/lib/windows/types.js +0 -1
@@ -1,168 +0,0 @@
1
- import { Flags } from "@oclif/core";
2
- import { getActiveSessionManager } from "../../../lib/active-sessions.js";
3
- import { isRunning } from "../../../lib/tmux/index.js";
4
- import * as windows from "../../../lib/windows/index.js";
5
- import { BaseCommand } from "../../base-command.js";
6
- function abbreviateHome(path) {
7
- const home = process.env.HOME;
8
- if (!home)
9
- return path;
10
- if (path === home)
11
- return "~";
12
- if (path.startsWith(`${home}/`))
13
- return `~/${path.slice(home.length + 1)}`;
14
- return path;
15
- }
16
- function paneRef(window) {
17
- return `${window.session}:${window.window}.${window.pane}`;
18
- }
19
- function pad(value, width) {
20
- if (value.length >= width)
21
- return value;
22
- return value + " ".repeat(width - value.length);
23
- }
24
- export default class WindowsMapCommand extends BaseCommand {
25
- static summary = "Map agent sessions to windows";
26
- static hidden = false;
27
- static examples = [
28
- "$ abbie windows map",
29
- "$ abbie windows map --orphans",
30
- "$ abbie windows map --unmapped",
31
- "$ abbie windows map --json",
32
- ];
33
- static flags = {
34
- ...BaseCommand.baseFlags,
35
- orphans: Flags.boolean({
36
- description: "Show orphan agents (no associated window)",
37
- default: false,
38
- }),
39
- unmapped: Flags.boolean({
40
- description: "Show windows without agents",
41
- default: false,
42
- }),
43
- };
44
- async execute() {
45
- const { flags } = await this.parse(WindowsMapCommand);
46
- this.parsedFlags = flags;
47
- const tmuxRunning = await isRunning();
48
- if (!tmuxRunning) {
49
- const result = {
50
- tmuxRunning: false,
51
- mappings: [],
52
- unmappedWindows: [],
53
- orphanAgents: [],
54
- };
55
- if (!this.jsonEnabled?.()) {
56
- this.log("tmux is not running");
57
- }
58
- return result;
59
- }
60
- const manager = getActiveSessionManager();
61
- const activeSessions = await manager.listAsync({ status: "running" });
62
- const states = await windows.inventory({
63
- includeNvim: false,
64
- includeAgent: true,
65
- includeBuffers: false,
66
- });
67
- const bySessionId = new Map();
68
- const byPid = new Map();
69
- for (const state of states) {
70
- if (state.agent?.sessionId) {
71
- bySessionId.set(state.agent.sessionId, state);
72
- }
73
- if (state.agent?.pid) {
74
- byPid.set(state.agent.pid, state);
75
- }
76
- }
77
- const mappings = [];
78
- for (const session of activeSessions) {
79
- let matched;
80
- let match = "none";
81
- if (bySessionId.has(session.session_id)) {
82
- matched = bySessionId.get(session.session_id);
83
- match = "session-id";
84
- }
85
- else if (typeof session.agent_pid === "number" && byPid.has(session.agent_pid)) {
86
- matched = byPid.get(session.agent_pid);
87
- match = "pid";
88
- }
89
- mappings.push({
90
- session: session.session_id,
91
- agent: session.agent,
92
- status: session.status,
93
- window: matched ? paneRef(matched.window) : null,
94
- paneId: matched?.window.paneId || null,
95
- cmd: matched?.window.title || null,
96
- cwd: matched ? abbreviateHome(matched.window.cwd) : session.cwd,
97
- match,
98
- pid: session.agent_pid ?? null,
99
- issue: session.issue,
100
- });
101
- }
102
- const unmappedWindows = states
103
- .filter((s) => !s.agent)
104
- .map((s) => ({
105
- paneId: s.window.paneId || paneRef(s.window),
106
- ref: paneRef(s.window),
107
- cmd: s.window.title,
108
- cwd: abbreviateHome(s.window.cwd),
109
- active: s.window.active,
110
- }))
111
- .sort((a, b) => a.ref.localeCompare(b.ref));
112
- const orphanAgents = mappings
113
- .filter((m) => m.window === null)
114
- .map((m) => ({
115
- session: m.session,
116
- agent: m.agent,
117
- status: m.status,
118
- pid: m.pid,
119
- cwd: m.cwd ?? "",
120
- }));
121
- const result = { tmuxRunning: true, mappings, unmappedWindows, orphanAgents };
122
- if (!this.jsonEnabled?.()) {
123
- this.printText(result, flags);
124
- }
125
- return result;
126
- }
127
- printText(result, flags) {
128
- const mapped = result.mappings.filter((m) => m.window !== null);
129
- if (mapped.length === 0) {
130
- this.log("No agent mappings found");
131
- }
132
- else {
133
- const sessionWidth = Math.max("SESSION".length, ...mapped.map((m) => m.session.length));
134
- const agentWidth = Math.max("AGENT".length, ...mapped.map((m) => m.agent.length));
135
- const windowWidth = Math.max("WINDOW".length, ...mapped.map((m) => (m.window ?? "").length));
136
- this.log("AGENT MAPPINGS");
137
- this.log(`${pad("SESSION", sessionWidth)} ${pad("AGENT", agentWidth)} ${pad("WINDOW", windowWidth)} STATUS`);
138
- for (const m of mapped) {
139
- this.log(`${pad(m.session, sessionWidth)} ${pad(m.agent, agentWidth)} ${pad(m.window ?? "-", windowWidth)} ${m.status}`);
140
- }
141
- }
142
- if (flags.unmapped) {
143
- this.log("");
144
- this.log("UNMAPPED WINDOWS (--unmapped)");
145
- if (result.unmappedWindows.length === 0) {
146
- this.log("None");
147
- }
148
- else {
149
- for (const w of result.unmappedWindows) {
150
- this.log(`${w.paneId} ${w.ref} ${w.cmd} ${w.cwd}${w.active ? " [active]" : ""}`);
151
- }
152
- }
153
- }
154
- if (flags.orphans) {
155
- this.log("");
156
- this.log("ORPHAN AGENTS (--orphans)");
157
- if (result.orphanAgents.length === 0) {
158
- this.log("None");
159
- }
160
- else {
161
- for (const a of result.orphanAgents) {
162
- const pidStr = a.pid ? `PID ${a.pid}` : "PID -";
163
- this.log(`${pidStr} (${a.agent}) - no associated window (${a.session})`);
164
- }
165
- }
166
- }
167
- }
168
- }
@@ -1,21 +0,0 @@
1
- import { BaseCommand } from "../../base-command.js";
2
- export default class WindowsReadCommand extends BaseCommand {
3
- static summary: string;
4
- static hidden: boolean;
5
- static examples: string[];
6
- static args: {
7
- ref: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
- };
9
- static flags: {
10
- scope: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
- lines: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
12
- redact: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
- format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
- quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
- "json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
- ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
- };
18
- execute(): Promise<unknown>;
19
- private printText;
20
- }
21
- //# sourceMappingURL=read.d.ts.map
@@ -1,241 +0,0 @@
1
- import { Args, Flags } from "@oclif/core";
2
- import { getBufferLines, getCurrentBufferInfo, getVisibleRange } from "../../../lib/nvim/remote.js";
3
- import { isRunning } from "../../../lib/tmux/index.js";
4
- import { redactLine } from "../../../lib/tmux/redaction.js";
5
- import * as windows from "../../../lib/windows/index.js";
6
- import { BaseCommand } from "../../base-command.js";
7
- function abbreviateHome(path) {
8
- const home = process.env.HOME;
9
- if (!home)
10
- return path;
11
- if (path === home)
12
- return "~";
13
- if (path.startsWith(`${home}/`))
14
- return `~/${path.slice(home.length + 1)}`;
15
- return path;
16
- }
17
- function paneRef(window) {
18
- return `${window.session}:${window.window}.${window.pane}`;
19
- }
20
- function formatPathForDisplay(path, cwd) {
21
- if (!path)
22
- return path;
23
- const normalizedCwd = cwd.endsWith("/") ? cwd : `${cwd}/`;
24
- if (path.startsWith(normalizedCwd)) {
25
- return path.slice(normalizedCwd.length);
26
- }
27
- return abbreviateHome(path);
28
- }
29
- export default class WindowsReadCommand extends BaseCommand {
30
- static summary = "Read nvim buffer content for a window";
31
- static hidden = false;
32
- static examples = [
33
- "$ abbie windows read",
34
- "$ abbie windows read %3",
35
- "$ abbie windows read --scope visible",
36
- "$ abbie windows read --scope cursor",
37
- "$ abbie windows read --scope all",
38
- "$ abbie windows read --lines 50",
39
- "$ abbie windows read --no-redact",
40
- "$ abbie windows read --json",
41
- ];
42
- static args = {
43
- ref: Args.string({
44
- description: "Pane ID (e.g. %3) or session:window.pane (e.g. work:0.0)",
45
- required: false,
46
- }),
47
- };
48
- static flags = {
49
- ...BaseCommand.baseFlags,
50
- scope: Flags.string({
51
- description: "Read scope",
52
- options: ["visible", "cursor", "all"],
53
- default: "visible",
54
- }),
55
- lines: Flags.integer({
56
- description: "Maximum lines to read",
57
- default: 50,
58
- }),
59
- redact: Flags.boolean({
60
- description: "Enable redaction",
61
- default: true,
62
- allowNo: true,
63
- }),
64
- };
65
- async execute() {
66
- const { args, flags } = await this.parse(WindowsReadCommand);
67
- this.parsedFlags = flags;
68
- const scope = flags.scope;
69
- const maxLines = Math.max(1, flags.lines);
70
- const tmuxRunning = await isRunning();
71
- if (!tmuxRunning) {
72
- const result = {
73
- tmuxRunning: false,
74
- window: null,
75
- ref: null,
76
- scope,
77
- startLine: null,
78
- endLine: null,
79
- buffer: null,
80
- lines: [],
81
- redacted: flags.redact,
82
- wasRedacted: false,
83
- };
84
- if (!this.jsonEnabled?.()) {
85
- this.log("tmux is not running");
86
- }
87
- return result;
88
- }
89
- const state = args.ref
90
- ? await windows.getWindowState(args.ref, {
91
- includeNvim: true,
92
- includeAgent: false,
93
- includeBuffers: false,
94
- })
95
- : await windows.getFocusedWindow({
96
- includeNvim: true,
97
- includeAgent: false,
98
- includeBuffers: false,
99
- });
100
- if (!state) {
101
- const result = {
102
- tmuxRunning: true,
103
- window: null,
104
- ref: null,
105
- scope,
106
- startLine: null,
107
- endLine: null,
108
- buffer: null,
109
- lines: [],
110
- redacted: flags.redact,
111
- wasRedacted: false,
112
- };
113
- if (!this.jsonEnabled?.()) {
114
- this.log("Window not found");
115
- }
116
- return result;
117
- }
118
- const nvimState = state.nvim;
119
- if (!nvimState?.available || !nvimState.serverAddr) {
120
- const result = {
121
- tmuxRunning: true,
122
- window: state.window,
123
- ref: paneRef(state.window),
124
- scope,
125
- startLine: null,
126
- endLine: null,
127
- buffer: null,
128
- lines: [],
129
- redacted: flags.redact,
130
- wasRedacted: false,
131
- };
132
- if (!this.jsonEnabled?.()) {
133
- this.log("nvim is not available for this window");
134
- }
135
- return result;
136
- }
137
- const serverAddr = nvimState.serverAddr;
138
- const bufferInfo = await getCurrentBufferInfo(serverAddr);
139
- if (!bufferInfo) {
140
- const result = {
141
- tmuxRunning: true,
142
- window: state.window,
143
- ref: paneRef(state.window),
144
- scope,
145
- startLine: null,
146
- endLine: null,
147
- buffer: null,
148
- lines: [],
149
- redacted: flags.redact,
150
- wasRedacted: false,
151
- };
152
- if (!this.jsonEnabled?.()) {
153
- this.log("Unable to query nvim current buffer");
154
- }
155
- return result;
156
- }
157
- let startLine = 1;
158
- let endLine = 1;
159
- let cursor = bufferInfo.cursor ?? { line: 1, col: 1 };
160
- if (scope === "visible") {
161
- const range = await getVisibleRange(serverAddr, bufferInfo.bufnr);
162
- if (range) {
163
- startLine = range.topLine;
164
- endLine = Math.min(range.bottomLine, range.topLine + maxLines - 1);
165
- cursor = range.cursor;
166
- }
167
- else {
168
- endLine = startLine + maxLines - 1;
169
- }
170
- }
171
- else if (scope === "cursor") {
172
- const desiredHalf = Math.min(20, Math.floor((maxLines - 1) / 2));
173
- startLine = Math.max(1, cursor.line - desiredHalf);
174
- endLine = startLine + Math.min(maxLines, desiredHalf * 2 + 1) - 1;
175
- }
176
- else {
177
- startLine = 1;
178
- endLine = startLine + maxLines - 1;
179
- }
180
- const rawLines = await getBufferLines(serverAddr, bufferInfo.bufnr, startLine, endLine);
181
- if (!rawLines) {
182
- const result = {
183
- tmuxRunning: true,
184
- window: state.window,
185
- ref: paneRef(state.window),
186
- scope,
187
- startLine,
188
- endLine,
189
- buffer: bufferInfo,
190
- lines: [],
191
- redacted: flags.redact,
192
- wasRedacted: false,
193
- };
194
- if (!this.jsonEnabled?.()) {
195
- this.log("Unable to read buffer content");
196
- }
197
- return result;
198
- }
199
- let wasRedacted = false;
200
- const renderedLines = rawLines.map((line) => {
201
- if (!flags.redact)
202
- return line;
203
- const redacted = redactLine(line);
204
- if (redacted !== line)
205
- wasRedacted = true;
206
- return redacted;
207
- });
208
- const result = {
209
- tmuxRunning: true,
210
- window: state.window,
211
- ref: paneRef(state.window),
212
- scope,
213
- startLine,
214
- endLine,
215
- buffer: { ...bufferInfo, cursor },
216
- lines: renderedLines,
217
- redacted: flags.redact,
218
- wasRedacted,
219
- };
220
- if (!this.jsonEnabled?.()) {
221
- this.printText(result);
222
- }
223
- return result;
224
- }
225
- printText(result) {
226
- if (!result.window || !result.buffer || result.startLine === null || result.endLine === null) {
227
- this.log("No buffer content available");
228
- return;
229
- }
230
- const displayPath = formatPathForDisplay(result.buffer.name, result.window.cwd);
231
- this.log(`BUFFER ${displayPath} (${result.buffer.filetype || "unknown"})`);
232
- this.log(`Window: ${result.window.paneId || "-"} (${result.ref})`);
233
- this.log(`Scope: ${result.scope} (lines ${result.startLine}-${result.endLine})`);
234
- this.log("");
235
- const width = String(result.endLine).length;
236
- for (let i = 0; i < result.lines.length; i++) {
237
- const lineNo = result.startLine + i;
238
- this.log(` ${String(lineNo).padStart(width)} │ ${result.lines[i]}`);
239
- }
240
- }
241
- }
@@ -1,24 +0,0 @@
1
- import { BaseCommand } from "../../base-command.js";
2
- export default class WindowsSearchCommand extends BaseCommand {
3
- static summary: string;
4
- static hidden: boolean;
5
- static description: string;
6
- static examples: string[];
7
- static args: {
8
- query: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
9
- };
10
- static flags: {
11
- session: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
- context: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
13
- lines: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
14
- redact: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
- limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
16
- format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
- quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
- "json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
- ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
20
- };
21
- execute(): Promise<unknown>;
22
- private printText;
23
- }
24
- //# sourceMappingURL=search.d.ts.map
@@ -1,171 +0,0 @@
1
- import { Args, Flags } from "@oclif/core";
2
- import { capturePane } from "../../../lib/tmux/bridge.js";
3
- import { isRunning } from "../../../lib/tmux/index.js";
4
- import { redactLine } from "../../../lib/tmux/redaction.js";
5
- import * as windows from "../../../lib/windows/index.js";
6
- import { BaseCommand } from "../../base-command.js";
7
- function abbreviateHome(path) {
8
- const home = process.env.HOME;
9
- if (!home)
10
- return path;
11
- if (path === home)
12
- return "~";
13
- if (path.startsWith(`${home}/`))
14
- return `~/${path.slice(home.length + 1)}`;
15
- return path;
16
- }
17
- function paneRef(window) {
18
- return `${window.session}:${window.window}.${window.pane}`;
19
- }
20
- export default class WindowsSearchCommand extends BaseCommand {
21
- static summary = "Search scrollback content across all tmux panes";
22
- static hidden = false;
23
- static description = "Searches terminal scrollback across all tmux panes for a pattern. " +
24
- "Uses tmux capture-pane to read scrollback history (up to 10,000 lines per pane).";
25
- static examples = [
26
- '$ abbie windows search "spatial"',
27
- '$ abbie windows search "TODO" --context 3',
28
- '$ abbie windows search "error" --session 2 --lines 5000',
29
- '$ abbie windows search "ARBOR-123" --json',
30
- ];
31
- static args = {
32
- query: Args.string({
33
- description: "Search pattern (case-insensitive regex)",
34
- required: true,
35
- }),
36
- };
37
- static flags = {
38
- ...BaseCommand.baseFlags,
39
- session: Flags.string({
40
- char: "s",
41
- description: "Filter to specific tmux session",
42
- }),
43
- context: Flags.integer({
44
- char: "C",
45
- description: "Lines of context around each match",
46
- default: 1,
47
- }),
48
- lines: Flags.integer({
49
- char: "n",
50
- description: "Maximum scrollback lines to search per pane",
51
- default: 10000,
52
- }),
53
- redact: Flags.boolean({
54
- description: "Enable redaction of sensitive content",
55
- default: true,
56
- allowNo: true,
57
- }),
58
- limit: Flags.integer({
59
- char: "l",
60
- description: "Maximum matches per pane",
61
- default: 20,
62
- }),
63
- };
64
- async execute() {
65
- const { args, flags } = await this.parse(WindowsSearchCommand);
66
- this.parsedFlags = flags;
67
- const query = args.query;
68
- const contextLines = Math.max(0, flags.context);
69
- const maxLines = Math.max(100, flags.lines);
70
- const maxMatchesPerPane = Math.max(1, flags.limit);
71
- const tmuxRunning = await isRunning();
72
- if (!tmuxRunning) {
73
- const result = { tmuxRunning: false, query, totalMatches: 0, windows: [] };
74
- if (!this.jsonEnabled?.()) {
75
- this.log("tmux is not running");
76
- }
77
- return result;
78
- }
79
- // Get all panes
80
- const states = await windows.inventory({
81
- session: flags.session,
82
- includeNvim: false,
83
- includeAgent: false,
84
- includeBuffers: false,
85
- });
86
- let pattern;
87
- try {
88
- pattern = new RegExp(query, "i");
89
- }
90
- catch {
91
- this.error(`Invalid regex pattern: ${query}`);
92
- }
93
- const windowMatches = [];
94
- let totalMatches = 0;
95
- // Search each pane's scrollback
96
- for (const state of states) {
97
- const w = state.window;
98
- const ref = paneRef(w);
99
- // Capture scrollback via tmux (works for all panes, nvim or not)
100
- const content = await capturePane(w.window, w.pane, {
101
- lines: maxLines,
102
- session: w.session,
103
- });
104
- if (!content)
105
- continue;
106
- const lines = content.split("\n");
107
- const matches = [];
108
- for (let i = 0; i < lines.length; i++) {
109
- if (matches.length >= maxMatchesPerPane)
110
- break;
111
- const line = lines[i];
112
- if (!pattern.test(line))
113
- continue;
114
- const displayLine = flags.redact ? redactLine(line) : line;
115
- // Gather context lines
116
- const ctx = [];
117
- if (contextLines > 0) {
118
- const start = Math.max(0, i - contextLines);
119
- const end = Math.min(lines.length - 1, i + contextLines);
120
- for (let j = start; j <= end; j++) {
121
- if (j === i)
122
- continue;
123
- const ctxLine = flags.redact ? redactLine(lines[j]) : lines[j];
124
- ctx.push(ctxLine);
125
- }
126
- }
127
- matches.push({
128
- lineNo: i + 1,
129
- line: displayLine,
130
- context: ctx.length > 0 ? ctx : undefined,
131
- });
132
- }
133
- if (matches.length > 0) {
134
- totalMatches += matches.length;
135
- windowMatches.push({
136
- paneId: w.paneId || ref,
137
- ref,
138
- session: w.session,
139
- windowName: w.windowName,
140
- cwd: abbreviateHome(w.cwd),
141
- matches,
142
- });
143
- }
144
- }
145
- const result = {
146
- tmuxRunning: true,
147
- query,
148
- totalMatches,
149
- windows: windowMatches,
150
- };
151
- if (!this.jsonEnabled?.()) {
152
- this.printText(result);
153
- }
154
- return result;
155
- }
156
- printText(result) {
157
- if (result.totalMatches === 0) {
158
- this.log(`No matches for "${result.query}"`);
159
- return;
160
- }
161
- this.log(`${result.totalMatches} match${result.totalMatches === 1 ? "" : "es"} across ${result.windows.length} window${result.windows.length === 1 ? "" : "s"}`);
162
- this.log("");
163
- for (const w of result.windows) {
164
- this.log(`── ${w.paneId} (${w.windowName}) ${w.cwd} ──`);
165
- for (const m of w.matches) {
166
- this.log(` ${String(m.lineNo).padStart(6)} │ ${m.line}`);
167
- }
168
- this.log("");
169
- }
170
- }
171
- }
@@ -1,19 +0,0 @@
1
- import { BaseCommand } from "../../base-command.js";
2
- export default class WindowsShowCommand extends BaseCommand {
3
- static summary: string;
4
- static hidden: boolean;
5
- static examples: string[];
6
- static args: {
7
- ref: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
- };
9
- static flags: {
10
- "with-buffers": import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
- format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
- quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
- "json-errors": import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
- ndjson: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
- };
16
- execute(): Promise<unknown>;
17
- private printText;
18
- }
19
- //# sourceMappingURL=show.d.ts.map