Post

Building a Claude Code Skill That Lets You Pick from a Menu

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:

  1. Show me a list of options
  2. Let me choose one
  3. 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:

  1. Read external files — the skill references a JSON config that lives outside the skill definition
  2. Use interactive toolsAskUserQuestion renders real clickable options in the terminal UI
  3. Branch on arguments — the $ARGUMENTS variable 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
  • AskUserQuestion is 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
  • $ARGUMENTS gives you a fast path to skip the menu when you know what you want
  • The 4-option limit on AskUserQuestion is the main constraint to design around

Resources

This post is licensed under CC BY 4.0 by the author.