@wwyxin/pi-ask
Multi-select capable `ask` tool for the Pi coding agent: tappable option lists in pi-web (works on a phone) and keyboard dialogs in the TUI.
Package details
Install @wwyxin/pi-ask from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@wwyxin/pi-ask- Package
@wwyxin/pi-ask- Version
0.1.4- Published
- Sep 23, 2026
- Downloads
- 492/mo · 492/wk
- Author
- wwyxin
- License
- MIT
- Types
- extension
- Size
- 34.1 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-ask
A multi-select capable ask tool for the Pi coding agent — tappable option lists in
pi-web (usable on a phone) and normal keyboard dialogs in the terminal TUI.
Why this package exists
Pi ships no interactive question tool of its own, and the obvious approaches do not work on a phone:
- The RPC / pi-web dialog protocol has no multi-select field.
ctx.ui.select()is rendered by pi-web as a list of native, tappable option buttons, but it returns a single string (options: string[]). ctx.ui.custom()panels are keyboard-only. Pi forwards a TUI component to pi-web as an ANSI text panel plus a hidden textarea that only receives raw keystrokes. A phone soft keyboard cannot sendArrowUp,SpaceorTab, so checkbox UIs built that way are unusable on mobile.
pi-ask therefore emulates multi-select by looping ctx.ui.select(): every pass is a fresh tappable
list, tapping an option toggles it, and tapping ✅ 完成选择 finishes the question. No keyboard required.
Install
pi install npm:@wwyxin/pi-ask
The extension auto-loads in every session (pi, pi-web, RPC). Restart pi-web or run /reload in an existing
session to pick it up.
Usage
The model calls the tool; you answer by tapping.
{
"questions": [
{
"id": "scope",
"prompt": "Which parts should I process?",
"multiSelect": true,
"options": [
{ "value": "api", "label": "API layer" },
{ "value": "db", "label": "Database migrations" },
{ "value": "docs", "label": "Documentation" }
]
},
{
"id": "mode",
"prompt": "How should I proceed?",
"allowOther": false, // opt out of the free-text row; it is on by default
"options": [
{ "value": "plan", "label": "Show me a plan first" },
{ "value": "do", "label": "Just do it" }
]
}
]
}
| Field | Type | Notes |
|---|---|---|
questions |
array | One or more questions, asked in order in a single tool call |
questions[].id |
string | Stable id used in the answer summary |
questions[].prompt |
string | Question text (shown as the dialog title) |
questions[].options |
array | { value, label, description? }; value is what the model gets back |
questions[].multiSelect |
boolean | true = checkbox question, several options may be picked |
questions[].allowOther |
boolean | Free-text row (✎ 输入其他 / 补充说明) so the user can always add a note. Defaults to true; set false only when free text would be meaningless |
What the user sees
Multi-select question (multiSelect: true) — in pi-web every row is a tappable button, and the three kinds
of row look different on purpose:
Which parts should I process? [已选:API layer、Documentation、放最后再做]
☑ API layer ← option: real checkbox (GFM task list)
☐ Database migrations
☑ (其他) 放最后再做 ← typed note: also a checkbox row; tap again to remove
✎ 输入其他 / 补充说明 ← free text: monospace chip, kept above the actions
✅ 完成选择(已选 3 项) ← commit: bold
🗑 清空选择 ← destructive: struck through
✕ 取消 ← escape: italic
pi-web renders option text as GFM Markdown (remark-gfm + rehype-sanitize), and the RPC protocol carries
no style information — the option string is the only lever, because pi-web draws the same button chrome
around every row. So in RPC mode each kind of row gets its own markdown treatment (checkbox / inline code /
bold / strikethrough / italic), which keeps the options, the free-text entry and each of the three action rows
visually distinct. The terminal TUI does not render Markdown and keeps the plain glyph form (☐/☑, plain
labels).
Known limitation: the bordered button around every row comes from pi-web itself (
ExtensionDialogincomponents/ChatWindow.tsx); the RPC protocol has no per-row style field andrehype-sanitizestripsstyle/class, so an extension cannot remove that frame. Typography above is the strongest differentiation available without patching pi-web.
- Every row is a button: tap to toggle
☐/☑. - The title echoes the running selection, so the list can be long without losing track.
✅ 完成选择ends the question (zero selections is a valid answer).🗑 清空选择appears only when something is selected, and drops typed notes as well as ticks.✕ 取消reports a cancellation to the model.
Every question offers a free-text row by default (allowOther defaults to true), so the user is never boxed
into the offered options. Typed text shows up as a removable checked row — tap it again to delete it, or tap
✎ 输入其他 / 补充说明 to add another note (duplicates are ignored).
Single-select questions (multiSelect omitted) are a plain list where one tap finishes immediately.
The tool result the model receives is a compact, machine-readable summary:
User answered:
- scope [多选]: API layer、Documentation
- mode: Just do it
Compatibility
- Works in the terminal TUI and in pi-web / RPC mode (pi-web renders the same dialogs natively).
- Verified against
@earendil-works/pi-coding-agent0.87.x and@agegr/pi-web0.9.x. - No runtime dependencies:
@earendil-works/pi-*are resolved and aliased by the pi extension loader.
Development
npm install # dev dependency: @earendil-works/pi-coding-agent (for the extension loader)
npm test # loads index.ts through the real loader and drives it with a fake UI
npm test covers option toggling, the confirm/clear/cancel rows, single-select, the free-text row
(including allowOther: false and removing a typed note), several questions per call and the no-UI failure
path. It makes no model calls and no network requests.
License
MIT
中文速览
给 Pi coding agent 加的 ask 工具,重点是手机上能用真·多选复选框。
- 安装:
pi install npm:@wwyxin/pi-ask,然后重启 pi-web 或在会话里/reload。 - 多选题目里,每个选项都是可点按的按钮,点一下切换勾选;标题实时显示「已选:…」,点「✅ 完成选择」结束。
- 每类行长得不一样(pi-web 把选项文本按 GFM Markdown 渲染,而 RPC 协议没有样式通道,只能靠文本本身):
选项行 = 真复选框(GFM 任务列表);
✎ 输入其他 / 补充说明= 等宽码片,且放在操作行上面; ✅ 完成选择 = 加粗;🗑 清空选择 =删除线(破坏性操作);✕ 取消 = 斜体。 终端 TUI 不渲染 Markdown,保持☐/☑原样。 - 每行外面那圈带边框的卡片是 pi-web 自己画的(
ExtensionDialog给每行都套同一个按钮壳),RPC 协议没有 逐行样式字段、rehype-sanitize又会去掉style/class,所以扩展改不掉那圈框——上面这套排版是“不改 pi-web 的前提下能做到的最强区分”。 - 每题默认都有一行「✎ 输入其他 / 补充说明」,选项都不合适或想补几句话就点它;输入过的文字会变成
一行可点掉的
☑ (其他) …,再点一次就删掉。「🗑 清空选择」会连输入的补充一起清掉。 - 单选题目点一下即结束。
- 为什么不用 TUI 自绘组件:那些组件在 pi-web 里只会变成一块收原始按键的文本面板,手机软键盘按不出
↑↓/空格/Tab,等于不可用。本包改成循环调用
ctx.ui.select(),所以纯点按即可。