aboutsummaryrefslogtreecommitdiffstats
path: root/examples/pi
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@atuin.sh>2026-04-13 20:41:30 +0100
committerGitHub <noreply@github.com>2026-04-13 20:41:30 +0100
commit129ad222d2ea2896a06ed29cbce5faa0b0d7399e (patch)
tree06eca765ff80c62581ec69a23a631bdf64aaedfb /examples/pi
parentfeat: remove agent search from tui (#3397) (diff)
downloadatuin-129ad222d2ea2896a06ed29cbce5faa0b0d7399e.zip
feat: add pi hook installer (#3398)
Support installing the pi extension via `atuin hook install pi`. Bundle the extension in the binary and update the docs. <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
Diffstat (limited to 'examples/pi')
-rw-r--r--examples/pi/atuin.ts87
1 files changed, 87 insertions, 0 deletions
diff --git a/examples/pi/atuin.ts b/examples/pi/atuin.ts
new file mode 100644
index 00000000..55c17cb8
--- /dev/null
+++ b/examples/pi/atuin.ts
@@ -0,0 +1,87 @@
+/**
+ * Atuin extension for pi.
+ *
+ * Tracks bash commands executed by pi in Atuin history with author `pi`.
+ *
+ * Install with:
+ * atuin hook install pi
+ *
+ * Then restart pi or run /reload.
+ */
+
+import type { BashOperations, ExtensionAPI } from "@mariozechner/pi-coding-agent";
+import { createBashTool, createLocalBashOperations } from "@mariozechner/pi-coding-agent";
+
+const ATUIN_AUTHOR = "pi";
+const ATUIN_TIMEOUT_MS = 10_000;
+
+async function startHistory(
+ pi: ExtensionAPI,
+ cwd: string,
+ command: string,
+): Promise<string | undefined> {
+ try {
+ const result = await pi.exec(
+ "atuin",
+ ["history", "start", "--author", ATUIN_AUTHOR, "--", command],
+ { cwd, timeout: ATUIN_TIMEOUT_MS },
+ );
+
+ if (result.code !== 0) return undefined;
+
+ const id = result.stdout.trim();
+ return id.length > 0 ? id : undefined;
+ } catch {
+ return undefined;
+ }
+}
+
+async function endHistory(
+ pi: ExtensionAPI,
+ cwd: string,
+ historyId: string,
+ exitCode: number,
+): Promise<void> {
+ try {
+ await pi.exec(
+ "atuin",
+ ["history", "end", historyId, "--exit", String(exitCode)],
+ { cwd, timeout: ATUIN_TIMEOUT_MS },
+ );
+ } catch {
+ // Ignore Atuin failures so command execution is never blocked.
+ }
+}
+
+export default function atuinPiExtension(pi: ExtensionAPI) {
+ const cwd = process.cwd();
+ const local = createLocalBashOperations();
+
+ const trackedOperations: BashOperations = {
+ async exec(command, commandCwd, options) {
+ const historyId = await startHistory(pi, commandCwd, command);
+ let exitCode: number | null = null;
+
+ try {
+ const result = await local.exec(command, commandCwd, options);
+ exitCode = result.exitCode;
+ return result;
+ } finally {
+ if (historyId) {
+ await endHistory(
+ pi,
+ commandCwd,
+ historyId,
+ exitCode ?? (options.signal?.aborted ? 130 : 1),
+ );
+ }
+ }
+ },
+ };
+
+ pi.registerTool(
+ createBashTool(cwd, {
+ operations: trackedOperations,
+ }),
+ );
+}