Skip to main content
scaffold Creates handlers, CLI commands, MCP tools, and daemon services following Outfitter Dev Kit conventions. Use when adding new components to a project, scaffolding code, or when "create handler", "new command", "add tool", or "daemon service" are mentioned.
الانتقال إلى التثبيت سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/outfitter-dev/outfitter --skill scaffoldيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المزيد من هذا المستودع Patterns for @outfitter/daemon including lifecycle management, IPC communication, health checks, and PID files. Use when building background services, daemons, or when "daemon", "IPC", "health check", "background service", or "@outfitter/daemon" are mentioned.
Deep patterns for @outfitter/mcp including tool registration, Zod schemas, resources, and server configuration. Use when building MCP servers, registering tools, defining resources, or when "MCP server", "MCP tool", "registerTool", or "@outfitter/mcp" are mentioned.
Generates patterns, templates, and guides for @outfitter/* packages. Covers transport-agnostic handler systems, Result types, error taxonomy, and package APIs. Use when working with @outfitter/*, Result types, Handler contract, error taxonomy, or when Result, Handler, ValidationError, NotFoundError, OutfitterError, or package names like contracts, cli, mcp, schema, tui, daemon, config, logging are mentioned.
المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
name scaffold version 0.1.0 description Creates handlers, CLI commands, MCP tools, and daemon services following Outfitter Dev Kit conventions. Use when adding new components to a project, scaffolding code, or when "create handler", "new command", "add tool", or "daemon service" are mentioned. allowed-tools Read Write Edit Glob Grep argument-hint ["component type"]
Scaffold Stack Components
Templates for creating @outfitter/* components.
Component Types
Handler
Transport-agnostic business logic returning Result<T, E>:
import {
Result ,
ValidationError ,
NotFoundError ,
createValidator,
type Handler ,
} from "@outfitter/contracts" ;
import { z } from "zod" ;
const InputSchema = z.object ({
id : z.string ().min (1 ),
});
type Input = z.infer <typeof InputSchema >;
interface Output {
id : string ;
name : string ;
}
const validateInput = createValidator (InputSchema );
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 (NotFoundError .create ("resource" , input.id ));
}
return Result .ok (resource);
};
CLI Command For Outfitter apps, define CLI behavior in the action registry and let
buildCliCommands() wire Commander for you.
import { actionCliPresets } from "@outfitter/cli/actions" ;
import { output } from "@outfitter/cli" ;
import { cwdPreset, verbosePreset } from "@outfitter/cli/flags" ;
import { jqPreset, outputModePreset } from "@outfitter/cli/query" ;
import { defineAction, Result } from "@outfitter/contracts" ;
import { z } from "zod" ;
import { myHandler } from "../handlers/my-handler.js" ;
const shared = actionCliPresets (verbosePreset (), cwdPreset ());
const mode = outputModePreset ({ includeJsonl : true });
const jq = jqPreset ();
export const myAction = defineAction ({
id : "my.get" ,
description : "Get a resource" ,
surfaces : ["cli" ],
input : z.object ({
id : z.string ().min (1 ),
verbose : z.boolean ().optional (),
cwd : z.string (),
outputMode : z.enum (["human" , "json" , "jsonl" ]).default ("human" ),
jq : z.string ().optional (),
}),
output : z.object ({
id : z.string (),
name : z.string (),
}),
cli : {
group : "my" ,
command : "get <id>" ,
options : [...shared.options , ...mode.options , ...jq.options ],
mapInput : ({ args, flags } ) => ({
id : String (args[0 ] ?? "" ),
...shared.resolve (flags),
...mode.resolve (flags),
...jq.resolve (flags),
}),
},
handler : async (input, ctx) => {
const result = await myHandler ({ id : input.id }, ctx);
if (result.isErr ()) {
return result;
}
await output (result.value , { mode : input.outputMode });
return Result .ok (result.value );
},
});
import { buildCliCommands } from "@outfitter/cli/actions" ;
import { createCLI } from "@outfitter/cli/command" ;
import { createActionRegistry } from "@outfitter/contracts" ;
import { myAction } from "./actions/my-action.js" ;
const cli = createCLI ({ name : "myapp" , version : "1.0.0" });
const registry = createActionRegistry ([myAction]);
for (const command of buildCliCommands (registry, {
schema : { programName : "myapp" , surface : {} },
})) {
cli.register (command);
}
await cli.parse ();
myapp schema generate
myapp schema diff
MCP Tool Zod schema with Result return:
import { Result , ValidationError } from "@outfitter/contracts" ;
import { z } from "zod" ;
const InputSchema = z.object ({
query : z.string ().describe ("Search query" ),
limit : z.number ().int ().positive ().default (10 ).describe ("Max results" ),
});
interface Output {
results : Array <{ id : string ; title : string }>;
total : number ;
}
export const myTool = {
name : "my_tool" ,
description : "Tool description for AI agent" ,
inputSchema : InputSchema ,
handler : async (
input : z.infer <typeof InputSchema >
): Promise <Result <Output , ValidationError >> => {
const results = await search (input.query , input.limit );
return Result .ok ({ results, total : results.length });
},
};
import { createMcpServer } from "@outfitter/mcp" ;
import { myTool } from "./tools/my-tool.js" ;
const server = createMcpServer ({ name : "my-server" , version : "0.1.0" });
server.registerTool (myTool);
server.start ();
Daemon Service Background service with health checks and IPC:
import {
createDaemon,
createIpcServer,
createHealthChecker,
getSocketPath,
getLockPath,
} from "@outfitter/daemon" ;
import { createLogger, createConsoleSink } from "@outfitter/logging" ;
import { Result } from "@outfitter/contracts" ;
const logger = createLogger ({
name : "my-daemon" ,
level : "info" ,
sinks : [createConsoleSink ()],
redaction : { enabled : true },
});
const daemon = createDaemon ({
name : "my-daemon" ,
pidFile : getLockPath ("my-daemon" ),
logger,
shutdownTimeout : 10000 ,
});
const healthChecker = createHealthChecker ([
{
name : "memory" ,
check : async () => {
const used = process.memoryUsage ().heapUsed / 1024 / 1024 ;
return used < 500
? Result .ok (undefined )
: Result .err (new Error (`High memory: ${used.toFixed(2 )} MB` ));
},
},
]);
const ipcServer = createIpcServer (getSocketPath ("my-daemon" ));
ipcServer.onMessage (async (msg) => {
const message = msg as { type : string };
switch (message.type ) {
case "status" :
return { status : "ok" , uptime : process.uptime () };
case "health" :
return await healthChecker.check ();
default :
return { error : "Unknown command" };
}
});
daemon.onShutdown (async () => {
logger.info ("Shutting down..." );
await ipcServer.close ();
});
async function main ( ) {
const startResult = await daemon.start ();
if (startResult.isErr ()) {
logger.error ("Failed to start" , { error : startResult.error });
process.exit (1 );
}
await ipcServer.listen ();
logger.info ("Started" , { socket : getSocketPath ("my-daemon" ) });
}
main ();
Best Practices
Handler First — Write handler before adapter (CLI/MCP/API)
Action Registry First — Add CLI behavior via defineAction() and mapInput()
Preset Composition — Prefer shared presets over manual flag parsing
Schema Drift Guard — Regenerate and diff .outfitter/surface.lock after CLI changes
Validate Early — Use createValidator at handler entry
Type Errors — List all error types in handler signature
Context Propagation — Pass context through all handler calls
Test Handlers — Test handlers directly without transport layer
References