# What is ivar
> The idea behind ivar — a hall of real git worktrees, one view directory per feature, and one agent session across every repo a change touches.
Source: https://ivar.run/docs/what-is-ivar

import { Callout } from 'fumadocs-ui/components/callout';
import { Card, Cards } from 'fumadocs-ui/components/card';
import { File, Files, Folder } from 'fumadocs-ui/components/files';

Your team already works in a monorepo. It just isn't one repo.

## The problem

A contract lives in `api`. Its client lives in `web`. It is one change — but git
sees two repositories, and your agent sees one of them.

So the work splits. You describe the contract change to an agent in one repo,
then describe it again, from memory, in the other. The half that knows what
changed cannot see the half that has to follow. Every review, every rebase and
every rollback then has to reconstruct a connection that was never written down.

`ivar` closes that gap without merging the repos: it mounts every repo the
change touches into a single directory, on a single branch, and opens one agent
session over all of them.

`ivar` is a binary your harness runs as a subprocess — it has no MCP server
yet. An agent reaches it the way it reaches `git`: by running the command and
reading the output, not by calling a tool.

## The hall

A **hall** is a directory that owns a set of repos, described by a committed
`ivar.json`:

```json title="ivar.json"
{
  "name": "acme",
  "providers": {
    "available": ["claude-code", "opencode"],
    "default": "claude-code"
  },
  "repos": [
    { "name": "api", "url": "https://github.com/acme/api", "default_branch": "main" },
    { "name": "web", "url": "https://github.com/acme/web", "default_branch": "main" }
  ],
  "version": 1
}
```

That file is the whole contract. Clone the hall, run `ivar sync`, and you have
the same repos on the same branches as everyone else — the command clones what
is missing, materialises harness config, and runs each repo's setup script.

```sh
git clone git@github.com:acme/hall.git && cd hall
ivar sync
```

Onboarding stops being a document that drifts out of date, because it is the
manifest the tool actually reads.

### On disk

Each repo gets exactly one bare clone. Every working copy — the default branch
included — is a git worktree cut from that clone.

<Files>
  <Folder name="acme-hall" defaultOpen>
    <File name="ivar.json" />
    <Folder name=".ivar" defaultOpen>
      <Folder name="repos" defaultOpen>
        <Folder name="api" defaultOpen>
          <File name=".bare" />
          <File name="main" />
          <File name="feat--billing-currency" />
        </Folder>
        <Folder name="web" />
      </Folder>
      <Folder name="features" />
      <Folder name="sessions" />
      <Folder name="skills" />
      <Folder name="setups" />
    </Folder>
  </Folder>
</Files>

<Callout title="No copies, no sync step">
  A change under the hall *is* a change in that repository — these are real
  worktrees, not mirrors. Nothing is duplicated, and there is no second command
  to remember before your edit counts.
</Callout>

## The feature

A **feature** is a name, a branch, and the set of repos that branch exists in.
Creating one records the name and the branch, and claims no repos yet:

```sh
ivar feature create billing-currency
```

Repos join it one at a time. Each promotion cuts the feature's branch in that
repo and materialises its worktree; a branch that already exists is adopted as
it is, one that does not is created off the repo's base.

```sh
ivar feature promote billing-currency api
ivar feature promote billing-currency web
```

Everything you did not promote stays on its default branch. Scope is rarely
right the first time, and that is the point: promote the repo you turn out to
need, demote the one that turned out not to belong.

```sh
ivar feature demote billing-currency infra
```

## The view directory

Starting a session materialises a **view directory**: the feature's repos
mounted at its root, all on the same branch, plus the agent config for the
harness you opened it in.

<Files>
  <Folder name="billing-currency" defaultOpen>
    <Folder name="api" defaultOpen>
      <File name="openapi.json" />
    </Folder>
    <Folder name="web" defaultOpen>
      <File name="src/api/billing.ts" />
    </Folder>
    <Folder name="shared — read-only" />
    <Folder name="infra — read-only" />
  </Folder>
</Files>

The agent edits `api/openapi.json` and then `web/src/api/billing.ts` in the same
session, reading the first to write the second. No handoff, no re-explaining.

## The guard

Repos you have not promoted have their write bits cleared — `mode & ~0o222`,
applied recursively. The kernel refuses the write.

That is the point: a prompt asking an agent not to touch `shared` works until it
does not. A cleared write bit does not depend on the model's cooperation. The
harness hook only explains how to promote the repo if you decide it belongs in
the feature after all.

## Skills and context

Repo skills keep their origin in their name, so two repos can each ship an
`openapi-contract` skill without one silently shadowing the other:

```
api--openapi-contract
web--openapi-contract
```

Hall skills mount flat and apply to the whole session. `ivar skill` installs
them from git, updates them to a tracked ref, and materialises them into each
harness's native location — so the same skill set follows you across harnesses
instead of being re-installed per tool.

## Delivery

`ivar feature deliver` pushes each promoted worktree and opens a pull request in
its own repo, then links them to each other — the URLs only exist once the pull
requests do. `--preview` prints the whole side-effect-free summary first and
pushes nothing.

The link reads **part of**, not *depends on*. `ivar` models co-belonging, not
dependency: it will not sequence your merges or decide whether the client can
land before the contract. Reviewers make that call; they just stop having to
reconstruct which changes belonged together.

## Sessions are not owned by one vendor

Nothing in the view directory belongs to a particular agent. The worktrees are
git, the manifest is JSON, the skills are folders of Markdown. A session relays
to another harness with the same branch and the same context, and nothing is
uploaded to do it.

```sh
ivar session relay billing-currency --provider opencode
```

Every command also takes `--json`, printing exactly the value it computed — the
human-readable output is a rendering of that same value, so a script and a
person can never be told different things.

## What ivar is not

- **Not a monorepo migration.** Your repos stay separate, with their own
  history, CI and pull requests.
- **Not a build system.** It does not model a task graph or cache builds; Nx and
  Turborepo do that, and they do it better.
- **Not a service.** A single Rust binary, local-only — it never talks to a
  server, and nothing is uploaded. That is a property of the architecture, not a
  policy.
- **Not tied to one agent.** Nothing in the view directory belongs to a vendor;
  the same worktrees, branch and context relay to another harness.
- **Not a merge queue.** It records that changes belong together and stops
  there.

## Where next

<Cards>
  <Card
    title="Quickstart"
    description="Install ivar, create a hall, and open your first discovery session."
    href="/docs/quickstart"
  />
  <Card
    title="Guide"
    description="The workflow you run from your harness, from discovery through delivery."
    href="/docs/guide/sessions"
  />
  <Card
    title="CLI reference"
    description="Every ivar command, for when you want to run one yourself."
    href="/docs/reference/cli"
  />
</Cards>
