Scan texture
Scan texture

Your Monorepo Already Has the Logic. Give Agents Access to It.

JS monorepos are full of rich client logic — validated types, generated API clients, cascading write sequences. Node.js SEA is the turnkey way to package that logic into agent skills without rewriting a line of it.

Published On

Sat Apr 11 2026

0
/
0

When people talk about building tools for AI agents, the conversation usually drifts toward Go pretty quickly. Single binary, zero runtime dependencies, ships anywhere. That's a real advantage, and it's why Go has become a popular target for CLI tooling. But there's a question that rarely gets asked before the rewrite begins: what are you actually losing by leaving JavaScript?

If you're working in a TypeScript monorepo, the answer is a lot. Your application layer has already done the hard work. It has types that map exactly to your API's wire format. It has generated gRPC clients that know how to talk to your services. It has validation logic derived from those same types, guaranteed to match what your backend actually accepts. It has write sequences that handle the stateful parts — create a parent resource, capture the DB-generated ID, cascade it into the dependent records — because a human engineer already had to figure out what order those calls need to happen in. All of that exists. It's just not accessible to an agent.

The problem isn't the logic. The problem is delivery.

Agents need commands, not libraries

An agent doesn't import your SDK. It runs commands. The interface between an agent and a tool is a binary path, a set of flags, and whatever comes back on stdout. That's the entire contract. Everything useful your monorepo knows about how to interact with your platform has to fit through that interface to be useful to an agent at all.

This is why the Go instinct exists. A Go binary satisfies the contract immediately — one file, no setup, call it from anywhere. The frustration is that you then have to rebuild all the logic that was already written in TypeScript. The generated clients, the validation, the cascading write sequences — you're rewriting them in a language that doesn't have the same ecosystem your application was built with, against a backend that was designed around the generated types you're leaving behind. You get the delivery mechanism but lose everything that made the logic correct.

Node.js Single Executable Applications close that gap. They let you take a TypeScript CLI from inside your monorepo, bundle it with all its dependencies, and ship it as a single hermetic binary that an agent can call with no installation, no node_modules, no auxiliary files. You keep the logic. You just change how it gets delivered.

What this actually unlocks

The pattern becomes compelling once you think about the categories of things an agent skill can do once it has real access to your application layer.

Search across platform data. A CLI that bundles your search client, knows your data schemas, and can surface relevant records in response to a natural language query gives an agent a retrieval capability that's genuinely grounded in your platform's own data. Not a generic vector search — a search that understands what your records actually look like and can return results in a format the agent already knows how to work with.

Validation against the real schema. When an agent is about to write something, the difference between validating against a schema that was generated from your actual TypeScript types and validating against something the agent inferred is significant. One is guaranteed to match what your API will accept. The other is a guess. A CLI that embeds your JSON Schema — generated at build time from the same types your application uses — gives the agent a validation contract it can rely on before the network call ever happens.

Multi-step CRUD with complex client logic abstracted away. This is the one that's hardest to replicate without the original code. Creating a resource in a real system isn't usually one POST. There's a sequence: create the parent, get the ID back, use that ID in the next call, handle the conditional branches depending on what came back. That logic exists somewhere in your application already. A CLI command that wraps the whole sequence — my-cli dashboard create --config dashboard.json — means the agent doesn't have to reason through the HTTP choreography. It issues one command and gets a result. The complexity lives in the binary, where it was already tested and understood.

The monorepo is the moat

There's a broader point here about where value lives in a software system. The generated types, the gRPC clients, the validated schema — none of these came for free. They were built up over time as your understanding of the domain matured. They encode decisions about what data looks like, what operations are valid, and what order things need to happen in. That's not documentation. It's executable knowledge.

Packaging it as an agent skill is a way of making that knowledge accessible to a new kind of consumer without giving up the source of truth. The binary is built from the monorepo. It's version-locked to the state of the code at build time. When the schema changes, you cut a new binary. The agent always operates against a known, stable contract.

