"pre"-claude is a TUI tool for efficiently creating complex prompts with structured forms for Claude Code.
Define templates in TypeScript config files to share with your team and enable reproducible prompt workflows.
Works seamlessly with your existing Claude Code setup including MCP and Skills.
Defines a document type (e.g., design doc, meeting notes). Configure prompt templates and output destinations.
Each page of the form wizard. Group related fields together for easier input.
| Scenario Selection | Form Input | Preview |
|---|---|---|
![]() |
![]() |
![]() |
- Node.js 18+
- Claude Code
npm install pre-claude# Try the example
npx pre-claude example
npx pre-claude example --lang ja
# Create a config file
npx pre-claude init
# Run the TUI
npx pre-claude run --config ./pre-claude.config.tsSee examples/ for configuration examples.
The TUI consists of 3 screens.
A 2-pane screen displayed at startup. Select a scenario in the left pane, then choose to create new or edit an existing document in the right pane.
| Key | Action |
|---|---|
ββ / j/k |
Navigate items |
β / l / Enter |
Select / Move to right pane |
β / h / Esc |
Move to left pane |
q |
Quit |
A 3-panel layout with step tabs at the top, field list on the left, and editing area on the right.
| Key | Action |
|---|---|
ββ / h/l |
Navigate steps |
ββ / j/k |
Navigate fields |
Enter |
Start editing / Confirm |
Esc |
Cancel |
n / p |
Next / Previous step |
d |
Delete repeatable item |
g |
Generate preview |
q |
Go back |
AI generates the document and displays the result with streaming.
| Key | Action |
|---|---|
ββ / j/k |
Scroll |
r |
Regenerate |
s |
Save |
c |
Continue in Claude Code |
i |
Show formData / aiContext |
Esc / q |
Go back |
Press c to continue the conversation in Claude Code, inheriting the current session.
import { defineConfig, defineScenario, type Step } from 'pre-claude';
const steps = [
{
slug: 'overview',
title: 'Overview',
description: 'Basic project information',
name: 'overview',
fields: [
{
id: 'title',
type: 'input',
label: 'Title',
description: 'Project name',
required: true,
},
],
},
] as const satisfies Step[];
export default defineConfig({
scenarios: [
defineScenario({
id: 'design-doc',
name: 'Design Document',
steps,
prompt: ({ formData, aiContext }) =>
`Create a design document based on:\n${JSON.stringify({ formData, aiContext }, null, 2)}`,
outputDir: './docs',
}),
],
});| Property | Type | Required | Description |
|---|---|---|---|
id |
string |
β | Unique identifier |
name |
string |
β | Display name |
steps |
Step[] |
β | Form wizard steps |
prompt |
(params) => string |
β | Prompt generator function |
outputDir |
string |
Output directory | |
filename |
string | function |
Filename |
The prompt function receives the following arguments. You can view the actual values by pressing i on the preview screen.
An object containing the values entered in the form.
{
[stepName: string]: {
[fieldId: string]: string | boolean | Array<{ [fieldId: string]: string | boolean }>
}
}Example:
{
"overview": {
"title": "My Project",
"priority": "high"
},
"features": {
"items": [
{ "name": "Feature 1", "desc": "Description 1" },
{ "name": "Feature 2", "desc": "Description 2" }
]
}
}Metadata such as field labels and descriptions. Helps the AI understand the meaning of each field.
{
[stepName: string]: {
_step: { title: string; description: string };
[fieldId: string]: { label: string; description: string }
}
}Example:
{
"overview": {
"_step": { "title": "Overview", "description": "Basic project information" },
"title": { "label": "Title", "description": "Project name" },
"priority": { "label": "Priority", "description": "Select priority" }
}
}| Property | Type | Description |
|---|---|---|
slug |
string |
URL-friendly identifier |
title |
string |
Title |
description |
string |
Description |
name |
string |
Key name in formData |
fields |
Field[] |
Field array |
{
id: 'title',
type: 'input',
label: 'Title',
description: 'Description',
placeholder: 'Placeholder',
required: true,
inputType: 'text', // 'text' | 'date' | 'url'
suggestions: ['Option 1', 'Option 2'], // Autocomplete
default: 'Default value',
}{
id: 'description',
type: 'textarea',
label: 'Description',
description: 'Detailed description',
rows: 5,
}{
id: 'priority',
type: 'select',
label: 'Priority',
description: 'Select priority',
options: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
],
default: 'medium',
}{
id: 'agree',
type: 'checkbox',
label: 'I agree',
description: 'Agreement to terms',
required: true,
}A repeatable field that can be dynamically added or removed.
{
type: 'repeatable',
id: 'features',
label: 'Features',
minCount: 1,
defaultCount: 2,
field: {
type: 'group',
fields: [
{ id: 'name', type: 'input', label: 'Name', description: '' },
{ id: 'desc', type: 'textarea', label: 'Description', description: '', rows: 2 },
],
},
}formData becomes an array:
{
features: [
{ name: 'Feature 1', desc: 'Description 1' },
{ name: 'Feature 2', desc: 'Description 2' },
]
}Groups multiple fields together. Used within repeatable.
Use the when property to specify display conditions for fields.
// Simple conditions
{ ..., when: { field: 'priority', is: 'high' } }
{ ..., when: { field: 'priority', is: ['high', 'medium'] } }
{ ..., when: { field: 'priority', isNot: 'low' } }
{ ..., when: { field: 'title', isNotEmpty: true } }
{ ..., when: { field: 'notes', isEmpty: true } }
// AND condition
{
...,
when: {
and: [
{ field: 'priority', is: 'high' },
{ field: 'type', is: 'feature' }
]
}
}
// OR condition
{
...,
when: {
or: [
{ field: 'priority', is: 'high' },
{ field: 'type', is: 'urgent' }
]
}
}
// Reference fields from other steps
{ ..., when: { field: 'overview.priority', is: 'high' } }Using defineScenario with as const satisfies Step[] enables type inference for formData.
const scenario = defineScenario({
id: 'my-scenario',
name: 'My Scenario',
steps,
prompt: ({ formData }) => {
// formData.overview?.title is string | undefined
return `Title: ${formData.overview?.title ?? 'Untitled'}`;
},
filename: ({ formData, timestamp }) =>
`${formData.overview?.title ?? 'untitled'}-${timestamp}.md`,
});MIT


