@rwese/pi-question

Unified question tool for pi coding agent - single or multi-question interactions with optional notes and custom input support

Package details

extension

Install @rwese/pi-question from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@rwese/pi-question
Package
@rwese/pi-question
Version
2.2.0
Published
Apr 27, 2026
Downloads
1,851/mo · 243/wk
Author
rwese
License
MIT
Types
extension
Size
46.6 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@rwese/pi-question

npm version License: MIT

Unified question tool for the pi coding agent with single/multi-question support, optional notes, per-option comments, and custom input.

Features

  • Single-select questions: Radio-style selection with keyboard navigation
  • Multi-select questions: Checkbox-style selection for multiple answers
  • Required selection: Multi-select requires at least one option before advancing
  • Per-item notes: Press (n) on any selected item to add a note (multi-select only)
  • Recommended options: Pre-select and highlight recommended choices
  • Custom input: "Other" option with inline text editor for free-form input
  • Multi-question support: Tab bar interface for sequential questioning
  • Answer review: Summary screen before final submission
  • Markdown output: Clean markdown formatting for AI consumption
  • Auto-disable: Tool is not registered in non-interactive mode (--print/-p)

Installation

# From npm (recommended)
pi install npm:@rwese/pi-question

# From GitHub
pi install git:github.com/rwese/pi-question

After install, enable via pi config → User → Extensions.

Screenshots

See demo.md for full interactive demo walkthrough.

Initial Single Select Note Entry
Pi starting up Single select Tab to add note
Multi Select Multi Selected Summary
Multi select Multiple options Review before submit

Usage

Tool Call

await pi.callTool("question", {
  questions: [
    {
      questionTopic: "Scope",
      prompt: "What type of change is this?",
      type: "single",
      options: [
        { value: "feat", label: "Feature" },
        { value: "fix", label: "Bug fix" },
        { value: "docs", label: "Documentation" }
      ]
    },
    {
      questionTopic: "Priority",
      prompt: "How urgent is this?",
      type: "multi",
      options: [
        { value: "high", label: "High", recommended: true },
        { value: "medium", label: "Medium" },
        { value: "low", label: "Low" }
      ]
    }
  ]
});

What Gets Injected Into the Agent

After the user answers all questions, the tool returns markdown output that is injected into the agent's context.

Resulting Markdown Output

The markdown is rendered inline in the agent's context, showing headers for each question and the selected answers.

Single-Select Output

When a single-select question is answered, the output includes the question prompt followed by the selected option:

## User answered our questions

### What type of change is this?

- **Bug fix** - Fix a bug in existing code

Note: When an option includes a description, it is bolded and displayed alongside the label. User notes (added via Tab) are shown with a Note: prefix.

Multi-Select Output

Multi-select questions use checkbox notation ([x]) to show selected items. Notes added via (n) key are shown as nested bullets:

### How urgent is this?

- [x] **High** - Needs immediate attention
- [x] Medium
  Note: Can be addressed in next sprint

Full Questionnaire Output

When multiple questions are asked, all answers are included in order:

## User answered our questions

### What type of change is this?

- **Bug fix** - Fix a bug in existing code

### How urgent is this?

- [x] **High** - Needs immediate attention
- [x] Medium

Return Data Structure

The tool also returns structured data in details for programmatic access:

QuestionnaireResult

interface QuestionnaireResult {
  questions: Question[];
  answers: Answer[];
  cancelled: boolean;
}

type Answer = SingleAnswer | MultiAnswer;

interface SingleAnswer {
  value: string;       // The option value (e.g., "go", "(other)")
  label: string;       // Display label (e.g., "Go", "Custom text")
  description?: string; // Option description (if provided)
  wasCustom: boolean;  // True if user entered custom text via "Other"
  index?: number;      // 1-based position in sorted options
  message?: string;    // Optional note added via Tab
}

interface MultiAnswerItem {
  value: string;       // The option value
  label: string;       // Display label
  description?: string; // Option description (if provided)
  wasCustom: boolean;  // True if custom text entered
  note?: string;       // User-provided note (added via (n) key)
}

