---
summary: "Running multiple Bridge instances for data isolation across organizations — shared CORE upstream, separate USER data per instance."
type: guide
last_updated: 2026-06-21
related:
  - docs/structure.md
  - docs/extension-model.md
---

# Multi-Instance Setup

Run multiple Bridge instances when you work across organizations that
require data isolation. Each instance shares the same CORE upstream but
keeps its own user data separate.

## When You Need This

- You work for **multiple organizations** and their project data must not
  mix in git history
- One organization uses GitHub, another uses Azure DevOps or GitLab
- Client contracts or compliance rules prohibit storing metadata (ticket
  IDs, team names, infrastructure URLs) on external git remotes
- You want some instances pushed to a remote and others kept local-only

> **Note:** This instance uses the cluster-wrapper layout
> (`identity/`, `infra/`, `workflow/`). Other instances may stay on
> the older layout — see [`CLAUDE.md`](../CLAUDE.md) section
> "Layout — Cluster-Wrappers".

> **Related but not identical:** Multi-instance describes
> **several Bridges side by side**, all pulling from the same upstream.
> The tier model (see CLAUDE.md § Tier Model) has a different focus:
> **one** Bridge with *two* upstreams (open-bridge = OSS layer,
> `<your-org>/<your-bridge>` = your org overlay) and a multi-upstream
> promote flow (`/promote` routes `scope:core` to open-bridge,
> `scope:org` to your org overlay). Multi-instance stays orthogonal — you can still run
> multiple Bridge clones side by side after adopting the tier model.

A single Bridge instance with multiple `workflow/contexts/<id>.yaml` files is sufficient when all
projects belong to the same organization or share the same data
classification. Multi-instance is for **cross-organization isolation**.

## Instance Registry

Register every Bridge this hub should be aware of in
`infra/instances/<slug>.yaml` (template + schema:
`infra/instances/_template.yaml` / `_schema.yaml`). The registry maps
where each instance lives, what it's for, and its data/push policy —
**awareness and navigation only**: knowing an instance exists is not a
licence to reach into it. The isolation hard rule
([`rules/multi-instance-isolation.md`](../rules/multi-instance-isolation.md))
still governs: read-only from here, operate each instance in its own
session at its path.

### Subscribing an instance to org overlays

An instance can declare which org overlays it subscribes to with the optional
`subscribes_overlays: [<name>]` field in `infra/instances/<slug>.yaml`. Each name
matches a `role: org-overlay` upstream in that instance's `bridge-config.yaml`,
where the actual `materialize:` block (url / ref / cache / precedence / select)
lives — the instance file only records *which* overlays apply, never the routing.
The separation is **per-URL and structural, not declarative**: an instance with
`subscribes_overlays: []` (or the field omitted) is overlay-incapable — there is
nothing to disable, the engine simply has no work and reports CORE-only. You opt
*in* per overlay by adding its materialize block via `/overlay add`, never out.
This keeps each instance's overlay subscriptions isolated: two instances sharing
the same CORE upstream can subscribe to entirely different org overlays without
their `scope:org` material ever crossing. Full guide:
[`docs/org-overlays.md`](org-overlays.md).

## Architecture

```
Instance 1: ~/work/org-a/open-bridge/    Instance 2: ~/work/org-b/open-bridge/
────────────────────────────────────     ────────────────────────────────────
Pushed → org-a remote (GitHub)           LOCAL ONLY, never pushed
ecosystem: org-a projects                ecosystem: org-b projects
contexts/: client-x/, internal/          contexts/: project-y/
work/: org-a work log                    work/: org-b work log (git-backed!)
Theme: professional-de                   Theme: professional
Agents: custom preset                    Agents: default roles
          ↑                                            ↑
          └───────── shared upstream: main ───────────┘
                     git merge main → same CORE updates
```

Both instances track the same `main` branch as upstream. CORE
updates (new commands, standing orders, templates, docs) flow into both
instances identically. USER data (contexts, work logs, agents,
ecosystem.yaml) is completely independent per instance.

## Setup

### Instance 1 (pushed to your private repo)

A pushed instance must push to a **private repo you own** — never to public
open-bridge. Make a private copy first (GitHub *Use this template → Private*, or
clone + re-home), then onboard:

```bash
git clone https://github.com/bks-lab/open-bridge.git ~/work/org-a/my-bridge
cd ~/work/org-a/my-bridge
git remote rename origin upstream                       # open-bridge = read-only upstream
gh repo create <you>/org-a-bridge --private --source=. --remote=origin --push
claude    # /bridge-onboard runs automatically — writes user data to your private origin
git push -u origin user/your-name                       # safe: origin is YOUR private repo
```

### Instance 2 (local-only)

Clone, configure, but never push the user branch — `origin` stays the public repo,
used read-only:

```bash
git clone https://github.com/bks-lab/open-bridge.git ~/work/org-b/open-bridge
cd ~/work/org-b/open-bridge
claude    # /bridge-onboard — configure for org-b
```

To pull CORE updates without pushing user data:

```bash
cd ~/work/org-b/open-bridge
git fetch origin main
git merge origin/main
# user/ branch stays local — never git push (origin is the PUBLIC repo; the
# pre-push guard blocks it anyway). See rules/push-guard.md.
```

### Fork Variant

If your pushed instance is a fork of the canonical upstream:

```bash
# Instance 1 (fork from open-bridge)
git remote add upstream https://github.com/bks-lab/open-bridge.git

# Instance 2 (also fork, or direct clone)
git remote add upstream https://github.com/bks-lab/open-bridge.git
```

> **Note:** Public OSS upstream is `bks-lab/open-bridge`. Org-internal
> users may set upstream to `<your-org>/<your-bridge>` (a private fork
> that layers org-specific skills on top). See CLAUDE.md
> § Tier Model for the multi-upstream pattern.

