Skip to Content
ScriptingMonorepos

Monorepos

Miso has first-class support for monorepos. When configured, you can run workspace-scoped scripts using the @workspace/script syntax, and Miso will automatically scope commands based on your current directory.

Setup

1. Add "repo": "mono" to miso.json:

>miso.json
{ "repo": "mono" }

2. Add a workspaces field to your root package.json:

>package.json
{ "name": "my-monorepo", "packageManager": "pnpm", "workspaces": [ "apps/*", "packages/*" ] }

The workspaces field uses standard glob patterns and is compatible with npm, yarn, pnpm, and bun — no extra tooling required.

Workspace Scripts

Each workspace can have its own scripts/ folder. Miso discovers and executes scripts from the correct workspace, and sets the working directory to that workspace’s root so all relative paths resolve correctly.

Folder Structure

my-monorepo/ ├── miso.json ├── package.json ├── scripts/ ← root-level scripts │ └── build.sh ├── apps/ │ ├── api/ │ │ └── scripts/ ← workspace-scoped scripts │ │ ├── build.sh │ │ └── deploy.sh │ └── web/ │ └── scripts/ │ ├── build.sh │ └── dev.sh └── packages/ └── ui/ └── scripts/ └── build.sh

Running Workspace Scripts

From the Root — @workspace/script Syntax

Target any workspace’s scripts from the project root using the @workspace/script syntax:

miso @api/build # runs apps/api/scripts/build.sh miso @web/dev # runs apps/web/scripts/dev.sh miso @ui/build # runs packages/ui/scripts/build.sh

The workspace identifier is the part between @ and the final /. By default this is the basename of the workspace directory — for example, apps/apiapi, packages/uiui.

From Inside a Workspace — Automatic Scoping

When you’re already inside a workspace directory, Miso automatically scopes to that workspace. No special syntax needed:

cd apps/api miso build # resolves to apps/api/scripts/build.sh miso deploy # resolves to apps/api/scripts/deploy.sh

This matches the same behaviour you’d expect from tools like Turborepo’s automatic package scoping.

How Workspace Matching Works

The identifier in @identifier/script is matched against every discovered workspace using three strategies, checked in order:

  1. Basename — the final segment of the workspace directory path (e.g. api matches packages/api)
  2. Relative path from root — the full path from the repo root (e.g. packages/api matches packages/api)
  3. package.json name — the name field in the workspace’s package.json (e.g. @myorg/api)

So for a workspace at packages/api with "name": "@myorg/api" in its package.json, all three of the following are equivalent:

miso @api/build # matched by basename miso @packages/api/build # matched by relative path miso @myorg/api/build # matched by package.json name

If the identifier matches more than one workspace, Miso exits with an error listing the conflicting paths so you can use a more specific form:

workspace "api" is ambiguous — matches multiple workspaces: apps/api, packages/api (use a more specific identifier)

If no workspace matches, Miso exits with an error listing the available workspace names:

workspace "typo" not found (available: api, web, ui)
Last updated on