interface MultiAnswer {
  items: MultiAnswerItem[]; // Array of selected items with notes
}

Example Return Value

{
  content: [
    {
      type: "text",
      text: "## User answered our questions\n\n### What type of change is this?\n\n- **Bug fix** - Fix a bug in existing code\n\n### How urgent is this?\n\n- [x] **High** - Needs immediate attention\n- [x] Medium\n"
    }
  ],
  details: {
    questions: [
      { questionTopic: "Scope", prompt: "What type of change is this?", type: "single", options: [...] },
      { questionTopic: "Priority", prompt: "How urgent is this?", type: "multi", options: [...] }
    ],
    answers: [
      { value: "fix", label: "Bug fix", description: "Fix a bug in existing code", wasCustom: false, index: 2 },
      { items: [
        { value: "high", label: "High", description: "Needs immediate attention", wasCustom: false },
        { value: "medium", label: "Medium", wasCustom: false }
      ] }
    ],
    cancelled: false
  }
}

UI States

Tab Bar (Multi-Question)

When multiple questions are asked, a tab bar appears at the top:

▸ Language      ■ Tools      □ OS       □ Workflow     ✓ Submit →
  • / : Navigation arrows
  • / : Unanswered / Answered status
  • : Submit tab (enabled when all questions answered)

Single-Select (Radio)

  1. ● Go        Fast, compiled, concurrent
  2.   ○ Rust    Safe, fast, zero-cost abstractions
  3.   ○ TypeScript    JavaScript with types    (Recommended)
  4.   ○ Python  Simple and readable
  5.   ○ Other ✎

Multi-Select (Checkbox)

  1. > ☑ VS Code     (Recommended)
  2.   ☐ Vim/Neovim
  3.   ☐ JetBrains IDEs
  4.   ☐ Zed
  5.   ☐ Other ✎

Note Entry (Tab Key)

 What is your preferred language?

 Selected: Go

 Add note (optional):
  Fast compilation time

 Enter/Tab save • Esc discard

Submit Review

 Ready to submit

  Scope: Bug fix
  Priority: High, Medium

 Press Enter to submit

Cancellation

If the user presses Esc, the questionnaire is cancelled:

{
  content: [{ type: "text", text: "User cancelled the question" }],
  details: { questions: [...], answers: [], cancelled: true }
}

A questionnaire-cancelled message is also sent to the agent.

Keyboard Navigation

Key Action
/ Navigate options
/ Navigate questions (multi)
Enter Select option + advance
Space Toggle option selection (multi)
(n) Add note to selected option (multi)
Escape Cancel entire questionnaire

Schema

// Question option
{
  value: string,           // Returned when selected
  label: string,            // Display label
  description?: string,    // Optional description below label (supports multi-line)
  recommended?: boolean    // Pre-select and highlight
}

// Question
{
  questionTopic: string,    // Tab bar label
  prompt: string,           // Question text (supports multi-line)
  type?: "single" | "multi", // Default: "single"
  options: QuestionOption[]
}

// Questionnaire
{
  questions: Question[]
}

Multi-line Text Support

Question prompts and option descriptions support multi-line text:

  • Long prompts: Automatically word-wrap to fit the terminal width
  • Long descriptions: Wrap across multiple lines with proper indentation
  • Max lines: Content is capped at 7 lines to prevent excessive scrolling
  • ANSI support: Styling is preserved across wrapped lines

Example with multi-line content:

  1. ● Feature      This is a comprehensive description that
     wraps across multiple lines to fit within the
     terminal width while maintaining readability
  2.   ○ Bug fix    A shorter description

Special Values

Value Meaning
(other) User selected "Other" and entered custom text
(no selection) Note: Multi-select with no options selected is now prevented by the UI. Users must select at least one option to proceed.

Development

# Install dependencies
npm install

# Type check
npm run typecheck

# Lint
npm run lint

# Format
npm run format

# Test
npm test

# Coverage
npm run coverage

# Validate (all checks)
npm run validate

License

MIT