Both instances run `git fetch upstream main` + `git merge` for
CORE updates. `/briefing` and `/archive` check upstream automatically
when `upstream.check_interval_days` is set in `bridge-config.yaml`.

## What Each Instance Gets

Every Bridge instance is a full, independent setup:

| Feature | Per instance |
|---------|-------------|
| `ecosystem.yaml` | Own project registry |
| `bridge-config.yaml` | Own theme, language, integrations |
| `workflow/contexts/` | Own project bundles |
| `work/` | Own board, log, tasks, archives |
| `.claude/agents/` | Own agent definitions or preset |
| `protocols/standing-orders/` | Shared CORE + own orders in `standing-orders/user/` |
| `infra/channels/`, `infra/remotes/` | Own messaging + remote machines |
| `identity/mandants/`, `workflow/calendars/` | Own recipients + scheduled actions |

## Data Isolation

The CORE/USER branch split isolates **data**. It does not, by itself, isolate
**capabilities** — that is a separate guarantee with a separate failure mode;
see [Capability Isolation](#capability-isolation) below.

- **USER paths** (bridge-config.yaml, workflow/contexts/, work/, .claude/agents/,
  infra/channels/, infra/remotes/, identity/mandants/, workflow/calendars/) live only on `user/{name}`
- If you never push `user/{name}`, none of that data leaves your machine
- CORE paths (CLAUDE.md, docs/, templates, commands) contain no
  organization-specific data

**What stays local in a local-only instance:**
- Organization names, team member names, project URLs
- Work item IDs, ticket numbers, infrastructure endpoints
- Work logs, task statuses, meeting insights
- Agent customizations with org-specific knowledge

**What is shared via CORE upstream:**
- Command definitions, protocol templates, standing orders
- Theme files, sub-agent definitions, onboarding wizard
- Documentation, examples, schemas

## Capability Isolation

Data isolation answers *"can instance B read instance A's files?"*. Capability
isolation answers a different question: *"whose skills actually run inside
instance B's sessions?"* — and the branch split does not answer it, because
skills are discovered per machine, not per branch.

**The one rule that keeps them isolated:**

> `~/.claude/skills` must not point at a Bridge repo. Skills in a Bridge
> instance belong to **that instance**; the user level is for skills that
> belong to the **machine**.

Every instance already ships `.claude/skills → ../skills`, which loads its own
skills whenever the CWD is inside it. That is sufficient and needs no help. But
Claude Code *also* loads user-level skills from `~/.claude/skills/`, and on a
name collision **the user level wins**:

> "When skills share the same name across levels, enterprise overrides personal,
> and personal overrides project."
> — [Claude Code skills documentation](https://code.claude.com/docs/en/skills.md)

Every Bridge ships the same CORE skill names. So if `~/.claude/skills` points at
instance A, then inside instance B:

- A's copies of `debrief`, `briefing`, `bridge-onboard`, … **override B's own**
- CORE fixes you make *in B* have no effect *in B*
- A's `scope: org` skills load into B — including that organization's customer
  names in their `description:` triggers

There is no setting to invert precedence, and none to point Claude Code at a
different skills path. The only fix is to keep colliding names out of the user
level.

**How you get here:** it is a natural first-instance move — you point
`~/.claude/skills` at your only Bridge so its skills work everywhere, which is
harmless while there is one instance. The trap belongs to the *second* instance,
and nothing about the first one hints at it.

**The failure is silent.** A shadowed instance emits plausible output from the
wrong instance's skills; there is no error and no symptom to search for. Check
it explicitly:

```bash
readlink ~/.claude/skills      # must NOT resolve into a Bridge repo
```

`/bridge-audit` reports this as a **P0** (own skills do not load) plus a **P1**
(foreign-scoped skills loaded into this context). To distribute a genuinely
standalone tool skill to every directory, use a plugin — not a symlink. Full
rationale, the removal procedure, and the trap that the same path is often *also*
hardcoded by scripts:
[`skill-distribution-architecture.md` § Why the user level is not a distribution
channel](skill-distribution-architecture.md#why-the-user-level-is-not-a-distribution-channel).

## Trade-offs

**What you gain:**
- Full data isolation between organizations
- Each instance has its own context window (no CLAUDE.md bloat)
- Each organization gets the full Bridge feature set independently
- Local-only instances give git-backed work tracking to projects that
  previously had no version-controlled logs

**What you give up:**
- No single board across all organizations — each instance has its own
  `work/board.md` and `work/log.md`
- `/briefing` shows only the current instance's projects
- Upstream CORE merges must be done per instance (but they're fast and
  conflict-free)

**Mitigations:**
- Use distinct terminal windows or workspaces per instance for clear
  separation
- Name instances by organization for easy identification (`org-a-bridge`,
  `org-b-bridge`)
- Set different themes per instance for visual distinction (professional-de
  for personal projects, professional for client work)

## FAQ

**Can I have more than two instances?**
Yes. Each is an independent clone with its own user branch. Three
organizations → three instances.

**Can I merge work logs between instances?**
Not automatically. The work systems are independent. If you need a
combined view, consider writing a script that reads `work/log.md` from
each instance and merges them.

**What if both organizations use GitHub?**
You still need separate instances if the data can't mix. Push each to
its own GitHub repo — `org-a/open-bridge` and `org-b/open-bridge` — or
keep one local.

**What if I only need contexts, not full isolation?**
Use a single instance with multiple `contexts/`. Multi-instance is
specifically for when project metadata must not share a git history.

**Does bridge-deck work with multiple instances?**
Each bridge-deck daemon points at one Bridge instance. You could run
two daemons on different ports, but that's unusual. Most users pick one
instance for visualization and manage the other via terminal.
