Reference for Outfitter Stack patterns including Result types, Handler contract, Error taxonomy, and @outfitter/* package conventions. Use when learning the stack, looking up patterns, understanding packages, or when "Result", "Handler", "error taxonomy", "OutfitterError", "CLI output", "pagination", "MCP server", "MCP tool", "structured logging", "redaction", "test handler", "daemon", "IPC", or "@outfitter/*" are mentioned.
View on GitHubplugins/outfitter-stack/skills/stack-patterns/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-patterns/SKILL.md -a claude-code --skill stack-patternsInstallation paths:
.claude/skills/stack-patterns/# Outfitter Stack Patterns
Primary reference for @outfitter/* package conventions.
## Handler Contract
Handlers are pure functions that:
- Accept typed input and context
- Return `Result<TOutput, TError>`
- Know nothing about transport (CLI flags, HTTP headers, MCP tool schemas)
```typescript
type Handler<TInput, TOutput, TError extends OutfitterError> = (
input: TInput,
ctx: HandlerContext
) => Promise<Result<TOutput, TError>>;
```
### Example
```typescript
import { Result, NotFoundError, type Handler } from "@outfitter/contracts";
export const getUser: Handler<{ id: string }, User, NotFoundError> = async (input, ctx) => {
ctx.logger.debug("Fetching user", { userId: input.id });
const user = await db.users.findById(input.id);
if (!user) {
return Result.err(new NotFoundError("user", input.id));
}
return Result.ok(user);
};
```
**Why?** Testability (just call the function), reusability (same handler for CLI/MCP/HTTP), type safety (explicit types), composability (handlers wrap handlers).
## Result Types
Uses `Result<T, E>` from `better-result` for explicit error handling.
```typescript
import { Result } from "@outfitter/contracts";
// Create
const ok = Result.ok({ name: "Alice" });
const err = Result.err(new NotFoundError("user", "123"));
// Check
if (result.isOk()) {
console.log(result.value); // TypeScript knows T
} else {
console.log(result.error); // TypeScript knows E
}
// Pattern match
const message = result.match({
ok: (user) => `Found ${user.name}`,
err: (error) => `Error: ${error.message}`,
});
// Combine
const combined = combine2(result1, result2); // tuple or first error
```
## Error Taxonomy
Ten categories map to exit codes and HTTP status:
| Category | Exit | HTTP | When to Use |
|----------|------|------|-------------|
| `validation` | 1 | 400 | Invalid input, schema failures |
| `not_found` | 2 | 404 | Resource doesn't exist |
| `conflict` | 3 | 409 | Already exists, version mismatch |
| `permission` | 4 |