Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    epicenterhq

    control-flow

    epicenterhq/control-flow
    Coding
    4,029
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Human-readable control flow patterns for refactoring complex conditionals. Use when refactoring nested conditionals, improving code readability, or restructuring decision logic.

    SKILL.md

    Human-Readable Control Flow

    When refactoring complex control flow, mirror natural human reasoning patterns:

    Related Skills: See refactoring for systematic code audit methodology including branch collapsing and caller counting.

    When to Apply This Skill

    Use this pattern when you need to:

    • Refactor nested conditionals into linear guard-clause control flow.
    • Replace mixed throw/return try-catch logic with readable early returns.
    • Name booleans and branches to read like natural human reasoning.
    • Restructure handlers so failure paths are explicit before the happy path.
    1. Ask the human question first: "Can I use what I already have?" -> early return for happy path
    2. Assess the situation: "What's my current state and what do I need to do?" -> clear, mutually exclusive conditions
    3. Take action: "Get what I need" -> consolidated logic at the end
    4. Use natural language variables: isUsingNavigator, isUsingLocalTranscription, needsOldFileCleanup: names that read like thoughts
    5. Avoid artificial constructs: No nested conditions that don't match how humans actually think through problems

    Transform this: nested conditionals with duplicated logic Into this: linear flow that mirrors human decision-making

    Example: Early Returns with Natural Language Variables

    // From apps/whispering/src/routes/(app)/_layout-utils/check-ffmpeg.ts
    
    export async function checkFfmpegRecordingMethodCompatibility() {
    	if (!window.__TAURI_INTERNALS__) return;
    
    	// Only check if FFmpeg recording method is selected
    	if (settings.value['recording.method'] !== 'ffmpeg') return;
    
    	const { data: ffmpegInstalled } =
    		await rpc.ffmpeg.checkFfmpegInstalled.ensure();
    	if (ffmpegInstalled) return; // FFmpeg is installed, all good
    
    	// FFmpeg recording method selected but not installed
    	toast.warning('FFmpeg Required for FFmpeg Recording Method', {
    		// ... toast content
    	});
    }
    

    Example: Natural Language Booleans

    // From apps/whispering/src/routes/(app)/_layout-utils/check-ffmpeg.ts
    
    const isUsingNavigator = settings.value['recording.method'] === 'navigator';
    const isUsingLocalTranscription =
    	settings.value['transcription.selectedTranscriptionService'] ===
    		'whispercpp' ||
    	settings.value['transcription.selectedTranscriptionService'] === 'parakeet';
    
    return isUsingNavigator && isUsingLocalTranscription && !isFFmpegInstalled;
    

    Example: Cleanup Check with Comment

    // From packages/epicenter/src/indexes/markdown/markdown-index.ts
    
    /**
     * This is checking if there's an old filename AND if it's different
     * from the new one. It's essentially checking: "has the filename
     * changed?" and "do we need to clean up the old file?"
     */
    const needsOldFileCleanup = oldFilename && oldFilename !== filename;
    if (needsOldFileCleanup) {
    	const oldFilePath = path.join(tableConfig.directory, oldFilename);
    	await deleteMarkdownFile({ filePath: oldFilePath });
    	tracking[table.name]!.deleteByFilename({ filename: oldFilename });
    }
    

    Example: Linearizing try-catch into Guard + Happy Path

    try-catch blocks create a nested, two-branch structure: the try body and the catch body. When only one call inside the try can actually throw, replace the try-catch with a guarded call + early return so the code reads top-to-bottom.

    Before (nested, mixed throw/return):

    async ({ body, status }) => {
    	const adapter = createAdapter(body.provider);
    
    	try {
    		const stream = chat({ adapter, messages: body.messages });
    		return toServerSentEventsResponse(stream);
    	} catch (error) {
    		if (error instanceof Error && error.name === 'AbortError') {
    			throw status(499, 'Client closed request');
    		}
    		const message = error instanceof Error ? error.message : 'Unknown error';
    		throw status('Bad Gateway', `Provider error: ${message}`);
    	}
    };
    

    After (linear, consistent returns):

    async ({ body, status }) => {
    	const adapter = createAdapter(body.provider);
    
    	const { data: stream, error: chatError } = trySync({
    		try: () => chat({ adapter, messages: body.messages }),
    		catch: (e) => Err(e instanceof Error ? e : new Error(String(e))),
    	});
    
    	if (chatError) {
    		if (chatError.name === 'AbortError') {
    			return status(499, 'Client closed request');
    		}
    		return status('Bad Gateway', `Provider error: ${chatError.message}`);
    	}
    
    	return toServerSentEventsResponse(stream);
    };
    

    The transformation follows the same human reasoning pattern:

    1. Try the risky thing — wrap only what can fail
    2. Check if it failed — early return with the appropriate error
    3. Continue with the happy path — the rest of the function assumes success

    This eliminates the nesting, makes return vs throw consistent, and separates the error boundary from the safe code that follows it.

    Example: Sequential Guards in a Handler

    When a handler has multiple failure points, each guard follows the same pattern: do the thing, check the result, return early or continue.

    async ({ body, status }) => {
    	// Guard 1: validate input
    	if (!isSupportedProvider(body.provider)) {
    		return status('Bad Request', `Unsupported provider: ${body.provider}`);
    	}
    
    	// Guard 2: resolve dependency
    	const apiKey = resolveApiKey(body.provider, headers['x-api-key']);
    	if (!apiKey) {
    		return status('Unauthorized', 'Missing API key');
    	}
    
    	// Guard 3: risky operation
    	const { data: stream, error } = trySync({
    		try: () => chat({ adapter: createAdapter(body.provider, apiKey) }),
    		catch: (e) => Err(e instanceof Error ? e : new Error(String(e))),
    	});
    	if (error) return status('Bad Gateway', error.message);
    
    	// Happy path — all guards passed
    	return toServerSentEventsResponse(stream);
    };
    

    Every guard has the same shape: check → return early on failure. The happy path accumulates at the bottom. Reading top-to-bottom, you see every way the function can fail before you see the success case.

    Recommended Servers
    Vercel Grep
    Vercel Grep
    Thoughtbox
    Thoughtbox
    Browserbase
    Browserbase
    Repository
    epicenterhq/epicenter
    Files