How to Build a Code Generation Tool With Claude
How to Build a Code Generation Tool With Claude
Building a code generation tool with Claude means wiring together three things: a prompt structure that reliably produces compilable code, an API integration that can stream or return structured output, and a thin layer of validation that catches the inevitable mistakes before they reach a developer's editor. None of these pieces is exotic — the model does the heavy lifting — but getting the plumbing right is what separates a demo from something people actually use.
This guide walks through the architecture step by step: how to structure prompts for code generation, how to request output you can parse programmatically, how to handle multi-file projects, and how to validate what comes back. If you're calling Claude directly or through a wrapper like SubToAPI, the same principles apply.
Define the Shape of the Output Before You Write a Prompt
The biggest mistake teams make when building a code generation tool is starting with the prompt. Start with the output contract instead. Decide:
- Is the output a single file, a diff, or a multi-file project?
- Do you need the raw code, or code plus explanation, plus a list of dependencies?
- Will downstream code parse the response automatically, or does a human read it?
If a machine consumes the output, you want structured, predictable formatting — not prose with code blocks scattered inside. This is where tool use (function calling) becomes useful even for generation tasks, not just for retrieval. Defining a tool schema like write_file(path, content) forces Claude to return each file as a discrete, parseable object instead of a single blob of markdown you have to regex apart.
{
"name": "write_file",
"description": "Write a single file to the generated project",
"input_schema": {
"type": "object",
"properties": {
"path": { "type": "string" },
"content": { "type": "string" },
"language": { "type": "string" }
},
"required": ["path", "content"]
}
}
See /docs/tools for the full schema format and request structure.
Prompt Structure That Actually Produces Working Code
A code generation prompt should include four things, in this order:
- Role and constraints — language/framework version, style guide, allowed dependencies.
- The task — what the code needs to do, phrased as a spec, not a vague request.
- Examples — one or two short snippets showing the code style you expect (naming conventions, error handling patterns).
- Output format instructions — explicit about whether you want tool calls, a fenced code block, or plain text.
A minimal example:
You are generating a Node.js Express route handler.
Use async/await, no callbacks. Validate inputs with zod.
Return only the file contents for routes/users.js — no explanation.
Task: Create a POST /users endpoint that validates { name: string, email: string }
and returns 201 with the created object, or 400 with validation errors.
Vague prompts ("write a function that handles users") produce code that compiles but doesn't match your conventions. Specific prompts with explicit constraints reduce the amount of post-processing you need to do.
Calling the API
Whether you're hitting Claude directly or through SubToAPI's compatible endpoint, the request shape is the same — a system prompt, a user message with the spec, and optionally a tools array for structured file output.
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4",
"max_tokens": 2048,
"system": "You generate production-ready code. Output only the requested file contents.",
"messages": [
{ "role": "user", "content": "Write a Python function that validates an IBAN." }
]
}'
For a working tool like this, you'll also want usage metadata per request so you can see token cost per generation — useful if you're billing users per generated file or tracking which prompts are expensive. SubToAPI exposes this in every response, which makes it easier to tune prompt length without flying blind. See /docs/messages for the full request/response reference.
Streaming for a Better Editor Experience
If your tool renders generated code live — in a browser-based editor, a CLI, or a VS Code extension — streaming matters more for code generation than almost any other use case. Developers expect to see code appear incrementally, the same way they'd watch themselves type. A non-streaming request that takes 15 seconds to return a 200-line file feels broken; the same request streamed token by token feels instant.
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 4096,
stream: true,
messages: [{ role: "user", content: "Generate a React hook for debounced input." }]
})
});
Full details on consuming the stream are in /docs/streaming.
Multi-File Projects: Generate One File at a Time
When the request is "scaffold a whole feature" rather than "write one function," resist the urge to ask Claude for the entire project in one response. Large multi-file outputs in a single call are harder to validate, more likely to truncate, and harder to re-run partially when one file needs a fix.
Instead:
- Ask Claude to first return a file list and brief description of each (a plan).
- Generate each file as a separate request, passing the plan and already-generated files as context.
- Validate each file (lint, type-check, run tests) before moving to the next.
This costs more tokens overall but produces dramatically more reliable output, and it lets you retry a single failed file instead of the whole batch.
Validate Before You Trust
Generated code should never go straight into a repo unchecked. At minimum:
- Run a linter and type checker against the output.
- For compiled languages, attempt a build.
- For anything touching dependencies, verify the imports actually exist.
If validation fails, feed the error message back to Claude in a follow-up turn ("this code fails to compile with error X, fix it") rather than regenerating from scratch. Iterative fixing within the same conversation is usually faster and cheaper than starting over.
Getting Set Up
If you're building this as an internal tool or a product feature, you don't need to manage separate Claude billing and API key infrastructure. SubToAPI turns your Claude access into a standard HTTPS API with application keys, streaming, tool use, and per-request usage metadata — everything described above works out of the box. Start with /docs/quickstart, check /pricing for plan details, or go straight to /signup to get a key.
FAQ
Does Claude generate code that compiles on the first try? Often, but not reliably enough to skip validation. Treat generated code as a draft: lint it, type-check it, and build it before it reaches production. Feeding compiler errors back to Claude in the same conversation usually fixes issues faster than regenerating from scratch.
Should I use tool use (function calling) or plain text output for code generation? Use tool use when another program needs to parse the output — for example, writing multiple files automatically. Use plain fenced code blocks when a human is reading the response directly in a chat-style interface.
How do I keep generation costs predictable? Break large tasks into smaller, well-scoped requests instead of one giant prompt, and track token usage per request so you can see which prompts are expensive. SubToAPI includes usage metadata on every response, which makes this easy to monitor without extra instrumentation.