How to Create a Custom Spec Command for AI Code Generation
This guide will walk you through setting up a custom command for Claude Code to streamline your development workflow. You’ll learn how to automate the generation of feature specifications and new Git branches, ensuring a more focused and efficient AI-assisted development process.
Overview
In this tutorial, you will learn how to implement a spec-driven development workflow using Claude Code. This process involves creating a high-level, non-technical specification for new features, followed by generating a detailed technical plan, and finally implementing the feature based on that plan. We will start by creating a custom slash command that automates the generation of these initial specifications and sets up a new Git branch for the feature. This approach helps minimize guesswork and incorrect assumptions by the AI, keeping it focused on the task at hand.
Prerequisites
- Basic understanding of Git and version control.
- Claude Code installed and configured.
- A project directory set up for Claude Code.
Steps
Create the `spec.nd` Command File
Navigate to the
.claude/commandsdirectory in your project. If it doesn’t exist, create it. Inside this directory, create a new file namedspec.nd. This file will contain the definition for your new custom command.Add Front Matter to `spec.nd`
Open the
spec.ndfile and add the following front matter. This section provides metadata for the command, including its description, an argument hint for users, and the tools Claude Code is allowed to use for this command.“`yaml
—
description: Create a feature spec file and branch from a short idea
argument_hint: A short feature description
allowed_tools: [read, write, glob, bash]
—
“`Define the Command Logic
Below the front matter, you will define the actual logic for the
/speccommand. This involves instructing Claude Code on how to process user input, generate feature details, create a Git branch, and write a specification file. Paste the following code into yourspec.ndfile:“`python
summary: “Make a new feature spec for the application using the user input below.”
# Respect anything inside the .claude file
input_variables:
arguments:
description: “A short description of the new feature.”
required: true# Outline the steps the model needs to take
steps:
– step: 1
name: “Check for uncommitted changes”
description: “Check the current branch for uncommitted or unstaged changes. If any exist, abort the command and instruct the user to stash or commit them first.”
– step: 2
name: “Extract feature details”
description: “Based on the user’s arguments, extract or come up with the following values:
– feature_title: A human-readable title for the feature.
– feature_slug: A URL-friendly slug for the feature (lowercase, kebab-case, alphanumeric, spaces replaced with dashes).
– git_branch_name: A safe Git branch name in the format ‘claude/feature/{feature_slug}’. Example: claude/feature/add-user-profile.”
– step: 3
name: “Create new Git branch”
description: “Switch to a new Git branch using the generated git_branch_name.”
– step: 4
name: “Create spec file”
description: “Create a new markdown file in the `specs` directory using the feature_slug as the filename (e.g., `specs/{feature_slug}.md`). Use the content of the `specs/template.md` file as a template. Do NOT include any technical implementation details or code examples in this spec file, as that is reserved for the planning step.”
– step: 5
name: “Respond with summary”
description: “Respond with a short summary of the actions taken, including the new branch name, the spec file location, and the feature title.”# Detailed instructions for each step
# Step 1: Check for uncommitted changes
run_script: |
if !git diff –quiet || !git diff –cached –quiet;
then
echo “You have uncommitted or unstaged changes. Please commit or stash them before creating a new feature spec.”
exit 1
fi# Step 2: Extract feature details and Step 3: Create new Git branch
execute_code:
tool_code: |
import refeature_description = arguments[0]
# Generate feature title
feature_title = feature_description.title()# Generate feature slug (kebab-case)
feature_slug = re.sub(r'[^ws-]’, ”, feature_description.lower())
feature_slug = re.sub(r'[s]+’, ‘-‘, feature_slug.strip())
feature_slug = re.sub(r'[-]+’, ‘-‘, feature_slug)# Generate Git branch name
git_branch_name = f”claude/feature/{feature_slug}”# Create and switch to the new branch
print(f”Creating and switching to branch: {git_branch_name}”)
os.system(f”git checkout -b {git_branch_name}”)# Define spec file path
spec_file_path = f”specs/{feature_slug}.md”# Get spec template content
with open(“specs/template.md”, “r”) as f:
spec_template_content = f.read()# Construct the spec content using the template
spec_content = spec_template_content.replace(“{{FEATURE_NAME}}”, feature_title)
spec_content = spec_content.replace(“{{BRANCH_NAME}}”, git_branch_name)
# Note: Figma component and design reference placeholders remain if not dynamically filled# Write the spec file
print(f”Creating spec file: {spec_file_path}”)
with open(spec_file_path, “w”) as f:
f.write(spec_content)# Prepare the final response
response = f”Successfully created feature spec and branch.nBranch: {git_branch_name}nSpec File: {spec_file_path}nFeature Title: {feature_title}”
print(response)# Use Claude’s planning mode to further refine the spec if needed
# This part is conceptual and would involve another tool call or prompt
# For now, we rely on the template and manual refinement.# Respond to the user
return response
“`Expert Note: The provided code snippet uses Python within the
execute_codeblock. Claude Code interprets this to run the Python script. The script handles generating slugs, branch names, creating the branch, and writing the spec file based on a template. The use ofos.systemis a direct way to execute shell commands likegit checkout -b.Create the `specs` Directory and `template.md` File
In the root directory of your project, create a new folder named
_specs. The underscore prefix helps keep this folder at the top of your file explorer. Inside the_specsfolder, create a new file namedtemplate.md.Populate `template.md`
Open
template.mdand paste the following content. This file serves as a template for all new feature specifications generated by your custom command. The placeholders like{{FEATURE_NAME}}and{{BRANCH_NAME}}will be automatically filled by the command.“`markdown
# {{FEATURE_NAME}}**Branch:** {{BRANCH_NAME}}
**Figma Component (if used):**
**Summary:**
**Functional Requirements:**
**Figma Design Reference (if referenced):**
**Edge Cases:**
**Acceptance Criteria:**
**Open Questions:**
**Testing Guidelines:**
– Create a test file in the `tests` folder for any new feature.
– Create meaningful tests for the following cases without going too heavy.
“`Tip: The placeholders for ‘Figma Component’ and ‘Figma Design Reference’ are included for future integration. For now, they can be ignored if you are not using Figma.
Test the Custom Command
Now you can test your new command. Open your terminal in the project directory and run:
/spec Create a user profile pageClaude Code should:
- Check for uncommitted changes.
- Create a new Git branch named something like
claude/feature/create-a-user-profile. - Create a file named
_specs/create-a-user-profile.mdusing the content fromtemplate.md, with the feature name and branch name filled in. - Provide a summary of the actions taken.
Warning: Ensure you have no uncommitted changes in your current Git branch before running the command, as it will abort if it detects any.
Conclusion
You have successfully created a custom /spec command for Claude Code. This command automates the initial steps of your spec-driven workflow by generating feature names, creating new Git branches, and producing a basic feature specification file based on a template. This lays the groundwork for more detailed planning and implementation in subsequent steps.
Source: Spec Driven Workflow with Claude Code #1 – Making a /spec Command (YouTube)