# Shell scripts are the highest-ROI layer under your AI skills


# Shell scripts are the highest-ROI layer under your AI skills

*The glamorous layer is the agent. The load-bearing one is the boring shell script underneath — and that's where most of your reliability actually lives.*

---

The highest-leverage code I shipped this month wasn't a prompt. It wasn't an agent. It was a handful of boring shell scripts.

They sit under [my second brain](https://blog.deepakgoyal.ai/stopped-being-my-second-brains-scheduler) — the system I wrote about recently, the one that stopped needing me to schedule it. That post was about what the automation *does*. This one is about the part that actually carries it, which I glossed over at the time: not the AI. The scripts.

## The two kinds of work in every AI system

Every AI automation is really doing two different jobs, and we tend to blur them.

One is **judgment**: decide which thing matters, draft the reply, synthesize the week into a paragraph. That needs a model — it's taste, not logic.

The other is **deterministic**: fetch the data, parse it, dedupe it, mutate a file, check a condition. That needs no brain at all. And yet the reflex, once you have a capable model in the loop, is to hand it that work too — because it *can* do it. It can. It'll also cost you tokens and hand back a slightly different answer every run.

The move that keeps earning its keep is dull to state and hard to remember: **push everything deterministic down into a script, and spend the model only on the judgment.**

## What the split actually looks like

I built a small system that surfaces conversations worth joining — a morning shortlist of threads where I genuinely have something to add. It has exactly two layers.

A **shell script** does the deterministic half: hit the API, pull candidate threads, keyword-match them against my areas, drop anything I've seen before. Some JSON parsing, a `grep`, a dedupe set. Nothing in there wants a brain.

An **agent** does the judgment half: read those candidates, pick the few I can actually help with, and draft a reply in my voice.

If I'd let the model do the fetching and filtering too, I'd be paying tokens to do a job `grep` does perfectly — and getting a slightly different shortlist each morning. Instead the mechanical part is fixed, fast, and free, and the model spends its whole budget on the part that's genuinely a decision.

## A script that breaks tells you it broke

Here's the part that settled it for me.

The morning after I wired it up, the shortlist came back empty. My instinct was to distrust the whole thing. But because the fetch layer is a *script*, I could ask it exactly what happened in one line:

```
curl -s -o /dev/null -w "%{http_code}\n" https://…
→ 403
```

The free API had started refusing unauthenticated requests. Thirty seconds to diagnose, because the failure was a *number*, not a mood.

Now put that same fetch inside a model loop. It hits the same wall — and then does what models do: smooths over the gap, returns a plausible empty result, and I trust it. Deterministic systems fail loudly and specifically. Probabilistic ones fail quietly and expensively. A script that breaks tells you it broke; that is worth far more than it sounds.

## The cheapest guardrail I own is a grep

One more, because it's my favourite.

I keep a public, open-source version of my system, built by copying pieces out of my private one and stripping the private bits. A single leaked name or path in a public repo is the sort of mistake you can't quietly undo. So before I tag a release, a script greps the staged files for anything private — names, absolute paths, tokens — and exits non-zero if it finds one. A spellcheck for secrets. Zero tokens, runs in a second, and it *cannot have an off day*.

I could ask a model, "is anything private in here?" It would be slower, cost tokens, and — the part that matters — it could miss *differently* each time. The grep can only catch what's on its list, too; it's not magic. But it catches those every single time, and the day something slips through a new pattern, I add one line and it's caught on every release after. That's the trade I want in a safety gate: it fails the same way twice, so I only have to fix it once.

## Why it's the highest ROI, not just the cheapest

It's tempting to say the win is cost, and it is. But cost is the bonus. The reason is three properties you get from code and cannot get from a model: it's **reliable** (same input, same output, forever — no drift, no temperature), it's **testable** (you can unit-test a script; you cannot unit-test a vibe), and it **fails visibly** (an exit code, not a confident wrong answer). Write it once, run it every morning, at zero marginal cost. That's the curve you want underneath the expensive, probabilistic layer — not on top of it.

## Where the line sits — and it cuts both ways

The skill isn't "script everything." It's knowing where the boundary is.

Fetching, parsing, deduping, mutating files, checking a condition — that's below the line, and it belongs in a script. Deciding which thread deserves your voice, drafting the reply, reading a messy week and calling the theme — that's above it, and it belongs to the model.

Push the line as far toward *script* as the work honestly allows, and not one step past. Script the judgment and you get brittle rules that shatter on the first case you didn't foresee. Hand determinism to the model and you get expensive nondeterminism. They're the same mistake, pointed in opposite directions.

## The load-bearing layer

The layer that ends up in the demo is the agent. The layer that keeps the thing standing is the script underneath it — and a surprising amount of your reliability lives down there, unglamorous and unmentioned.

If you're building anything with AI this week, the highest-leverage hour probably isn't a sharper prompt. It's taking one deterministic thing your model is quietly doing, and moving it into a small, dull script that will never surprise you.

Let the model do the thinking. Everything else is a job for something that shows up, does the boring thing the same way every time, and tells you plainly when it can't.

