<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Levi</title>
    <description>The latest articles on Forem by Levi (@levitc).</description>
    <link>https://forem.com/levitc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3864354%2F5130f60c-cbd8-46dd-a0ca-58915313f684.png</url>
      <title>Forem: Levi</title>
      <link>https://forem.com/levitc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/levitc"/>
    <language>en</language>
    <item>
      <title>I converted 10 popular APIs to MCP tools. 7 would let an agent delete your data with zero guardrails.</title>
      <dc:creator>Levi</dc:creator>
      <pubDate>Sat, 11 Apr 2026 14:16:53 +0000</pubDate>
      <link>https://forem.com/levitc/i-converted-10-popular-apis-to-mcp-tools-7-would-let-an-agent-delete-your-data-with-zero-kp6</link>
      <guid>https://forem.com/levitc/i-converted-10-popular-apis-to-mcp-tools-7-would-let-an-agent-delete-your-data-with-zero-kp6</guid>
      <description>&lt;p&gt;Stripe. GitHub. Twilio. Slack. Notion. Shopify. Discord. SendGrid. Linear. PagerDuty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;None of them&lt;/strong&gt; ship MCP tool definitions. Every agent developer connecting to these APIs is hand-wiring tools, writing custom auth, and — most dangerously — giving agents full CRUD access with zero risk classification.&lt;/p&gt;

&lt;p&gt;These are the APIs that run production systems. If you're connecting them to AI agents without knowing which endpoints are destructive, you're one hallucination away from a very bad day.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem is worse than "no MCP support"
&lt;/h2&gt;

&lt;p&gt;I took the public OpenAPI specs for 10 of the most commonly used APIs and converted them to MCP tool definitions. Then I counted how many destructive operations each one exposes — endpoints that delete data, cancel subscriptions, revoke access, or mutate state irreversibly.&lt;/p&gt;

&lt;p&gt;Here's what I found:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Total Endpoints&lt;/th&gt;
&lt;th&gt;Safe (GET)&lt;/th&gt;
&lt;th&gt;Moderate (POST/PATCH)&lt;/th&gt;
&lt;th&gt;Destructive (DELETE)&lt;/th&gt;
&lt;th&gt;Official MCP server?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stripe&lt;/td&gt;
&lt;td&gt;314&lt;/td&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;163&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;347&lt;/td&gt;
&lt;td&gt;189&lt;/td&gt;
&lt;td&gt;111&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;Community only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twilio&lt;/td&gt;
&lt;td&gt;215&lt;/td&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slack&lt;/td&gt;
&lt;td&gt;168&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;112&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notion&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Community only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shopify Admin&lt;/td&gt;
&lt;td&gt;280+&lt;/td&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;td&gt;130&lt;/td&gt;
&lt;td&gt;55+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discord&lt;/td&gt;
&lt;td&gt;190+&lt;/td&gt;
&lt;td&gt;65&lt;/td&gt;
&lt;td&gt;89&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SendGrid&lt;/td&gt;
&lt;td&gt;120+&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linear&lt;/td&gt;
&lt;td&gt;50+ (GraphQL)&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Community only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PagerDuty&lt;/td&gt;
&lt;td&gt;180+&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;That's 300+ destructive endpoints across 10 APIs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you convert an API spec to MCP tools and hand them all to an agent, those destructive endpoints are mixed in with everything else. The agent doesn't know that &lt;code&gt;delete_customer&lt;/code&gt; is fundamentally different from &lt;code&gt;get_customer&lt;/code&gt;. They're both just tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually goes wrong
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stripe:&lt;/strong&gt; 47 DELETE endpoints include &lt;code&gt;delete_customer&lt;/code&gt;, &lt;code&gt;void_invoice&lt;/code&gt;, &lt;code&gt;cancel_subscription&lt;/code&gt;, and &lt;code&gt;refund_charge&lt;/code&gt;. An agent trying to "clean up test data" could cancel live subscriptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;code&gt;delete_repository&lt;/code&gt;, &lt;code&gt;remove_collaborator&lt;/code&gt;, &lt;code&gt;transfer_repository&lt;/code&gt;, &lt;code&gt;delete_org&lt;/code&gt;. An agent asked to "reorganize the GitHub org" has the tools to do irreversible damage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shopify:&lt;/strong&gt; The admin API lets you delete products, cancel orders, and remove customer data. An agent doing "inventory management" has access to endpoints that can wipe your catalog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Twilio:&lt;/strong&gt; &lt;code&gt;delete_message&lt;/code&gt;, &lt;code&gt;release_phone_number&lt;/code&gt;, &lt;code&gt;delete_recording&lt;/code&gt;. An agent optimizing your Twilio usage could release production phone numbers.&lt;/p&gt;

