---
title: "Monorepos"
description: "Run several MainSDK apps in one repository with a shared main.workspace.yaml, one main.lock, and mainsdk check only on what a change touches."
section: "guides"
status: "Planned for 0.7"
spec: "monorepos"
canonical: "https://mainsdk.dev/docs/guides/monorepos"
updated: "2026-10-28"
---

# Monorepos

> Run several MainSDK apps in one repository with a shared main.workspace.yaml, one main.lock, and mainsdk check only on what a change touches.

Status: Planned for 0.7 · Canonical: https://mainsdk.dev/docs/guides/monorepos · Updated: 2026-10-28

Share policies, drivers and overlays across several apps in one repository, and check only what a change touches. Each app keeps its own `main.yaml`; one optional `main.workspace.yaml` at the root holds what they share. It is configuration only and adds no runtime code to your bundles.

> **Note:** Monorepo support ships in phase 2, milestone 0.7. In phase 1, `main.workspace.yaml` is read as a file with inheritance only; per-package `check` and `sync` come in 0.7.

**Before you start:** a pnpm, npm or Yarn workspace, or a Turborepo or Nx repo, with at least one app that has a `main.yaml`.

## 1. Add the workspace file

```text
pinecart/
  main.workspace.yaml     # shared policies, drivers, overlays
  main.lock               # one per workspace
  policies/
  apps/web/main.yaml      # Pinecart web app, Next.js
  apps/api/main.yaml      # Hono API
  packages/ui/
```

```yaml title="main.workspace.yaml"
schema: 1
packages: auto                 # from pnpm, npm or Yarn workspaces, Turborepo or Nx
policies: [policies/]
providers: { email: resend }
overlays: { order: [market, segment, env] }
network: { default: deny, allow: ["*.pinecart.dev"] }
```

```yaml title="apps/web/main.yaml"
schema: 1
project: prj_01JC8Q4W7ZK3M5N8P2R6T9V0XY
baseline: main27
targets: { web: { framework: nextjs } }
auth: { driver: github }
```

The web app inherits `providers.email: resend`, the policies and the network list. Packages are discovered from pnpm, npm and Yarn workspaces, Turborepo and Nx. Inheritance runs org, workspace, app, overlays; see [main.yaml and overlays](https://mainsdk.dev/docs/concepts/main-yaml).

## 2. Tighten, never weaken

An app may tighten what the workspace sets. Weakening it needs an exception with an owner and an expiry.

```yaml title="apps/api/main.yaml"
network: { default: allow }    # weakens the workspace
exceptions:
  - rule: net.default_deny
    reason: Partner VPN gateway until the move to a fixed host
    owner: "@pinecart/platform"
    expires: 2026-11-30
```

Without the exception, `check` fails and names the weakened key. An expired exception fails like no exception.

## 3. Verify where each value comes from

```bash
npx mainsdk explain config --package apps/web
```

```text
$ npx mainsdk explain config --package apps/web
schema = 1  (apps/web/main.yaml:1)
packages = auto  (main.workspace.yaml:2)
providers.email = resend  (main.workspace.yaml:4)
network.default = deny  (main.workspace.yaml:6)
project = web  (apps/web/main.yaml:2)
auth.driver = github  (apps/web/main.yaml:5)
```

Each value names the file and line it came from. Add `--json` for tools.

## 4. Check only what changed

```bash
npx mainsdk check --affected --base origin/develop
```

`--affected` checks the packages a change touches, the packages that depend on them, and every app when `main.workspace.yaml` or `main.lock` changes. Use `--package apps/web` for one app or `--all` for everything. `sync` takes the same flags.

```yaml title=".github/workflows/mainsdk.yml"
name: mainsdk
on: [pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: pnpm/action-setup@v4
      - run: pnpm install --frozen-lockfile
      - run: pnpm mainsdk check --affected --base origin/develop
```

## 5. Keep one lock for every app

```bash
npx mainsdk sync --all
```

`mainsdk sync --all` writes one `main.lock` at the root, so every app resolves the same contract versions, with hashes. No app folder has its own lock.

```yaml title="main.lock"
lock: 1
interfaces:
  email: { range: "^1.2", resolved: "1.4.0" }
drivers:
  resend:
    version: 2.3.1
    implements: ["email@^1.2"]
    sha256: "9f2c…"
```

Org-wide defaults for repos outside this workspace live in `main.org.yaml`.

## Next

- [main.yaml and overlays](https://mainsdk.dev/docs/concepts/main-yaml)
- [main.yaml reference](https://mainsdk.dev/docs/reference/main-yaml)
- [CLI reference](https://mainsdk.dev/docs/reference/cli)
