@juancrg90/ask-user-question

Interactive AskUserQuestion tool for Pi — pause and ask the user structured questions in the TUI with stable ID-based results.

Packages

Package details

extension

Install @juancrg90/ask-user-question from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@juancrg90/ask-user-question
Package
@juancrg90/ask-user-question
Version
1.1.1
Published
Nov 2, 2026
Downloads
319/mo · 239/wk
Author
juancrg90
License
MIT
Types
extension
Size
72.2 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

AskUserQuestion

Interactive Pi tool. Pause agent flow. Ask structured questions in TUI. Return stable ID-keyed answers.

Install

pi install npm:@juancrg90/ask-user-question

Tool

AskUserQuestion

Use when:

  • user preference changes outcome
  • multiple valid paths
  • ambiguity not inferable from repo/context
  • batching related choices better than serial follow-ups

Do not use when:

  • asking permission for risky actions
  • plan approval already covered elsewhere
  • answer inferable with high confidence

Input

interface AskUserQuestionParams {
  questions: Question[];
  metadata?: {
    source?: string;
    flowId?: string;
    tags?: string[];
  };
}

interface Question {
  id: string;
  question: string;   // must end with ?
  header: string;     // max 12 chars
  multiSelect?: boolean;
  required?: boolean; // default true
  options: Option[];  // 2–4 options
}

interface Option {
  id: string;
  label: string;
  description: string;
  preview?: string;   // single-select only
  recommended?: boolean;
}

Rules:

  • 1–8 questions
  • 2–4 options per question
  • unique, non-blank question.id
  • unique, non-blank option.id within each question
  • IDs beginning with $ and the internal __other__ ID are reserved
  • question text must end with ?
  • header must be non-blank and no longer than 12 characters
  • labels and descriptions must be non-blank; labels must be unique per question
  • explicit Other / Other... options are forbidden; the tool auto-adds one
  • preview is allowed only on single-select questions
  • at most one option per question may set recommended: true

Output

interface AskUserQuestionResult {
  cancelled: boolean;
  answers?: Record<string, AnswerValue>;      // keyed by question.id
  annotations?: Record<string, QuestionAnnotations>;
  metadata?: { source?: string; flowId?: string };
}

type AnswerValue =
  | {
      kind: "single";
      optionId?: string;
      label: string;
      other?: boolean;
      text?: string;
    }
  | {
      kind: "multi";
      selections: Array<{
        optionId?: string;
        label: string;
        other?: boolean;
        text?: string;
      }>;
      empty: boolean;
    };

interface QuestionAnnotations {
  questionNotes?: string;
  optionNotes?: Record<string, string>; // option.id or "$other"
  selectedPreview?: string;
}

The complete structured result is included in model-visible tool content as well as tool details. Follow-up responses can therefore use answers, notes, preview context, and preserved metadata without reading TUI-only state.

Runtime behavior

  • one-question flow submits immediately after answer
  • multi-question flow enters review once all required questions are answered
  • optional questions may remain unanswered
  • multi-select Space immediately updates answered state; empty selection needs two Enter presses
  • dismiss path returns cancelled: true and terminate: true
  • working indicator hidden while a question is pending; always restored on completion
  • Ctrl+Shift+Q temporarily hides/restores the modal without answering or dismissing
  • while hidden, Pi receives normal input so you can scroll and read the conversation; a footer reminder shows how to resume, and the agent continues waiting
  • selections, notes, text drafts, cursor position, and review state survive hiding
  • supports external abort via _signal
  • emits low-noise _onUpdate milestones:
    • dialog_opened
    • question_answered
    • review_ready
    • submitted
    • dismissed

Keybindings

In every modal view (including help, review, and text input):

  • Ctrl+Shift+Q — hide modal to read the conversation; press again to resume
  • requires a terminal that reports modified keys (e.g. Kitty keyboard protocol); terminals or OS shortcuts that intercept this key combination cannot toggle it
  • while hidden, ordinary Pi bindings apply, including any interrupt/abort bindings

Normal:

  • ↑/↓ or j/k — move focus
  • Tab / Shift+Tab — switch questions
  • ←/→ — switch questions; move picker during review
  • Space — toggle focused option in multi-select
  • Enter — confirm / submit current action
  • o — open Other... input
  • n — edit note for focused option
  • N — edit note for the current question
  • ? — open help
  • Esc, Esc — dismiss to chat
  • Ctrl-C — dismiss immediately

Help:

  • any key closes help

Other... / note input:

  • uses Pi TUI's native single-line Input control
  • type or paste plain text; Unicode and terminal paste are supported
  • ←/→, Home, and End move the cursor
  • Enter saves
  • Esc cancels without overwriting the saved value
  • configured Pi editor bindings handle deletion, word movement, and undo

TUI

The dialog uses Pi's native Container, Text, Box, Input, and DynamicBorder controls. It follows the active Pi theme for headings, focus, selections, warnings, descriptions, controls, and borders.

Moshi Chat View

Moshi submits option answers through the live terminal dialog. Its Pi bridge (validated with moshi-hook 0.4.45) requires the visible English markers navigate, select, and enter before sending keys. The normal and preview layouts preserve these markers in their keyboard hints; do not remove or translate them without rechecking compatibility. The dialog spans the terminal width so conversation text beside wrapped lines cannot interrupt the question in Moshi's pane capture.

Preview

  • single-select only
  • plain text only
  • wide terminals: side-by-side option list + preview
  • narrow terminals: preview stacked below list
  • if focused option has no preview, explicit (no preview) shown

Example input

AskUserQuestion({
  questions: [
    {
      id: "framework",
      question: "Which frontend framework do you prefer?",
      header: "Framework",
      options: [
        {
          id: "react",
          label: "React",
          description: "Component-based UI library",
          preview: "Best if you want broad ecosystem support.",
        },
        {
          id: "vue",
          label: "Vue",
          description: "Progressive framework",
          preview: "Good default if you want gentle adoption.",
        },
      ],
    },
  ],
});

Example result

{
  "cancelled": false,
  "answers": {
    "framework": {
      "kind": "single",
      "optionId": "react",
      "label": "React"
    }
  },
  "annotations": {
    "framework": {
      "selectedPreview": "Best if you want broad ecosystem support."
    }
  }
}

Security

Do not pass secrets in question text, descriptions, previews, or notes.

License

MIT