BLOG/DEVELOPER DAILY
THEME
DEVELOPER DAILY

Tame your monorepo scripts

Every package has its own build, lint, and dev commands, and the root package.json has thirty scripts nobody can keep straight. Give the monorepo one entry point with per-package tasks and task calls.

Jun 15, 2026 OrchStep Team 6 minROLE: Frontend DeveloperSCALE: Any
RUNNABLE DEMO
Full source for this post: blog/monorepo-tasks
VIEW SOURCE

Open the root package.json of any monorepo that's been alive for a year. There are thirty scripts: build:web, build:ui, build:api, dev:web, test:ui, lint:all, and a build that's just npm run build:ui && npm run build:web && npm run build:api with the order memorized by exactly one person. New teammates run the wrong one, forget the build order, and learn the dependency graph by breaking it.

The scripts aren't the problem. The problem is that the relationships between them — this builds before that, this is the one you actually run — live in a flat list of strings with no structure.

OrchStep gives you per-package tasks and lets one task call another. The build order stops being tribal knowledge and becomes the workflow.

One entry point, tasks underneath

Each package gets a task. One top-level build task calls them in the right order. That's the whole pattern:

orchstep.yml
name: monorepo
defaults:
  mode: dev

tasks:
  # `orchstep run ui`
  ui:
    steps:
      - name: build-ui
        func: shell
        do: echo "pnpm --filter ui build"

  # `orchstep run web`
  web:
    steps:
      - name: build-web
        func: shell
        do: echo "pnpm --filter web build"

  # `orchstep run api`
  api:
    steps:
      - name: build-api
        func: shell
        do: echo "pnpm --filter api build"

  # `orchstep run build` — the single entry point newcomers learn.
  build:
    steps:
      - name: shared-ui
        task: ui
      - name: frontend
        task: web
      - name: backend
        task: api
      - name: done
        func: shell
        do: echo "all packages built ({{ vars.mode }})"

The task: field is the key move. build doesn't repeat the ui commands — it calls the ui task. The shared library builds before the apps because the steps are ordered, not because someone remembered. Need to build just one package? Run it directly. Need everything? Run build.

Run it

orchstep run build

One command, the right order, every time. The shared ui package builds first, then web and api. When ui changes its build command, you change it in one place — web and api keep calling the same task.

Don't remember the task name?

Thirty scripts in a package.json means npm run and squinting. Here you press a key:

orchstep menu

A fuzzy task picker with single-key hotkeys lists every package task. New teammates discover the whole build surface without reading a wiki — and because the picker refuses to hang in a pipeline, the same tasks are safe to call from CI.

What you actually gained

Concernthirty package.json scriptsOrchStep
Build ordermemorized && chainordered task: calls
Reusecopy the command stringcall the package task
One entry pointa build script that lists alla build task that calls each
Discoverabilitynpm run and guessorchstep menu
Per-package runnpm run build:weborchstep run web

This doesn't replace pnpm, turbo, or your bundler — they still do the building. OrchStep gives the orchestration a shape, so the build graph is something you read instead of something you memorize. If turbo run build with a tuned pipeline already does this for you, keep it. When your orchestration is a wall of &&, this is the upgrade.

Where to go next

Got a package.json with thirty scripts and a memorized build order? Give the monorepo one entry point and let the task calls hold the graph.

#MONOREPO#FRONTEND#TASK-RUNNER#PRODUCTIVITY
Try it in two minutes — one binary, no signup.
curl -fsSL https://orchstep.dev/install.sh | sh

RELATED — DEVELOPER DAILY