Templates for creating handlers, CLI commands, MCP tools, and daemon services following Outfitter Stack conventions. Use when scaffolding new components, creating handlers, adding commands, or when "create handler", "new command", "add tool", "scaffold", "template", or "daemon service" are mentioned.
View on GitHubplugins/outfitter-stack/skills/stack-templates/SKILL.md
February 1, 2026
Select agents to install to:
npx add-skill https://github.com/outfitter-dev/agents/blob/main/plugins/outfitter-stack/skills/stack-templates/SKILL.md -a claude-code --skill stack-templatesInstallation paths:
.claude/skills/stack-templates/# Stack Templates
Templates for creating @outfitter/* components.
## Component Types
| Type | Package | Template |
|------|---------|----------|
| Handler | `@outfitter/contracts` | [handler](#handler) |
| Handler Test | `@outfitter/testing` | [handler-test](#handler-test) |
| CLI Command | `@outfitter/cli` | [cli-command](#cli-command) |
| MCP Tool | `@outfitter/mcp` | [mcp-tool](#mcp-tool) |
| Daemon | `@outfitter/daemon` | [daemon-service](#daemon-service) |
## Handler
Transport-agnostic business logic returning `Result<T, E>`:
```typescript
import {
Result,
ValidationError,
NotFoundError,
createValidator,
type Handler,
} from "@outfitter/contracts";
import { z } from "zod";
// 1. Input schema
const InputSchema = z.object({
id: z.string().min(1),
});
type Input = z.infer<typeof InputSchema>;
// 2. Output type
interface Output {
id: string;
name: string;
}
// 3. Validator
const validateInput = createValidator(InputSchema);
// 4. Handler
export const myHandler: Handler<unknown, Output, ValidationError | NotFoundError> = async (
rawInput,
ctx
) => {
const inputResult = validateInput(rawInput);
if (inputResult.isErr()) return inputResult;
const input = inputResult.value;
ctx.logger.debug("Processing", { id: input.id });
const resource = await fetchResource(input.id);
if (!resource) {
return Result.err(new NotFoundError("resource", input.id));
}
return Result.ok(resource);
};
```
## Handler Test
Test handlers directly without transport layer:
```typescript
import { describe, test, expect } from "bun:test";
import { createContext } from "@outfitter/contracts";
import { myHandler } from "../handlers/my-handler.js";
describe("myHandler", () => {
test("returns success for valid input", async () => {
const ctx = createContext({});
const result = await myHandler({ id: "valid-id" }, ctx);
expect(result.isOk()).toBe(true);
expect(result.value).toMatchObject({ id: "valid-id" });
});
test("returns