Building a Claude Code Skill That Lets You Pick from a Menu
Claude Code skills (slash commands) are great for automating repetitive tasks, but out of the box they’re fire-and-forget — you type /my-skill, it runs. What if you want a skill that presents a list of options first, then executes your selection? Skills don’t have built-in UI components, but with a simple two-file setup you can build a /pick command that shows a menu every time you invoke it.
The Problem
I have a handful of commands I run constantly during development — start the dev server, run tests, update the ElevenLabs agent config, check the deployment health endpoint. Typing them out (or scrolling through shell history) gets old fast.
I wanted a single /pick command that would:
- Show me a list of options
- Let me choose one
- Execute it
The catch: Claude Code skills are just markdown instruction files. There’s no native menu widget, no fzf integration (Claude’s Bash tool doesn’t support interactive stdin), no built-in picker component.
The Solution: AskUserQuestion + JSON Config
Claude Code skills can instruct Claude to use any of its available tools, including AskUserQuestion — which renders a set of clickable options in the terminal. Combine that with an external JSON config file, and you get a fully customizable option picker.
Here’s the complete setup:
1. Create the Skill File
Create .claude/commands/pick.md in your project:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
description: Pick from a list of options and execute the selection
---
Read the options file at `.claude/pick-options.json`.
Present the options to the user as a numbered list using the
`AskUserQuestion` tool, with each option's `label` as the
choice text and `command` as the description.
When the user picks an option, execute its `command` using Bash.
If `$ARGUMENTS` is provided and matches an option label
(case-insensitive), skip the prompt and execute that option directly.
That’s it for the skill itself. It’s just instructions — Claude reads the JSON, presents the choices, and runs whatever you pick.
2. Create the Options Config
Create .claude/pick-options.json in your project root:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"description": "Customizable options for the /pick skill.",
"options": [
{
"label": "Start dev server",
"command": "uvicorn app.main:app --reload --port 8000"
},
{
"label": "Run tests",
"command": "pytest"
},
{
"label": "Update agent config",
"command": "python scripts/setup_agent.py"
},
{
"label": "Check deployment status",
"command": "curl -s https://my-app.onrender.com/health"
}
]
}
Edit this file anytime to add, remove, or change options. No need to touch the skill definition.
3. Use It
Type /pick in Claude Code. Claude reads the JSON, shows you the options as clickable choices, and runs the one you select:
1
2
3
4
5
6
7
8
> /pick
Which option would you like to run?
● Start dev server — uvicorn app.main:app --reload --port 8000
○ Run tests — pytest
○ Update agent config — python scripts/setup_agent.py
○ Check deployment status — curl -s https://my-app.onrender.com/health
You can also skip the menu entirely by passing an argument:
1
> /pick run tests
Claude matches the argument to the label and runs it directly.
Why This Works
The key insight is that Claude Code skills aren’t limited to static instructions. They can tell Claude to:
- Read external files — the skill references a JSON config that lives outside the skill definition
- Use interactive tools —
AskUserQuestionrenders real clickable options in the terminal UI - Branch on arguments — the
$ARGUMENTSvariable lets you bypass the menu for quick execution
This pattern separates the behavior (the skill markdown) from the data (the JSON config), so you can customize your options per-project without writing a new skill each time.
Limitations to Know About
Max 4 options per question. The AskUserQuestion tool caps at 4 choices per prompt. If you have more than 4 options, you’ll need to either split them across multiple questions, or have Claude present them as a numbered text list and ask you to type a number.
No interactive terminal tools. Claude Code’s Bash tool doesn’t support stdin, so fzf, bash select, or gum choose won’t work. The AskUserQuestion approach is the best alternative — it’s native to Claude Code and renders nicely in the terminal.
Commands run in Bash. Whatever you put in the command field runs through Claude’s Bash tool, which means it follows the same permission model. Commands that need approval will still prompt you.
Extending the Pattern
Once you have the basic picker working, you can extend it:
Add categories. Group options by type and have Claude show a two-step picker — first pick a category, then pick the command:
1
2
3
4
5
6
7
{
"options": [
{ "label": "Start dev server", "category": "dev", "command": "..." },
{ "label": "Run unit tests", "category": "test", "command": "..." },
{ "label": "Deploy to staging", "category": "deploy", "command": "..." }
]
}
Add confirmation. For dangerous commands, add a "confirm": true field and instruct the skill to ask “Are you sure?” before executing.
Make it project-agnostic. Move the skill to ~/.claude/commands/pick.md (user-level) so it’s available in every project. Each project can have its own .claude/pick-options.json with project-specific commands.
Key Takeaways
- Claude Code skills are markdown instructions, not code — but they can orchestrate any of Claude’s tools
AskUserQuestionis your best option for presenting interactive choices within a skill- Separating skill logic from a JSON config file keeps things flexible and easy to edit
$ARGUMENTSgives you a fast path to skip the menu when you know what you want- The 4-option limit on
AskUserQuestionis the main constraint to design around