The alternative — describing your API in a system prompt and hoping the agent constructs valid requests from natural language — works until it doesn't. Validation errors are opaque, the agent retries with variations, and the gap between what the agent thinks the API accepts and what it actually accepts widens over time. Giving the agent a binary that already knows the answer is a fundamentally different approach.

JavaScript is the right language for this

There's a temptation to treat the need for a hermetic binary as evidence that you should have used a different language. I'd argue the opposite. If your platform is built around a TypeScript monorepo, JavaScript is exactly the right language for the tools that need to understand it deeply. The generated types, the shared validators, the API clients — these are JavaScript artifacts. Reaching them from Go means either duplicating them or calling back into JavaScript anyway.

Node.js SEA turns the language choice from a distribution liability into a non-issue. The binary is self-contained. The Node runtime is bundled. The dependency graph is resolved at build time and locked into the blob. From the agent's perspective, it's indistinguishable from a Go binary — one file, zero setup, predictable behavior.

The rewrite is the longer path. The SEA build is the shorter one, and it preserves everything your application layer already got right.

More writing

Recent posts.

Notes on engineering, design, and building products.

ai

Packaging a Monorepo CLI as a Node.js SEA for Agent Skills

How to turn a TypeScript CLI with deep monorepo dependencies into a single hermetic binary an AI agent can call with zero setup — using Node.js Single Executable Applications.

ai

Your Monorepo Already Has the Logic. Give Agents Access to It.

JS monorepos are full of rich client logic — validated types, generated API clients, cascading write sequences. Node.js SEA is the turnkey way to package that logic into agent skills without rewriting a line of it.

ai

CLIs Are for Robots, IDEs Are for Humans

A mental model for agentic coding workflows: where machines execute, where humans judge, and why keeping that distinction sharp makes everything work better.

ai

A Practical Pattern for Hydrating AI-Generated Object Templates

How I hydrate server-side LLM templates with client constants and API data using a queue-based pattern.

flutter

Stateless Classes Are Better: A Lesson from Flutter

Stop storing state in your classes. Localize it via providers, minimize your bug surface area, and write code that's actually testable.

data-visualization

Treat Your Chart Like MVVM: Client-Side ETL for Better Visualizations

Learn how to build better data visualizations by treating charts like MVVM components with proper client-side ETL pipelines. Stop fighting your charting libraries and start feeding them clean, predictable data.

typescript

Caching Isn’t a SaaS Product, It’s a Data Structure

The industry won’t tell you this, but a hashmap does 90% of what you need

typescript

The Ultimate Tool for Managing Types in Monorepos

gRPC Is the Secret Weapon Your Monorepo Desperately Needs

typescript

Divide and Conquer Timeline Data with Typescript

Typescript time series and Date objects

ai

The Growing Importance of SMEs in AI Agent Design

AI agents are revolutionizing industries, but here's why they still need us more than ever

engineering-culture

The Myth of the “Universal Language” for Internal Tool Development

We've all heard this story before. You finally get buy-in to build a tool that solves your pet peeve. You have a plan figured out, but then your manager says the dreaded phrase, “Use a different language so that others can contribute”… which seldom happens.

react

The Performant Interface Dilemma: Taming Object Equality in React

A comprehensive guide for developers on handling object equality issues in JavaScript, with a focus on practical solutions for React applications

startup

Will My Startup's Problem Be Big Enough?

How to evaluate the potential of a startup idea by understanding your Serviceable Obtainable Market, the Venn diagram of opportunity

ux

UX Meets Database Design, a Match Made in Heaven

Putting UX at the heart of user-centric SQL schema data modeling

ai

I Stuffed TensorFlow.js Into a React App

Here's what I learned about Web Workers

ux-research

Social Distanced UX Research Strategies For your Next iOS App

COIVD forced us to stop using in-person UX research. Here are some tried and true methods we're keeping after the lockdowns lift

flutter

How to Deploy Flutter for Web Apps with Netlify

Have you ever wanted to turn your iPad or iPhone app into a website?

All posts →