# Mesh
Source: https://dorkos.ai/docs/concepts/mesh

How DorkOS finds your AI agents across your projects and connects them so they can reach each other





# Mesh [#mesh]

Mesh finds the AI agents scattered across your projects and gathers them in one place. It scans your folders, shows you what it found, and lets you approve which agents to add. Once an agent is in, other agents can find it and reach it. Mesh is always on, with nothing to turn on first.

<Callout type="info">
  Cross-project messaging is new. We're still hardening it, so expect a rough edge here and there
  while we catch up with real-world use.
</Callout>

**Try it:** open the **Agents** page and click **New Agent**, then choose **Import Project**. Mesh scans your folders and shows you what it found. From the Agents page you can also switch to the **Topology** tab to see the network map, or the **Access** tab to manage messaging rules between groups.

## The problem it solves [#the-problem-it-solves]

When you run agents in several projects, they cannot see each other. A Claude Code agent working on your backend has no idea a Cursor agent is editing your frontend. So you become the go-between, copying context from one session into the next.

Mesh removes that step. It finds your agent projects, keeps a list of them, and connects them so they can message each other. Nothing gets added without your approval.

## Finding your agents [#finding-your-agents]

When you run a scan, Mesh walks your folders and looks for the tell-tale signs of an agent project, like a `CLAUDE.md` file or a `.cursor/` folder. It knows the markers for ten popular agent tools. For anything it finds, it shows you the agent as a candidate and waits for your yes before adding it.

A few things happen on their own during a scan:

* **Agents you already added come back for free.** If a folder already holds a DorkOS agent file (`.dork/agent.json`), Mesh adds it back on the next scan without asking again. You never re-approve the same agent twice.
* **Known and skipped folders are left alone.** Agents already on your list, and folders you have said no to, are passed over.

Mesh scans a few folders deep by default (five levels) so a normal scan finishes quickly.

<Callout type="info">
  A scan only reads your folders. It never changes anything in your projects until you approve an
  agent.
</Callout>

## Adding an agent [#adding-an-agent]

When you approve a candidate, Mesh turns it into a full agent. It gives the agent an ID that also records when it was created, so your lists stay in order. It writes a small `.dork/agent.json` file in the project, so the agent's identity travels with the code and you can commit it like any other file. It adds the agent to its list. And if messaging is on, it gives the agent a mailbox so other agents can reach it right away.

You can also add an agent by pointing Mesh straight at a folder, which is handy when you already know the one you want.

## Grouping agents [#grouping-agents]

Mesh groups agents by where they live on disk. An agent in `projects/backend/api-service`, scanned from `projects`, lands in the `backend` group. DorkOS calls each group a **namespace**.

Groups do two jobs:

* **They tidy the view.** The network map groups agents by their namespace.
* **They keep messaging safe.** Agents in the same group can message each other freely. Messaging across groups is off until you allow it.

To open a path between two groups, you add an allow rule. Rules go one way only: letting agent A message agent B does not let B message A.

## Skipping folders you don't want [#skipping-folders-you-dont-want]

If a folder keeps showing up as a candidate and you never want it, you can add it to the skip list. Mesh remembers your choice and passes that folder over on every future scan. You can take a folder off the skip list later to let it show up again.

## Seeing the whole network [#seeing-the-whole-network]

The network map shows you your agents grouped by namespace, with the rules that connect them. It respects your messaging rules as walls: an agent only sees the agents it is allowed to reach, so agents cannot even tell that off-limits agents exist.

<Callout type="info">
  The DorkOS dashboard uses an admin view that sees past those walls, so it can draw the full map
  for you.
</Callout>

## Knowing which agents are alive [#knowing-which-agents-are-alive]

Mesh watches each agent through a heartbeat: a quick "still here" signal an agent sends as it works, the agent equivalent of a text back that just says "yep, still alive." From that, it sorts every agent into one of three states:

* **Active**: seen just now
* **Inactive**: quiet for a while, but probably fine
* **Stale**: quiet for a long time, and may be offline

When an agent's state changes, the dashboard updates the network map on the spot. You also get a running count of how many agents are active, inactive, and stale.

## Where Mesh keeps its data [#where-mesh-keeps-its-data]

Mesh keeps its list in a small database at `~/.dork/dork.db`. But the real source of truth is the `.dork/agent.json` file in each project, not the database, on purpose, so your agents survive even if the database doesn't. If the database is ever lost, Mesh rebuilds it from those files on the next pass. Nothing you care about lives only in the database, so you cannot lose an agent by deleting `dork.db`.

Scanning and registering agents only ever reads and writes files on your own machine, through your own DorkOS server.

## Reference [#reference]

The rest of this page is for developers wiring up Mesh or reading its internals. If you just want to use Mesh, you can stop here.

### Detection markers [#detection-markers]

Mesh recognizes agent projects with pluggable **detection strategies**. Each strategy looks for one tool's filesystem markers and reports a suggested name, runtime type, inferred capabilities, and description. DorkOS ships ten:

