From 90c353d4d42752ddf4c3fed451593d2cb20e4a82 Mon Sep 17 00:00:00 2001 From: Atlas-Key <296298943+Atlas-Key@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:08:13 -0400 Subject: [PATCH 1/3] fix(pi-leader-key): bind palette to Ctrl+Q, not Ctrl+X Pi already uses ctrl+x for app.message.copy, so the extension shortcut was skipped. --- AGENTS.md | 2 +- README.md | 2 +- extensions/pi-leader-key/AGENTS.md | 4 +++- extensions/pi-leader-key/README.md | 6 +++--- extensions/pi-leader-key/package.json | 2 +- extensions/pi-leader-key/src/index.ts | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c38c212..fa63844 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -59,7 +59,7 @@ Interactive tests may run Pi in a bounded tmux session, send input, capture the - `extensions/pi-anti-slop/AGENTS.md` - anti-authorship firewall, scanner packaging, licensing, and verification. - `extensions/pi-better-ask-user/AGENTS.md` - decision UI, preview workflow, Herdr integration, and verification. - `extensions/pi-better-btw/AGENTS.md` - temporary side-conversation overlay behavior and verification. -- `extensions/pi-leader-key/AGENTS.md` - Ctrl+X leader palette, model pickers, and verification. +- `extensions/pi-leader-key/AGENTS.md` - Ctrl+Q leader palette, model pickers, and verification. - `extensions/pi-tool-pills/AGENTS.md` - tool pills, collapsed output, write/edit diffs, and verification. ## Maintaining this file diff --git a/README.md b/README.md index 68bb7c9..0a313d4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The root Pi manifest exposes these Atlas-owned private workspaces: - [`pi-anti-slop`](./extensions/pi-anti-slop/README.md) - substance-defect review and repair skills plus a local house-style gate - [`pi-better-ask-user`](./extensions/pi-better-ask-user/README.md) - interactive decision UI, decision-gate skill, and optional Herdr integration - [`pi-better-btw`](./extensions/pi-better-btw/README.md) - temporary in-memory side conversation overlay -- [`pi-leader-key`](./extensions/pi-leader-key/README.md) - Ctrl+X leader-key command palette +- [`pi-leader-key`](./extensions/pi-leader-key/README.md) - Ctrl+Q leader-key command palette - [`pi-tool-pills`](./extensions/pi-tool-pills/README.md) - colored tool pills and Shiki diffs for built-in tools The collection is a single Git-installable Pi package. The tutorial below explains how to install it, select its resources, develop against a local checkout, and publish updates. diff --git a/extensions/pi-leader-key/AGENTS.md b/extensions/pi-leader-key/AGENTS.md index 5ebe19c..c235b31 100644 --- a/extensions/pi-leader-key/AGENTS.md +++ b/extensions/pi-leader-key/AGENTS.md @@ -2,7 +2,9 @@ ## Purpose -Provide a Ctrl+X / `/lk` leader-key overlay that groups frequent Pi actions, including scoped-model and model-switcher flows. +Provide a Ctrl+Q / `/lk` leader-key overlay that groups frequent Pi actions, including scoped-model and model-switcher flows. + +Do not bind `ctrl+x`: current Pi uses it for `app.message.copy` (and scoped-models `app.models.clearAll`), so the extension shortcut is skipped. ## Ownership diff --git a/extensions/pi-leader-key/README.md b/extensions/pi-leader-key/README.md index b8af732..597465b 100644 --- a/extensions/pi-leader-key/README.md +++ b/extensions/pi-leader-key/README.md @@ -1,8 +1,8 @@ # pi-leader-key -Ctrl+X leader-key command palette for [pi](https://github.com/earendil-works/pi). +Ctrl+Q leader-key command palette for [pi](https://github.com/earendil-works/pi). -Press `Ctrl+X` (or run `/lk`) to open a floating palette of grouped actions, then press a chord and an action key. The palette is an Atlas-owned port of [tomsej's leader-key extension](https://github.com/tomsej/pi-ext). +Press `Ctrl+Q` (or run `/lk`) to open a floating palette of grouped actions, then press a chord and an action key. Pi already binds `Ctrl+X` to copy the last assistant message, so this extension does not register that shortcut. The palette is an Atlas-owned port of [tomsej's leader-key extension](https://github.com/tomsej/pi-ext). ## Install @@ -28,7 +28,7 @@ This workspace remains private and is not published to npm. Run `/reload` after ## Usage -- `Ctrl+X` or `/lk` opens the leader palette +- `Ctrl+Q` or `/lk` opens the leader palette - `Ctrl+M` opens the scoped-models picker directly - Chord keys open a group; a letter key runs an action - `Esc` / `Backspace` goes back or closes diff --git a/extensions/pi-leader-key/package.json b/extensions/pi-leader-key/package.json index 0a5d268..c8c7d0e 100644 --- a/extensions/pi-leader-key/package.json +++ b/extensions/pi-leader-key/package.json @@ -2,7 +2,7 @@ "name": "@edheltzel/pi-leader-key", "version": "0.1.0", "private": true, - "description": "Ctrl+X leader-key command palette for Pi", + "description": "Ctrl+Q leader-key command palette for Pi", "keywords": [ "extension", "leader-key", diff --git a/extensions/pi-leader-key/src/index.ts b/extensions/pi-leader-key/src/index.ts index cc015e4..7d6d168 100644 --- a/extensions/pi-leader-key/src/index.ts +++ b/extensions/pi-leader-key/src/index.ts @@ -1,7 +1,7 @@ /** * Leader Key Extension * - * Press Ctrl+X to open a floating command palette showing available + * Press Ctrl+Q to open a floating command palette showing available * actions organised into groups (like Vim's which-key or Emacs' leader key). * * Ported from tomsej/pi-ext leader-key (MIT). @@ -350,7 +350,7 @@ export default function leaderKeyExtension(pi: ExtensionAPI) { }, }); - pi.registerShortcut(Key.ctrl("x"), { + pi.registerShortcut(Key.ctrl("q"), { description: "Open Leader Key", handler: async (ctx) => { await openLeaderKey(ctx); From fe7f7df5eaf1607877bce5973e1665b752741ac2 Mon Sep 17 00:00:00 2001 From: Atlas-Key <296298943+Atlas-Key@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:23:33 -0400 Subject: [PATCH 2/3] no-mistakes(document): Confirm Ctrl+Q docs and flag test typing --- .../pi-leader-key/tests/overlay.unit.test.ts | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/extensions/pi-leader-key/tests/overlay.unit.test.ts b/extensions/pi-leader-key/tests/overlay.unit.test.ts index 36f1c59..76ed798 100644 --- a/extensions/pi-leader-key/tests/overlay.unit.test.ts +++ b/extensions/pi-leader-key/tests/overlay.unit.test.ts @@ -1,7 +1,7 @@ -import { describe, expect, it } from "vitest"; -import type { Theme } from "@earendil-works/pi-coding-agent"; -import { visibleWidth } from "@earendil-works/pi-tui"; -import { buildEntries, LeaderKeyOverlay } from "../src/index"; +import { describe, expect, it, vi } from "vitest"; +import type { ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent"; +import { Key, visibleWidth } from "@earendil-works/pi-tui"; +import leaderKeyExtension, { buildEntries, LeaderKeyOverlay } from "../src/index"; import { OverlayFrame, padToWidth } from "../src/overlay"; const theme = { @@ -9,6 +9,46 @@ const theme = { bold: (text: string) => text, } as unknown as Theme; +describe("extension registration", () => { + it("opens the palette from Ctrl+Q and /lk without registering Ctrl+X", async () => { + type Shortcut = { handler: (ctx: ExtensionContext) => Promise }; + type Command = { handler: (args: string, ctx: ExtensionContext) => Promise }; + + const shortcuts = new Map(); + const commands = new Map(); + const pi = { + on: vi.fn(), + registerShortcut: vi.fn((key: string, shortcut: Shortcut) => { + shortcuts.set(key, shortcut); + }), + registerCommand: vi.fn((name: string, command: Command) => { + commands.set(name, command); + }), + } as unknown as ExtensionAPI; + + leaderKeyExtension(pi); + + expect([...shortcuts.keys()]).toEqual([Key.ctrl("q")]); + expect(shortcuts.has(Key.ctrl("x"))).toBe(false); + expect([...commands.keys()]).toContain("lk"); + + const shortcut = shortcuts.get(Key.ctrl("q")); + const command = commands.get("lk"); + if (!shortcut || !command) throw new Error("Leader key triggers were not registered"); + + const custom = vi.fn(async () => null); + const ctx = { hasUI: true, ui: { custom } } as unknown as ExtensionContext; + await shortcut.handler(ctx); + await command.handler("", ctx); + + expect(custom).toHaveBeenCalledTimes(2); + expect(custom.mock.calls[0]?.[1]).toMatchObject({ + overlay: true, + overlayOptions: { anchor: "center", width: 80 }, + }); + }); +}); + describe("OverlayFrame", () => { it("pads content to a visible width", () => { expect(padToWidth("hi", 4)).toBe("hi "); From 9e4c7c7fb94c10122142ab868293e0582d49aad2 Mon Sep 17 00:00:00 2001 From: Atlas-Key <296298943+Atlas-Key@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:08:37 -0400 Subject: [PATCH 3/3] fix: hoist pi-tool-pills runtime deps to the git collection root --- AGENTS.md | 1 + README.md | 9 +++++---- knip.json | 5 ++++- package.json | 5 +++++ pnpm-lock.yaml | 10 ++++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fa63844..8327761 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,6 +19,7 @@ Develop independently loadable Pi extensions and supporting packages in one pnpm - Pi loads TypeScript through jiti; extension workspaces normally need no build step. - Keep each extension independently loadable through its own `package.json` `pi` manifest. - The root `pi` manifest is the Git collection at `git:github.com/edheltzel/pi-extensions`. Only resources listed in the root `package.json` belong to that collection; see the root README for installation paths for other workspaces. +- Pi's Git install only installs root `package.json` dependencies. Collection extensions that import runtime npm packages (currently `diff`, `shiki`, `@shikijs/cli` for `pi-tool-pills`) must also list those deps on the collection root. - Atlas-owned workspaces remain private until an explicit npm publishing decision removes that safeguard and adds a release changeset. - Preserve upstream attribution, copyright, and split-license notices in package-level license files. diff --git a/README.md b/README.md index 0a313d4..e335c27 100644 --- a/README.md +++ b/README.md @@ -159,16 +159,17 @@ pi remove -l ./extensions/context-commands To add or remove resources from the Atlas Git collection: 1. Edit the root [`package.json`](./package.json) `pi.extensions` or `pi.skills` arrays. -2. If dependencies or workspace metadata changed, run `pnpm install` so [`pnpm-lock.yaml`](./pnpm-lock.yaml) stays current. -3. Run the relevant checks before sharing the change: +2. If a collection extension imports a runtime npm package, list it on the root `package.json` `dependencies` as well. Pi's Git install only installs that root manifest, not workspace `package.json` files. +3. If dependencies or workspace metadata changed, run `pnpm install` so [`pnpm-lock.yaml`](./pnpm-lock.yaml) stays current. +4. Run the relevant checks before sharing the change: ```sh pnpm run typecheck pnpm run test ``` -4. Commit and push the repository change. -5. Update the installed Git package: +5. Commit and push the repository change. +6. Update the installed Git package: ```sh pi update git:github.com/edheltzel/pi-extensions diff --git a/knip.json b/knip.json index 54d33c8..9f20ba1 100644 --- a/knip.json +++ b/knip.json @@ -74,7 +74,10 @@ "@earendil-works/pi-ai", "@earendil-works/pi-coding-agent", "@earendil-works/pi-tui", - "@sinclair/typebox" + "@sinclair/typebox", + "@shikijs/cli", + "diff", + "shiki" ], "ignoreIssues": { "extensions/preset/src/extension.ts": ["duplicates"] diff --git a/package.json b/package.json index 31bd26d..53f5054 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,11 @@ "typecheck": "tsc --noEmit -p tsconfig.json", "changeset-publish": "changeset publish" }, + "dependencies": { + "@shikijs/cli": "^3.15.0", + "diff": "^8.0.2", + "shiki": "^3.15.0" + }, "devDependencies": { "@changesets/changelog-github": "=0.6.0", "@changesets/cli": "=2.31.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a9e7bd..5e711f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,16 @@ settings: importers: .: + dependencies: + '@shikijs/cli': + specifier: ^3.15.0 + version: 3.23.0 + diff: + specifier: ^8.0.2 + version: 8.0.4 + shiki: + specifier: ^3.15.0 + version: 3.23.0 devDependencies: '@changesets/changelog-github': specifier: '=0.6.0'