Claude Code Plugins

Community-maintained marketplace

Feedback

Questionnaire CLI workflow and context

@duggthangs/questionnaire_cli
0
0

Understand how questions are loaded, validated, presented in Ink, and written back out as markdown.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name Questionnaire CLI workflow and context
description Understand how questions are loaded, validated, presented in Ink, and written back out as markdown.
metadata [object Object]

Context

The questions CLI expects a JSON array of question definitions and uses Ink to walk a human operator through them. Users typically pipe JSON or point the CLI at a file (questions sample_questions.json). The entrypoint normalizes argv, reads the question set, validates each prompt, and boots the Ink app. Inside the TUI, the operator navigates with [/h and ]/l, arrow keys or j/k, and Enter/Space depending on the question type. Yes/no prompts always include a third "Other" row that opens a custom input so operators can supply free-form context without toggling configuration. Answers are cached locally until the final submit screen, where the UI is replaced with the generated markdown; the CLI simultaneously writes the same payload to --output when set (and only logs directly to stdout when running non-interactively). The finalOutput state doubles as the "submitted" flag—once it holds a string, prior screens unmount and the only available action is confirming exit.

Relevant Files

  • src/cli.tsx – parses CLI flags, loads question JSON from stdin/file, validates structure, and renders the Ink app.
  • src/components/App.tsx – orchestrates per-question state, keyboard handling, navigation, and submission lifecycle.
  • src/components/{SingleSelect,MultiSelect,FreeForm,YesNo}.tsx – renderers for each supported question type, including custom-option UX.
  • src/components/Header.tsx – displays global navigation affordances and current progress counter.
  • src/components/SubmitScreen.tsx – review + submit view that surfaces every answer and triggers finalizing logic on Enter.
  • src/utils/markdown.ts – turns (questions, answers) into the markdown payload written to stdout/file.
  • sample_questions.json – reference dataset demonstrating the JSON schema accepted by the CLI.

Relevant Types

  • Question union (src/types.ts) – guarantees each prompt carries id, question, and type-specific metadata (options, suggestions).
  • Answer (src/types.ts) – union used across the UI to store the current value for each question id.
  • parseQuestions(input) (src/cli.tsx) – runtime guard that enforces the schema before Ink ever mounts.
  • generateMarkdown(questions, answers) (src/utils/markdown.ts) – shared formatter used by the submit handler to keep stdout and file output in sync.

Workflow

  1. Input resolutionsrc/cli.tsx inspects process.argv, supports -f/--file and positional file args, falls back to piped stdin, or exits with help if no payload exists.
  2. Question validation – raw input is parsed as JSON; every entry must have id, question, and a supported type, plus options/suggested arrays where required. Failures exit early so the Ink UI never loads bad data.
  3. App initializationrender(<App ... />) seeds per-question UI state (selection indexes, custom strings, multi-select sets) and tracks currentStep to know which component to show.
  4. Interactive answeringuseInput inside App centralizes keyboard handling ([/h and ]/l to move steps, arrows or j/k to change the highlighted option, Space for multi-select toggles, Enter/Space to confirm). Components receive state slices to display cursors, custom text fields, and selection markers.
  5. Saving answerssaveAnswer() maps current UI state into the canonical Answer union per question id; multi-select answers are arrays, custom entries persist when Enter/Space is pressed, yes/no returns booleans for Yes/No or a custom string when "Other" is confirmed, and skipped questions remain null.
  6. Submission and output – when the operator advances past the last question, SubmitScreen shows a summary. Pressing Enter/Space once generates the markdown via generateMarkdown, stores it in finalOutput, and swaps the UI to a read-only Markdown view; finalOutput !== null now indicates the session is locked and no prior step can be revisited. Any subsequent Enter/Space (or key press) triggers the final onSubmit/exit path, which writes to --output (or stdout) and terminates the Ink app.

Edge Cases

  • No input / unreadable file – CLI errors with guidance if stdin/file is empty or cannot be read.
  • Schema violations – missing ids, unsupported types, or absent options arrays throw descriptive errors before entering the interactive flow.
  • Custom option handling – multi-select custom entries are only stored once the user confirms the typed text; hitting Escape clears the draft.
  • Empty selections – multi-select answers serialize as _none selected_/(none selected) in markdown so downstream readers know it was intentional.
  • Output failures – disk write errors propagate from Bun.write; the CLI surfaces them after printing to stdout so callers can retry another path.

Questions to Clarify

  • Should the CLI ship with additional built-in templates beyond sample_questions.json, or fetch remote question sets?
  • Do we need persistence/resume capabilities so partially answered sessions can be reloaded?
  • How should automated pipelines (non-interactive environments) provide answers—should we allow defaults or scripted input?
  • Is markdown the only required output, or should alternate formats (JSON/HTML) be supported behind additional flags?