&lt;p&gt;The pattern is always the same: the API spec doesn't distinguish between "safe to call freely" and "requires human approval." That distinction only exists if you add it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm doing about it
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://github.com/ruah-dev" rel="noopener noreferrer"&gt;ruah conv&lt;/a&gt; to automate this entire pipeline — and to add the safety layer that API specs don't have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @ruah-dev/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point it at any API spec, get MCP tools with automatic risk classification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruah conv generate stripe-openapi.yaml &lt;span class="nt"&gt;--target&lt;/span&gt; mcp-ts-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;→ 314 tools generated from stripe-openapi.yaml
→ Risk breakdown: 104 safe, 163 moderate, 47 destructive
→ Destructive: delete_customer, cancel_subscription, 
   refund_charge, void_invoice... (+43 more)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every tool gets tagged &lt;code&gt;safe&lt;/code&gt;, &lt;code&gt;moderate&lt;/code&gt;, or &lt;code&gt;destructive&lt;/code&gt; based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP method (GET = safe, DELETE = destructive)&lt;/li&gt;
&lt;li&gt;Endpoint patterns (&lt;code&gt;/cancel&lt;/code&gt;, &lt;code&gt;/revoke&lt;/code&gt;, &lt;code&gt;/destroy&lt;/code&gt;, &lt;code&gt;/remove&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Mutation semantics (state changes that can't be undone)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you filter before loading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Only generate safe + moderate tools. No destructive.&lt;/span&gt;
ruah conv generate stripe-openapi.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target&lt;/span&gt; mcp-ts-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--max-risk&lt;/span&gt; moderate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your agent has 267 tools instead of 314, and none of them can delete anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The context window problem (bonus finding)
&lt;/h2&gt;

&lt;p&gt;Here's the other thing nobody warned me about:&lt;/p&gt;

&lt;p&gt;Each MCP tool definition is 200–500 tokens. Stripe's 314 endpoints = &lt;strong&gt;60,000–150,000 tokens&lt;/strong&gt; just for tool metadata.&lt;/p&gt;

&lt;p&gt;Perplexity's CTO flagged this at Ask 2026 — MCP tool descriptions eat 40–50% of available context windows before agents do any actual work.&lt;/p&gt;

&lt;p&gt;The fix is the same: &lt;strong&gt;filter before you load.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Only payment-related tools, nothing destructive&lt;/span&gt;
ruah conv generate stripe-openapi.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target&lt;/span&gt; mcp-ts-server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--include-tags&lt;/span&gt; payments,charges &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--max-risk&lt;/span&gt; moderate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;25 tools instead of 314. Your agent is safer AND faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input formats → Output targets
&lt;/h2&gt;

&lt;p&gt;ruah conv doesn't just handle OpenAPI. These are all the specs I tested with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inputs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAPI 3.x / Swagger 2.0&lt;/li&gt;
&lt;li&gt;Postman Collection v2.1&lt;/li&gt;
&lt;li&gt;GraphQL SDL (Linear, Shopify Storefront)&lt;/li&gt;
&lt;li&gt;HAR files (recorded browser traffic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Outputs:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;What you get&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcp-ts-server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full TypeScript MCP server scaffold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcp-py-server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full Python MCP server scaffold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcp-tools&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Just the tool definitions (JSON)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;openai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OpenAI function-calling schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;anthropic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Anthropic tool schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a2a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agent-to-Agent service wrapper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Auth normalization, pagination wrappers, retry logic, and dry-run mode included in every output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @ruah-dev/cli
ruah conv generate your-spec.yaml &lt;span class="nt"&gt;--target&lt;/span&gt; mcp-ts-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Node.js 18+. One dependency. MIT licensed.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/ruah-dev" rel="noopener noreferrer"&gt;github.com/ruah-dev&lt;/a&gt;&lt;br&gt;
Docs: &lt;a href="https://www.ruah.sh" rel="noopener noreferrer"&gt;ruah.sh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The converter is part of a larger toolchain (orchestrator for parallel agents, optimizer for cost tracking), but it works completely standalone. No lock-in, no account, no cloud dependency.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>I got tired of hand-wiring agent tools, so I built an OpenAPI MCP converter</title>
      <dc:creator>Levi</dc:creator>
      <pubDate>Sat, 11 Apr 2026 10:30:08 +0000</pubDate>
      <link>https://forem.com/levitc/i-got-tired-of-hand-wiring-agent-tools-so-i-built-an-openapi-mcp-converter-1251</link>
      <guid>https://forem.com/levitc/i-got-tired-of-hand-wiring-agent-tools-so-i-built-an-openapi-mcp-converter-1251</guid>
      <description>&lt;p&gt;You know that moment where you find the perfect API for your agent, and then you spend the next 45 minutes manually writing tool definitions for it?&lt;/p&gt;

&lt;p&gt;Mapping every parameter. Copying descriptions from the docs. Realizing you forgot the request body schema. Debugging why the agent keeps hallucinating a parameter that doesn't exist.&lt;/p&gt;

&lt;p&gt;I kept doing this. Over and over. For every API. And at some point I thought — the machine-readable spec is &lt;em&gt;right there&lt;/em&gt;. Why am I doing this by hand?&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/ruah-dev/ruah-conv" rel="noopener noreferrer"&gt;Ruah Convert&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Feed it an OpenAPI spec. Get MCP tool definitions out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @ruah-dev/conv generate petstore.yaml &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. One command. You get a JSON array of MCP-compatible tools with names, descriptions, and input schemas — ready to drop into any agent framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  But first, let me inspect
&lt;/h2&gt;

&lt;p&gt;Before generating anything, you probably want to know what's in the spec. The &lt;code&gt;inspect&lt;/code&gt; command gives you a quick summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @ruah-dev/conv inspect petstore.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API Spec Summary
──────────────────────────────────────────────────
  Title:    Petstore API
  Version:  1.0.0
  Format:   openapi-3.0
  Base URL: https://api.petstore.example.com/v1

Auth Schemes (1)
  • apiKeyAuth: apiKey (X-API-Key)

Tools (4)
  • listPets    GET    /pets           (2 params)
  • createPet   POST   /pets           (0 params +body)  [moderate]
  • getPet      GET    /pets/{petId}   (1 params)
  • deletePet   DELETE /pets/{petId}   (1 params)         [destructive]

Types (3)
  Pet, NewPet, Error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every endpoint becomes a tool. Every parameter maps into the input schema. And notice the &lt;code&gt;[moderate]&lt;/code&gt; and &lt;code&gt;[destructive]&lt;/code&gt; tags — more on that in a second.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risk classification
&lt;/h2&gt;

&lt;p&gt;This is my favorite part. Every generated tool gets a risk level based on its HTTP method:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET, HEAD, OPTIONS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;safe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read-only, no side effects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;moderate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT, PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;moderate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Modifies resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;destructive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removes resources&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Your agent knows which tools are dangerous &lt;em&gt;before&lt;/em&gt; it calls them. If you're building guardrails or approval workflows, this gives you the classification for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation catches problems early
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @ruah-dev/conv validate petstore.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This checks your spec for things that will trip up LLMs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Missing descriptions&lt;/strong&gt; — LLMs need these to understand what a tool does&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unresolved &lt;code&gt;$ref&lt;/code&gt;&lt;/strong&gt; — broken references mean broken schemas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate tool names&lt;/strong&gt; — two operations with the same name = confusion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No operations&lt;/strong&gt; — a spec with no paths has nothing to convert&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Warnings are advisory. The tool still generates output, but you know what to fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works under the hood
&lt;/h2&gt;

&lt;p&gt;Most converters are one-to-one: OpenAPI in, one specific format out. That works until you need to support Postman collections, or GraphQL, or output in OpenAI's function calling format instead of MCP.&lt;/p&gt;

&lt;p&gt;Ruah Convert uses an &lt;strong&gt;intermediate representation&lt;/strong&gt; called the Ruah Tool Schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Input Parsers              IR                Output Generators
 ─────────────        ──────────────        ─────────────────────
 OpenAPI 3.x  ──┐                        ┌── MCP Tool Definitions ✓
 Swagger 2.0  ──┤                        ├── MCP Server (TS)
 Postman v2.1 ──┼──→  Ruah Tool Schema ──┼── Function Calling (OpenAI)
 GraphQL SDL  ──┤     (canonical IR)     ├── Function Calling (Anthropic)
 HAR files    ──┘                        └── A2A service wrapper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every input parser normalizes to the IR. Every output generator reads from it. Adding a new input format means writing one parser. Adding a new output format means writing one generator. Never N×M.&lt;/p&gt;

&lt;p&gt;The IR is fully inspectable — &lt;code&gt;ruah conv inspect ./spec.yaml --json&lt;/code&gt; dumps the whole thing as JSON, so you can pipe it into whatever you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programmatic API
&lt;/h2&gt;

&lt;p&gt;Not just a CLI. You can use it in your own code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validateIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;generate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ruah-dev/conv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./petstore.yaml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;warnings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validateIR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mcp-tool-defs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What ships today (v0.1)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OpenAPI 3.0 / 3.1 parser (YAML and JSON)&lt;/li&gt;
&lt;li&gt;Ruah Tool Schema intermediate representation&lt;/li&gt;
&lt;li&gt;MCP tool definitions output (JSON)&lt;/li&gt;
&lt;li&gt;Risk classification per tool&lt;/li&gt;
&lt;li&gt;IR validation with warnings&lt;/li&gt;
&lt;li&gt;CLI: &lt;code&gt;generate&lt;/code&gt;, &lt;code&gt;inspect&lt;/code&gt;, &lt;code&gt;validate&lt;/code&gt;, &lt;code&gt;targets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Programmatic API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;v0.2&lt;/strong&gt;: Full MCP TypeScript server scaffold, Swagger 2.0 auto-upgrade, Postman collection parser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v0.3&lt;/strong&gt;: MCP Python server (FastMCP), OpenAI + Anthropic function calling schemas, GraphQL SDL parser&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run without installing&lt;/span&gt;
npx @ruah-dev/conv inspect your-api-spec.yaml

&lt;span class="c"&gt;# Or install globally&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ruah-dev/conv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One runtime dependency (&lt;code&gt;yaml&lt;/code&gt;). Node 18+. MIT licensed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/ruah-dev/ruah-conv" rel="noopener noreferrer"&gt;github.com/ruah-dev/ruah-conv&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;a href="https://www.npmjs.com/package/@ruah-dev/conv" rel="noopener noreferrer"&gt;@ruah-dev/conv&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This is the first tool in the &lt;a href="https://github.com/ruah-dev" rel="noopener noreferrer"&gt;Ruah ecosystem&lt;/a&gt; — an open-source toolchain for building, running, and managing agentic AI systems. Orchestration, planning, safety, observability — all composable, all standalone.&lt;/p&gt;

&lt;p&gt;If you're building with agents, I'd love to hear what you think. What APIs are you wiring up? What output formats do you need? Drop a comment or open an issue.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I Let 5 AI Agents Loose on One Repo. It Was a Disaster. So I Built This.</title>
      <dc:creator>Levi</dc:creator>
      <pubDate>Fri, 10 Apr 2026 19:46:48 +0000</pubDate>
      <link>https://forem.com/levitc/i-let-5-ai-agents-loose-on-one-repo-it-was-a-disaster-so-i-built-this-k3</link>
      <guid>https://forem.com/levitc/i-let-5-ai-agents-loose-on-one-repo-it-was-a-disaster-so-i-built-this-k3</guid>
      <description>&lt;p&gt;Last month I tried something ambitious: split a feature across five AI coding agents running in parallel. Claude Code on auth. Aider on the API. Codex on tests. Two more on frontend components.&lt;/p&gt;

&lt;p&gt;Within 90 seconds, three of them had edited &lt;code&gt;src/index.ts&lt;/code&gt;. Two had conflicting changes to the same utility function. One had deleted a file another was importing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The merge was unfixable.&lt;/strong&gt; I lost an hour untangling it, then threw everything away and did it sequentially. One agent at a time. Like it's 2024.&lt;/p&gt;

&lt;p&gt;That experience broke something in my brain. AI agents are fast enough to work in parallel — but our tooling assumes they work alone. So I built the missing piece.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Every AI coding tool — Claude Code, Cursor, Aider, Codex, Windsurf — operates with a mental model of "one agent, one repo." And that's fine for solo tasks.&lt;/p&gt;

&lt;p&gt;But the moment you want parallelism — the thing that &lt;em&gt;should&lt;/em&gt; make AI 5x faster — you hit the wall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No workspace isolation.&lt;/strong&gt; Agents share a checkout. One agent's &lt;code&gt;git stash&lt;/code&gt; nukes another's work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No file ownership.&lt;/strong&gt; Two agents rewrite the same module with zero awareness of each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No merge strategy.&lt;/strong&gt; You're the merge strategy. At 2am. With conflicting diffs you didn't write.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No dependency ordering.&lt;/strong&gt; The frontend agent starts before the API it depends on exists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git branches help with history isolation. But branches don't prevent two agents from touching the same files. They just defer the pain to merge time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ruah Orch: Parallel Agents That Don't Collide
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ruah-dev/ruah-orch" rel="noopener noreferrer"&gt;Ruah Orch&lt;/a&gt; is an open-source orchestration engine that coordinates multiple AI agents working on the same repository. Each task gets:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. An isolated workspace&lt;/strong&gt; (Git worktree — a real checkout, not a branch)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruah task create auth &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/auth/**"&lt;/span&gt; &lt;span class="nt"&gt;--executor&lt;/span&gt; claude-code
ruah task create api  &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/api/**"&lt;/span&gt;  &lt;span class="nt"&gt;--executor&lt;/span&gt; aider
ruah task create ui   &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/ui/**"&lt;/span&gt;   &lt;span class="nt"&gt;--executor&lt;/span&gt; claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. File locks checked &lt;em&gt;before&lt;/em&gt; agents start&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruah task create utils &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/utils/**"&lt;/span&gt;
&lt;span class="c"&gt;# ERROR: Lock conflict with task 'auth' on src/utils/helpers.ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more discovering conflicts after an agent has been running for 10 minutes. Ruah rejects overlapping file claims at creation time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Smart parallel execution with dependency ordering&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# workflow.md&lt;/span&gt;

backend:
  files: src/api/&lt;span class="ge"&gt;**&lt;/span&gt;
  executor: claude-code
  prompt: "Build REST endpoints for user management"

frontend:
  files: src/ui/&lt;span class="ge"&gt;**&lt;/span&gt;
  executor: claude-code
  parallel: true
  prompt: "Build user profile components"

integration-tests:
  files: tests/&lt;span class="ge"&gt;**&lt;/span&gt;
  depends: [backend, frontend]
  executor: aider
  prompt: "Write integration tests for the user flow"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruah workflow run workflow.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruah builds a DAG, validates there are no cycles, checks for file conflicts, then runs &lt;code&gt;backend&lt;/code&gt; and &lt;code&gt;frontend&lt;/code&gt; in parallel. &lt;code&gt;integration-tests&lt;/code&gt; waits until both are done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Contract enforcement before merge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tasks can declare modification contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;owned&lt;/code&gt; — only this task touches these files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shared-append&lt;/code&gt; — append only, no deletions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;read-only&lt;/code&gt; — hands off&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Violations are caught &lt;em&gt;before&lt;/em&gt; merge, not after.&lt;/p&gt;

&lt;h2&gt;
  
  
  It Works With Everything
&lt;/h2&gt;

&lt;p&gt;Ruah isn't tied to one AI tool. It ships with executor adapters for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Executor&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude-code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Claude Code CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aider&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;codex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OpenAI Codex CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;script&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any shell command&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Mix and match. Use Claude Code for complex architecture and Aider for quick edits. Ruah doesn't care — it manages workspaces, not agents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruah task create backend &lt;span class="nt"&gt;--executor&lt;/span&gt; claude-code &lt;span class="nt"&gt;--prompt&lt;/span&gt; &lt;span class="s2"&gt;"Design the auth system"&lt;/span&gt;
ruah task create docs    &lt;span class="nt"&gt;--executor&lt;/span&gt; aider        &lt;span class="nt"&gt;--prompt&lt;/span&gt; &lt;span class="s2"&gt;"Write API documentation"&lt;/span&gt;
ruah task create tests   &lt;span class="nt"&gt;--executor&lt;/span&gt; codex        &lt;span class="nt"&gt;--prompt&lt;/span&gt; &lt;span class="s2"&gt;"Add unit test coverage"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The 5-Minute Version
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ruah-dev/orch

&lt;span class="c"&gt;# Initialize in your repo&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
ruah init

&lt;span class="c"&gt;# Create parallel tasks with file isolation&lt;/span&gt;
ruah task create auth    &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/auth/**"&lt;/span&gt;    &lt;span class="nt"&gt;--executor&lt;/span&gt; claude-code
ruah task create payments &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/payments/**"&lt;/span&gt; &lt;span class="nt"&gt;--executor&lt;/span&gt; claude-code

&lt;span class="c"&gt;# Start them (each gets its own worktree)&lt;/span&gt;
ruah task start auth
ruah task start payments

&lt;span class="c"&gt;# When done, merge cleanly&lt;/span&gt;
ruah task &lt;span class="k"&gt;done &lt;/span&gt;auth
ruah task merge auth

ruah task &lt;span class="k"&gt;done &lt;/span&gt;payments
ruah task merge payments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Two agents, working in parallel, zero collisions, clean merges.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens Under the Hood
&lt;/h2&gt;

&lt;p&gt;When you run &lt;code&gt;ruah task start auth&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Worktree created&lt;/strong&gt; — A real Git worktree at &lt;code&gt;.ruah/worktrees/auth/&lt;/code&gt;, branched from your current HEAD&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Locks acquired&lt;/strong&gt; — &lt;code&gt;src/auth/**&lt;/code&gt; is claimed. No other task can touch these files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment injected&lt;/strong&gt; — The agent receives &lt;code&gt;RUAH_TASK&lt;/code&gt;, &lt;code&gt;RUAH_WORKTREE&lt;/code&gt;, &lt;code&gt;RUAH_FILES&lt;/code&gt;, &lt;code&gt;RUAH_ROOT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Executor launched&lt;/strong&gt; — Claude Code (or Aider, or your script) starts in the isolated worktree&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifacts captured&lt;/strong&gt; — Changed files, patches, and commit metadata are persisted to &lt;code&gt;.ruah/state.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you &lt;code&gt;ruah task merge auth&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Contracts validated&lt;/strong&gt; — Did the agent stay within its file boundaries?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance gates run&lt;/strong&gt; — If you have quality gates (linting, tests, type checking), they run automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean merge&lt;/strong&gt; — Changes merge into your base branch. No surprises.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Subtasks: Agents Spawning Agents
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. A parent task can spawn child tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruah task create auth-api &lt;span class="nt"&gt;--parent&lt;/span&gt; auth &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/auth/api/**"&lt;/span&gt;
ruah task create auth-ui  &lt;span class="nt"&gt;--parent&lt;/span&gt; auth &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="s2"&gt;"src/auth/ui/**"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Children branch from the parent (not main), inherit its context, and merge back into the parent. The parent then merges into main. It's turtles all the way down — but organized turtles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero Dependencies. Zero Network. Zero Risk.
&lt;/h2&gt;

&lt;p&gt;Ruah has &lt;strong&gt;zero runtime dependencies&lt;/strong&gt;. The &lt;code&gt;node_modules&lt;/code&gt; after install? Just dev tools. The binary is pure TypeScript compiled to ESM.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No network calls (unless you explicitly opt into update checks)&lt;/li&gt;
&lt;li&gt;No secrets stored&lt;/li&gt;
&lt;li&gt;No shell injection risk (array-form process spawning)&lt;/li&gt;
&lt;li&gt;MIT licensed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your code never leaves your machine. Ruah just manages workspaces and state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in Safety Net
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Health check everything&lt;/span&gt;
ruah doctor

&lt;span class="c"&gt;# See what's running&lt;/span&gt;
ruah status

&lt;span class="c"&gt;# Clean up stale tasks and orphaned worktrees&lt;/span&gt;
ruah clean

&lt;span class="c"&gt;# Preview a workflow without executing&lt;/span&gt;
ruah workflow run plan.md &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When Should You Use This?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use Ruah when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're splitting features across multiple AI agents&lt;/li&gt;
&lt;li&gt;You want parallelism without merge hell&lt;/li&gt;
&lt;li&gt;You use more than one AI coding tool&lt;/li&gt;
&lt;li&gt;Your team has AI agents running on shared repos&lt;/li&gt;
&lt;li&gt;You're building agentic workflows that decompose tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't use Ruah when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're running a single agent on a single task (just use the agent directly)&lt;/li&gt;
&lt;li&gt;Your changes are all in one file (no isolation needed)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Ruah Orch is Phase 1. The orchestration layer. Coming next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ruah Architect&lt;/strong&gt; — Feed it a PRD or GitHub issue, get a parallelized workflow back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruah Guard&lt;/strong&gt; — Policy engine for what agents can and can't do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruah Observe&lt;/strong&gt; — Tracing and observability for multi-agent runs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruah Studio&lt;/strong&gt; — Visual UI for watching agents work in real-time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But Orch is shipping now, it's stable, and it solves the #1 pain point: &lt;strong&gt;agents that don't step on each other.&lt;/strong&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ruah-dev/orch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/ruah-dev/ruah-orch" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://www.npmjs.com/package/@ruah-dev/orch" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've felt the pain of merging parallel AI agent work, give it a try. Stars welcome. Issues more welcome. PRs most welcome.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried running multiple AI agents in parallel? What was your experience? Drop a comment — I'd love to hear your war stories.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