| Strategy        | Filesystem markers                                                                                   | Runtime       |
| --------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
| **claude-code** | `CLAUDE.md` or `AGENTS.md` at the project root. Extracts a description from the first paragraph.     | `claude-code` |
| **cursor**      | `.cursor/` directory or `.cursorrules` file at the project root.                                     | `cursor`      |
| **codex**       | `.codex/` directory at the project root.                                                             | `codex`       |
| **windsurf**    | `.windsurfrules` file or `.windsurf/` directory at the project root.                                 | `windsurf`    |
| **gemini**      | `GEMINI.md` file or `.gemini/` directory at the project root.                                        | `gemini`      |
| **cline**       | `.clinerules` file or directory at the project root.                                                 | `cline`       |
| **roo-code**    | `.roo/` directory or `.roorules` file at the project root.                                           | `roo-code`    |
| **copilot**     | Copilot-specific files within `.github/` (`copilot-instructions.md`, `instructions/`, or `agents/`). | `copilot`     |
| **amazon-q**    | `.amazonq/` directory at the project root.                                                           | `amazon-q`    |
| **continue**    | `.continue/` directory at the project root.                                                          | `continue`    |

The `AgentRuntime` enum also carries placeholder values for tools that do not have a strategy yet: `augment`, `jetbrains-ai`, `kilo-code`, `trae`, and `other`.

Any directory that already contains a `.dork/agent.json` manifest is **auto-imported** by the scanner rather than surfaced as a candidate. This is scanner behavior, not a detection strategy. The scan yields `DiscoveryCandidate` objects only for directories that match a strategy and are not yet registered or denied.

### The agent manifest [#the-agent-manifest]

Every registered agent has a manifest stored in `.dork/agent.json`:

| Field                 | Description                                                                                                                                    |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **id**                | Time-ordered ID assigned at registration                                                                                                       |
| **name**              | Human-readable name (e.g., "backend-api")                                                                                                      |
| **description**       | What the agent does                                                                                                                            |
| **runtime**           | Agent platform (e.g., `claude-code`, `cursor`, `codex`, `windsurf`, `gemini`, `cline`, `roo-code`, `copilot`, `amazon-q`, `continue`, `other`) |
| **capabilities**      | Capability tags (e.g., "typescript", "testing")                                                                                                |
| **behavior**          | Response mode: `always`, `direct-only`, `mention-only`, or `silent`                                                                            |
| **namespace**         | Derived from project path relative to scan root                                                                                                |
| **persona**           | Optional system prompt text injected into Claude sessions                                                                                      |
| **personaEnabled**    | Whether persona text is injected (default: true)                                                                                               |
| **color**             | CSS color override for visual identity                                                                                                         |
| **icon**              | Emoji override for visual identity                                                                                                             |
| **enabledToolGroups** | Per-domain MCP tool overrides (tasks, relay, mesh, adapter)                                                                                    |

### Access rule priority [#access-rule-priority]

Under the hood, Mesh writes Relay access-control rules with a priority scheme. Higher priority wins:

| Priority | Rule                  | Effect                                             |
| -------- | --------------------- | -------------------------------------------------- |
| **100**  | Same-namespace allow  | Agents in the same namespace always communicate    |
| **50**   | Cross-namespace allow | Explicitly permitted cross-namespace communication |
| **10**   | Cross-namespace deny  | Default deny for all other cross-namespace traffic |

### Storage tables and Relay integration [#storage-tables-and-relay-integration]

Mesh stores its data in `~/.dork/dork.db`, managed by Drizzle ORM: the **agent registry** (`agents` table) holds every registered agent with its manifest, project path, namespace, and health fields, and the **denial list** (`agent_denials` table) holds the paths excluded from discovery. Because the `.dork/agent.json` files are the canonical source (ADR-0043), the database is a rebuildable cache: on a missing `dork.db`, the reconciler walks the managed agents home (`~/.dork/agents/`) and the scan roots of surviving agents, re-importing every `.dork/agent.json` it finds.

When both Mesh and Relay are enabled, registering an agent in Mesh creates a Relay endpoint for it at `relay.agent.{namespace}.{agentId}`:

* **Registration** creates the endpoint and sets up intra-namespace access rules, so same-namespace agents can communicate immediately.
* **Unregistration** removes the endpoint. If it was the last agent in its namespace, the namespace-specific access rules are removed too.
* **Lifecycle signals** broadcast health-status changes on the `mesh.agent.lifecycle.*` subject pattern, which the dashboard subscribes to for real-time map updates.

## Next Steps [#next-steps]

<Cards>
  <Card title="Relay" href="/docs/concepts/relay">
    Understand the messaging layer that Mesh agents use to communicate.
  </Card>

  <Card title="Sessions" href="/docs/concepts/sessions">
    Learn how agent sessions work and how they connect to the Mesh registry.
  </Card>

  <Card title="Architecture" href="/docs/concepts/architecture">
    See how Mesh fits into the overall DorkOS architecture.
  </Card>
</Cards>
