pi-quiet 0.1.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 (3) hide show
  1. package/README.md +53 -0
  2. package/package.json +37 -0
  3. package/src/index.ts +76 -0
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # pi-quiet
2
+
3
+ Calm tool rendering for the [pi](https://pi.dev) coding agent.
4
+
5
+ pi renders every bash call with the full command text, a multi-line output
6
+ preview, and timing — useful when you're debugging a command, noisy when the
7
+ agent is doing routine work. `pi-quiet` collapses each bash call to two lines:
8
+
9
+ ```
10
+ $ ls -la /tmp | head -20
11
+ → ok · 15 lines · … -rw-r--r-- 1 user staff 5742 Aug 26 22:17 README.md
12
+ ```
13
+
14
+ Multi-line commands show `(+N lines)`. Failures show a red `error`. Streaming
15
+ shows `… running`.
16
+
17
+ Press **ctrl+o** (pi's `app.tools.expand` binding) and the stock built-in
18
+ rendering returns in full — complete commands, full output, truncation
19
+ warnings. Press it again to re-collapse. It's a live toggle over the whole
20
+ transcript: work collapsed, expand when something looks off.
21
+
22
+ ## Display-only, by construction
23
+
24
+ The extension re-registers the built-in `bash` tool via pi's own
25
+ `createBashToolDefinition` and overrides only the two render slots. Execution
26
+ *is* the built-in tool:
27
+
28
+ - the model receives the full, untruncated-by-us output;
29
+ - permission systems, reviewers, and sandboxes that hook execution are
30
+ unaffected;
31
+ - session logs store the full result.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pi install npm:pi-quiet
37
+ ```
38
+
39
+ Or try it for one session:
40
+
41
+ ```bash
42
+ pi -e npm:pi-quiet
43
+ ```
44
+
45
+ pi shows a one-time notice that the built-in `bash` tool was overridden —
46
+ that's this extension, and it's expected.
47
+
48
+ ## Caveats
49
+
50
+ - Covers `bash` only (the dominant chatter source). `read`/`grep`/`find`/`ls`
51
+ may follow.
52
+ - The expanded path delegates to pi's built-in renderer, so a pi upgrade that
53
+ reshapes renderer internals can require a patch release here.
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "pi-quiet",
3
+ "version": "0.1.0",
4
+ "description": "Calm tool rendering for the pi coding agent: each bash call collapses to one line; ctrl+o brings back full built-in rendering. Display-only — execution, permissions, and model context are untouched.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/schuettc/pi-extensions.git",
10
+ "directory": "packages/pi-quiet"
11
+ },
12
+ "keywords": [
13
+ "pi-package",
14
+ "pi-extension",
15
+ "pi-coding-agent",
16
+ "tui",
17
+ "tool-output",
18
+ "quiet"
19
+ ],
20
+ "files": [
21
+ "src",
22
+ "README.md"
23
+ ],
24
+ "pi": {
25
+ "extensions": [
26
+ "./src/index.ts"
27
+ ]
28
+ },
29
+ "scripts": {
30
+ "typecheck": "tsc --noEmit -p tsconfig.json"
31
+ },
32
+ "devDependencies": {
33
+ "@earendil-works/pi-coding-agent": "^0.84.3",
34
+ "@earendil-works/pi-tui": "^0.84.3",
35
+ "typescript": "^5.6.0"
36
+ }
37
+ }
package/src/index.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * quiet-tools: collapse bash tool chatter to one line per call.
3
+ *
4
+ * Re-registers the built-in bash tool (execution untouched — it IS the
5
+ * built-in, via createBashToolDefinition) and overrides only the two render
6
+ * slots. Collapsed (the default): the call renders as a single truncated
7
+ * `$ command` line and the result as a single muted summary line. Expanded
8
+ * (ctrl+o / app.tools.expand): both slots defer to the built-in renderer,
9
+ * so the full command, streamed output, truncation warnings, and duration
10
+ * come back exactly as stock pi shows them.
11
+ *
12
+ * Display-only by design: permission gating, auto-review, and the sandbox
13
+ * all hook execution, which this file never touches.
14
+ */
15
+
16
+ import {
17
+ createBashToolDefinition,
18
+ type ExtensionAPI,
19
+ } from "@earendil-works/pi-coding-agent";
20
+ import { Text } from "@earendil-works/pi-tui";
21
+
22
+ function firstLine(command: string): { line: string; more: number } {
23
+ const lines = command.split("\n");
24
+ return { line: lines[0] ?? "", more: lines.length - 1 };
25
+ }
26
+
27
+ function resultText(result: { content?: { type: string; text?: string }[] }): string {
28
+ return (result.content ?? [])
29
+ .filter((c) => c.type === "text")
30
+ .map((c) => c.text ?? "")
31
+ .join("\n");
32
+ }
33
+
34
+ export default function quietTools(pi: ExtensionAPI) {
35
+ const builtin = createBashToolDefinition(process.cwd());
36
+
37
+ pi.registerTool({
38
+ ...builtin,
39
+
40
+ renderCall(args: any, theme: any, context: any) {
41
+ if (context.expanded && builtin.renderCall) {
42
+ return builtin.renderCall(args, theme, context);
43
+ }
44
+ const command = typeof args?.command === "string" ? args.command : "...";
45
+ const { line, more } = firstLine(command.trim());
46
+ const suffix = more > 0 ? theme.fg("muted", ` (+${more} lines)`) : "";
47
+ // Text handles width truncation; keep the line itself short anyway so
48
+ // narrow panes stay one visual row.
49
+ const shown = line.length > 200 ? `${line.slice(0, 200)}…` : line;
50
+ return new Text(
51
+ theme.fg("toolTitle", theme.bold(`$ ${shown}`)) + suffix,
52
+ 0,
53
+ 0,
54
+ );
55
+ },
56
+
57
+ renderResult(result: any, options: any, theme: any, context: any) {
58
+ if (options.expanded && builtin.renderResult) {
59
+ return builtin.renderResult(result, options, theme, context);
60
+ }
61
+ if (options.isPartial) {
62
+ return new Text(theme.fg("muted", " … running"), 0, 0);
63
+ }
64
+ const text = resultText(result).trim();
65
+ const lineCount = text ? text.split("\n").length : 0;
66
+ const status = result.isError ? theme.fg("error", "error") : "ok";
67
+ const tail = text ? text.split("\n").at(-1) ?? "" : "";
68
+ const tailShown = tail.length > 120 ? `${tail.slice(0, 120)}…` : tail;
69
+ const summary =
70
+ lineCount <= 1
71
+ ? ` → ${status}${tailShown ? theme.fg("toolOutput", ` · ${tailShown}`) : ""}`
72
+ : ` → ${status} · ${lineCount} lines${tailShown ? theme.fg("toolOutput", ` · … ${tailShown}`) : ""}`;
73
+ return new Text(theme.fg("muted", summary), 0, 0);
74
+ },
75
+ });
76
+ }