# ask > Prompts the interactive user for one or more option-picker or free-form answers. ## Source - Entry: `packages/coding-agent/src/tools/ask.ts` - Model-facing prompt: `packages/coding-agent/src/prompts/tools/ask.md` - Key collaborators: - `packages/coding-agent/src/config/settings-schema.ts` — `ask.timeout` / `ask.notify` defaults - `packages/coding-agent/src/modes/theme/theme.ts` — checkbox and radio glyphs for TUI rendering - `packages/coding-agent/src/tui/index.ts` — status-line rendering ## Inputs | Field | Type | Required | Description | | --- | --- | --- | --- | | `questions` | `Question[]` | Yes | One or more questions. Empty arrays are rejected by schema and also guarded at runtime. | ### `Question` | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | `string` | Yes | Stable identifier used in multi-question results. | | `question` | `string` | Yes | Prompt text shown to the user. | | `options` | `{ label: string; description?: string }[]` | Yes | Option labels for the picker, each with optional explanatory `description` text shown below the label. The schema does not require a minimum length; the UI always appends `Other (type your own)`, and callers must not include it. | | `multi` | `boolean` | No | Enables multi-select mode. Default: `false`. | | `recommended` | `number` | No | Zero-based recommended option index. In single-select mode the label gets ` (Recommended)` appended in the UI. | ## Outputs - Single-shot result. - `content[0].text` is plain text: - single question: `User selected: ...` and/or `User provided custom input: ...` - multiple questions: `User answers:` followed by one line per `id` - `details`: - single question: `{ question, options, multi, selectedOptions, customInput?, timedOut? }` - multiple questions: `{ results: QuestionResult[] }`, where each item includes `id`, `question`, `options`, `multi`, `selectedOptions`, and optional `customInput` and `timedOut` - Cancellation and headless cases throw instead of returning a structured success result. ## Flow 1. `AskTool.createIf()` only registers the tool when `session.hasUI` is true; headless sessions never get it. 2. `execute()` requires `context.ui`; if missing it aborts the context and throws `ToolAbortError("Ask tool requires interactive mode")`. 3. It reads `ask.timeout` from settings, converts seconds to milliseconds (`0` disables timeout), and disables timeout entirely while plan mode is enabled (`packages/coding-agent/src/tools/ask.ts`). 4. If `ask.notify` is not `off`, it sends a terminal notification: `Waiting for input`. 5. For each question, `askSingleQuestion()` drives either: - single-select list + optional editor for `Other` - multi-select checkbox loop + `Done selecting` sentinel + optional editor for `Other` 6. In multi-question mode, left/right arrow handlers enable back/forward navigation between questions and preserve prior selections. 7. If a timeout fires before any selection/custom input, the tool auto-selects the recommended option, or the first option when no valid `recommended` index exists; the result text gets an ` (auto-selected after timeout)` suffix and `details.timedOut` is set. 8. If the user cancels without timeout, `execute()` aborts the tool context and throws `ToolAbortError("Ask tool was cancelled by the user")`. 9. On success it formats human-readable text plus structured `details`; the TUI renderer uses `details` for rich display. ## Modes / Variants - Single question: returns flattened `details` fields for one question. - Multiple questions: returns `details.results[]` and allows back/forward navigation across questions. - Single-select: one option or custom input. - Multi-select: toggled checkbox list, `Done selecting` sentinel only when forward navigation is not active. ## Side Effects - User-visible prompts / interactive UI - Opens a selection dialog via `context.ui.select(...)`. - Opens a text editor dialog via `context.ui.editor(...)` for `Other`. - Sends a terminal notification unless `ask.notify=off`. - Session state - Reads plan-mode state to disable timeouts. - Calls `context.abort()` on headless use or user cancellation. - Background work / cancellation - Wraps UI waits in `untilAborted(...)` so abort signals interrupt pending dialogs. ## Limits & Caps - `questions` must contain at least 1 item (`askSchema` in `packages/coding-agent/src/tools/ask.ts`). - `ask.timeout` default is `0` seconds, which disables timeout (`packages/coding-agent/src/config/settings-schema.ts`). Configured non-zero values are seconds. - Prompt guidance says provide 2-5 options, but code only requires the `options` array field and does not enforce a minimum or maximum length (`packages/coding-agent/src/prompts/tools/ask.md`). - Timeout only applies to the option picker; once the user chooses `Other`, the editor has no timeout (`promptForCustomInput()` in `packages/coding-agent/src/tools/ask.ts`). - `AskTool.concurrency = "exclusive"`: the tool runs alone in its tool batch because the selector/editor UI surface is shared and concurrent `ask` calls would clobber each other. ## Errors - Missing interactive UI: throws `ToolAbortError("Ask tool requires interactive mode")`. - User cancels picker/editor without timeout: throws `ToolAbortError("Ask tool was cancelled by the user")`. - Abort signal during input: converted to `ToolAbortError("Ask input was cancelled")`. - Empty `questions` at runtime returns a text error payload instead of throwing: `Error: questions must not be empty`. ## Notes - `recommended` is only a UI hint; invalid indexes are ignored. - In single-select mode the returned `selectedOptions` value strips the appended ` (Recommended)` suffix. - Multi-select results preserve selection order by `Set` insertion order, not original option order after arbitrary toggles. - Option labels and prompt text are returned verbatim in `details`; the tool does not interpret them beyond UI affordances like `Other` and ` (Recommended)`.