Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Define commands once, deploy to CLI, API, and MCP automatically. Use when building new commands/tools for Supernal — ensures consistent interfaces across all...
Define commands once, deploy to CLI, API, and MCP automatically. Use when building new commands/tools for Supernal — ensures consistent interfaces across all...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Define once, deploy everywhere. Single source of truth for CLI, API, and MCP interfaces.
If you're building commands for Supernal, use this package. Don't create separate CLI/API/MCP implementations.
npm install @supernal/universal-command
import { UniversalCommand } from '@supernal/universal-command'; export const userCreate = new UniversalCommand({ name: 'user create', description: 'Create a new user', input: { parameters: [ { name: 'name', type: 'string', required: true }, { name: 'email', type: 'string', required: true }, { name: 'role', type: 'string', default: 'user', enum: ['user', 'admin'] }, ], }, output: { type: 'json' }, handler: async (args, context) => { return await createUser(args); }, });
// CLI program.addCommand(userCreate.toCLI()); // → mycli user create --name "Alice" --email "alice@example.com" // Next.js API export const POST = userCreate.toNextAPI(); // → POST /api/users/create // MCP Tool const mcpTool = userCreate.toMCP(); // → user_create tool for AI agents
Write your logic once. The handler receives validated args and returns the result: handler: async (args, context) => { // This same code runs for CLI, API, and MCP return await doThing(args); }
Define parameters once — validation, CLI options, API params, and MCP schema are auto-generated: input: { parameters: [ { name: 'id', type: 'string', required: true }, { name: 'status', type: 'string', enum: ['draft', 'active', 'done'] }, { name: 'limit', type: 'number', min: 1, max: 100, default: 10 }, ], }
Override behavior per interface when needed: cli: { format: (data) => formatForTerminal(data), streaming: true, }, api: { method: 'GET', cacheControl: { maxAge: 300 }, auth: { required: true, roles: ['admin'] }, }, mcp: { resourceLinks: ['export://results'], },
For multiple commands: import { CommandRegistry } from '@supernal/universal-command'; const registry = new CommandRegistry(); registry.register(userCreate); registry.register(userList); registry.register(userDelete); // Generate all CLI commands for (const cmd of registry.getAll()) { program.addCommand(cmd.toCLI()); } // Generate all API routes await generateNextRoutes(registry, { outputDir: 'app/api' }); // Generate MCP server const server = createMCPServer(registry);
For simple setups without code generation: import { createRuntimeServer } from '@supernal/universal-command'; const server = createRuntimeServer(); server.register(userCreate); server.register(userList); // Serve as Next.js export const GET = server.getNextHandlers().GET; export const POST = server.getNextHandlers().POST; // Or as Express app.use('/api', server.getExpressRouter()); // Or as MCP await server.startMCP({ name: 'my-server', transport: 'stdio' });
Know which interface is calling: handler: async (args, context) => { if (context.interface === 'cli') { // CLI-specific logic } else if (context.interface === 'api') { const userId = context.request.headers.get('x-user-id'); } return result; }
Test once, works everywhere: import { userCreate } from './user-create'; test('creates user', async () => { const result = await userCreate.execute( { name: 'Alice', email: 'alice@example.com' }, { interface: 'test' } ); expect(result.name).toBe('Alice'); });
┌─────────────────────────────────────────┐ │ UniversalCommand Definition │ │ name, description, input, handler │ └────────────────┬────────────────────────┘ │ ┌────────┼────────┐ ▼ ▼ ▼ ┌─────┐ ┌─────┐ ┌─────┐ │ CLI │ │ API │ │ MCP │ └─────┘ └─────┘ └─────┘
✅ Building any new Supernal command/tool ✅ Adding CLI interface to existing logic ✅ Exposing functionality to AI agents (MCP) ✅ Creating REST APIs with consistent patterns ❌ Simple one-off scripts (overkill) ❌ Third-party integrations with their own patterns
Both sc (supernal-coding) and si (supernal-interface) use universal-command under the hood. When adding new commands to these tools, define them as UniversalCommands.
class UniversalCommand<TInput, TOutput> { execute(args: TInput, context: ExecutionContext): Promise<TOutput>; toCLI(): Command; // Commander.js Command toNextAPI(): NextAPIRoute; // Next.js route handler toExpressAPI(): ExpressRoute; toMCP(): MCPToolDefinition; validateArgs(args: unknown): ValidationResult<TInput>; } class CommandRegistry { register(command: UniversalCommand): void; getAll(): UniversalCommand[]; } function createRuntimeServer(): RuntimeServer; function generateNextRoutes(registry: CommandRegistry, options: CodegenOptions): Promise<void>; function createMCPServer(registry: CommandRegistry, options: MCPOptions): MCPServer;
Package: @supernal/universal-command npm: https://www.npmjs.com/package/@supernal/universal-command DO NOT rebuild this pattern. Use it!
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.