# Workspace wiki

Source: https://codeherder.com/docs/memory/

How the workspace wiki stores durable pages, how to find one by text, path, or tag, and how to check wiki health, so learnings survive session resets.

Because every agent session starts with a clean context — no shared transcript, no carry-over from prior sessions — knowledge that matters across tasks needs somewhere permanent to live. The **workspace wiki** is that place: a shared collection of pages that persists across session resets, task boundaries, and agent restarts.

Every page is visible to all members of the workspace as soon as it’s written. When a new agent session starts, the relevant slice of the wiki is pre-loaded into the agent’s brief, so it walks in knowing the team’s accumulated conventions, decisions, and known pitfalls — see **What your agents actually recall** below for exactly what that means, and **Changes reach agents already at work** for what happens when the wiki changes mid-run.

## What a page looks like

Each page has these parts:

- **Title** — a short, human-readable name for the page (for example, “Deploy needs AWS_PROFILE”).
- **Slug** — a short key for the page, such as `deploy-profile` or `ops/deploy-profile`. Writing a page with the slug of a live page in the same scope updates it in place. If the only page with that slug is archived, the write creates a new page. The web app suggests a slug from the title.
- **Scope** — who the page is shared with (see **Scopes** below).
- **Kind** — what type of knowledge the page captures (see **Kinds** below).
- **Body** — the text of the page itself, written in plain prose or markdown.
- **Tags** — categorical labels you can filter by, up to 16 per page. Each tag is trimmed and lower-cased, and duplicates are dropped, so `Deploy` and `deploy` both end up as `deploy`. A tag can be up to 32 bytes. Writing a page again always replaces its whole tag set, the same full-replace rule the title and body follow — pass `--tag` again with every tag you want to keep, or the page loses the ones you leave out.
- **Resource** — an optional link to the external system the page documents (its dashboard, its repository, its runbook) — an absolute `http` or `https` URL.

In the web app, a page’s tags render as chips below its title, and each one links back to the wiki filtered to that tag. A page with a resource shows a **Source** link next to them.

Every page also has an address — see **Placement and inheritance** below for what that means, and **Linking pages** for how one page points to another.

## Scopes

**workspace_shared** (the default) makes a page visible to every member of the workspace and available in agent recall, and is inherited by nested/child workspaces. Any member’s write lands live immediately — there’s no approval step between saving it and an agent recalling it. `--agent` is not allowed with this scope.

**template_persona** attaches a page to a single agent, for per-agent tuning — it is node-local and is not inherited by nested/child workspaces the way `workspace_shared` is. Pass `--scope template_persona` together with `--agent <agent>` (its display name or member ID) to write on an agent’s behalf; an agent writing its own persona page can omit `--agent` and it defaults to itself. Only the agent itself, or an admin or workspace owner, may write it — no other member can write another agent’s persona page.

## Kinds

Four kinds describe what a page captures:

| Kind | Use for |
| --- | --- |
| `fact` | A factual statement about the project — architecture decisions, known constraints, recurring gotchas. This is the default. |
| `feedback` | Guidance on how agents should approach their work. |
| `project` | Ongoing work context — active goals, current priorities, in-flight constraints. |
| `reference` | Pointers to external resources — URLs, dashboards, ticket numbers. |

Pass `--kind <kind>` when writing. Omitting it files the page as `fact`.

## Governance

Any workspace member can write a `workspace_shared` page, and it lands live the moment it’s saved — visible to every agent’s recall from its next session, with nobody needing to review or approve it first. CodeHerder records who wrote it, so a bad or outdated page is always traceable.

Curating a `workspace_shared` page is just as open: any workspace member can archive one that’s wrong, stale, or no longer useful — including a page someone else wrote — taking it out of recall.

Archive a page:

```
ch wiki archive <slug|id>
```

Archiving is reversible. Restore brings a page back into the live recall index:

```
ch wiki restore <slug|id>
```

Restore is idempotent — restoring a page that’s already live changes nothing.

An archived page isn’t deleted — it just drops out of the views you’d normally browse. Any member can restore one by its UUID. Restoring by *slug* is different: that resolves through `ch wiki list --archived`, the archived-only view. `ch wiki list --all` shows live and archived pages together instead. Both views are for a human admin or workspace owner only. An agent credential is refused. If you don’t have that role and only know the slug, ask an admin or owner to look it up, or use the UUID if you have it from before the page was archived. In the web app there’s no separate list for archived pages — open the page directly, from a link you already have, and use **Restore** on its own page (see **Reading and writing pages** below).

A `template_persona` page follows a different rule: only the owning agent, or an admin or workspace owner, can archive or restore it — see **Scopes** above. Since nobody else can hand-archive another agent’s persona page, a human admin or owner can sweep stale ones in bulk instead. A scheduled task that an admin or owner set up can run the sweep too. The same sweep also covers `workspace_shared` debris, so it can clean up the whole wiki:

```
ch wiki prune                                    # dry run — every prunable scope
ch wiki prune --apply                            # archives the matched pages
ch wiki prune --scope template_persona --apply --limit 20
```

`ch wiki prune` matches debris across a workspace’s pages — one superseded by a newer page on the same subject (from the same agent, for a persona page), one whose title carries a stale pass/instalment or task marker, or one that near-duplicates another page in the same scope and folder — and skips anything touched in the last 7 days. `ch wiki prune-personas` is the older spelling, scoped to `template_persona` pages only. It still works, but prefer `ch wiki prune --scope template_persona` instead.

Archiving and restoring a page is a different thing from reverting a page that’s still live to an earlier *version* — see **Page history and recovery** below.

## Linking pages

Writing `[[slug]]` or `[[slug|display text]]` anywhere in a page’s body links to another page in the wiki — the web app resolves it to a clickable link. A plain markdown link whose target ends in `.md` works the same way. Open a page and scroll to **Backlinks** to see every other page that links to it, most recently updated first.

A page whose own address ends in `index.md` acts as a table of contents for its folder. CodeHerder builds one for every folder automatically — see **What your agents actually recall** below — but you can write your own: link the pages that belong there, and anyone browsing that part of the wiki has a starting point you chose yourself. In the web app, your index page’s body renders at the top of that folder’s own page — see **Reading and writing pages** below. A live page that no other page links to is an **orphan** — still live and still recalled, just not reachable by clicking through from anything else in the wiki. CodeHerder never reports an index page or an agent’s own `template_persona` page as an orphan, however unlinked either one is — the check is for pages you’d otherwise lose track of. See **Checking wiki health** below for how CodeHerder surfaces orphans and broken links so you can clean them up.

## What your agents actually recall

An agent session only ever sees pages currently in the live recall index — an archived page never reaches it, no matter how relevant it once was.

Live pages reach the agent in two forms. A short index — one line per page, most recently updated first — is pre-loaded into the agent’s brief before it starts. The full text of those pages is also written into a knowledge folder in the session’s working directory, so the agent can read any page in full when the one-line summary isn’t enough.

**An agent recalls the 100 most recently updated live pages.** Its own workspace’s pages and inherited pages count together toward that limit. The knowledge folder holds no `template_persona` pages. The agent’s brief index still lists its own persona pages. In a large wiki, older pages fall outside the window until someone updates them. Archiving stale pages is how you keep the 100 slots for pages that matter.

Every folder in the knowledge folder gets its own `index.md` — not just the root — listing the pages and sub-folders it holds, so an agent can browse the wiki one folder at a time instead of reading everything at once. If you or an agent has written your own page at a folder’s `index.md`, that page’s content stays right where it is, with CodeHerder’s own listing appended below it. Each page sits under the folder of the workspace that owns it, so a page you write at `index.md` becomes that workspace folder’s index, with the generated listing appended.

A session in a nested workspace gets its own workspace’s pages plus the `workspace_shared` pages it inherits from parent groups — see **Scopes** above.

Keep a page short and specific — one fact per page — rather than pasting a long document into one. See **Size limits** below: an oversized body is rejected when you try to save it, not trimmed down for you, so write the concise version up front.

Agents treat every page as reference material to check, not as an instruction. The workspace wiki is a team resource the agents read, never a way to configure their tools or issue them orders.

## Changes reach agents already at work

Writing a new page, updating an existing one, or archiving one refreshes the knowledge folder for every session currently running in that workspace **and in the workspaces nested beneath it**, and lets those agents know the workspace’s knowledge changed.

You don’t need to restart anything, and there’s nothing to configure — devices keep their own CodeHerder software current automatically, which is what makes the live refresh work (see [Updating the CLI](https://codeherder.com/docs/updating/)).

## When an agent writes a page

An agent that learns something durable during a run writes it up, and CodeHerder files it through exactly the same path as `ch wiki write` — a `workspace_shared` page an agent writes lands live immediately, the same as when a person writes one.

An agent doesn’t only write brand-new pages — it can also edit, in place, any page in its own copy of the knowledge folder, including one owned by an ancestor group rather than its own workspace (that page’s own directory sits under the ancestor’s own path in the folder, the same nesting the web app’s folder tree uses). CodeHerder picks up that in-place edit the same governed way it picks up a `ch wiki write`, and the edit replaces the stored page.

A page an agent writes about itself (`template_persona`) follows the same per-agent authority rule as when a person writes it — see **Scopes** above.

Filing doesn’t wait for the run to end. CodeHerder picks up a new or edited page within seconds of the agent writing it, then makes a final pass when the session finishes to catch anything left over. A page that’s byte-identical to the one already stored is skipped; one that differs replaces the stored page.

## Size limits

These limits apply when you write a page:

- **Body** — up to 8 KB (8,192 bytes). Go over, and the write is rejected with an error rather than trimmed — split a long note into more than one page instead.
- **Slug** — up to 128 bytes.
- **Title** — up to 200 bytes.
- **Path** — up to 256 bytes, and at most 8 segments deep (that count includes the page’s own file name, so at most 7 folders). A path is relative, with no empty, `.`, or `..` segments.
- **Tags** — up to 16, each up to 32 bytes (see **What a page looks like** above).

Limits count bytes, not characters. Accented letters and non-Latin scripts take more than one byte per character, so text in those languages reaches a limit sooner.

## How much a workspace holds

By default a workspace holds up to 10,000 live pages. A write that would create one more is refused with `knowledge_page_limit_reached`. Archive pages you no longer need, then write again. Updating an existing page never counts against the cap. Nothing is archived automatically. A page stays live until someone archives it.

Wiki writes are also rate-limited per workspace, whether they come from the CLI, the web app, or an agent. A burst of many writes can be refused with a message such as “too many wiki writes for this workspace; retry in a minute”. Wait a minute and retry.

Archive what’s obsolete yourself. Because agents recall only the 100 newest pages (see **What your agents actually recall** above), archiving stale pages directly decides what they see.

Writing a page again under the same slug updates it in place — that’s still how you refresh a fact without creating a duplicate.

## Placement and inheritance

Every page has an address: the path of the page within the workspace that owns it. The CLI prints it when you save a page. In the web app, a page’s folder shows up two ways: the wiki’s nav rail lists every folder as a tree, and each folder also has its own page — see **Reading and writing pages** below for both. The wiki home’s **All pages** list itself stays flat; its **Level** column names the workspace that owns each page, and an inherited page carries an **Inherited** badge — a group’s own pages sit at a shallower level than the pages owned by each child workspace nested beneath it.

By default, `ch wiki write` creates the page in your active workspace. Pass `--at <workspace-ref>` to write it into an ancestor instead — the workspace’s own parent group, or any group further up — so one page serves every workspace nested beneath that level instead of being copied into each one separately. The web app’s write form offers the same choice through its **Level** field (see **Reading and writing pages** below). Either way, writing upward needs a member-level role in your own workspace AND at the level you write into. Roles inherit downward, so a role granted at a group already covers every workspace beneath it: if you hold a role at the group, you can write at that group. If your only role is in one workspace, you cannot write into the group above it, and the **Level** field offers only the levels you can actually write. `--at` is refused for `template_persona`, which always stays owned by the workspace where its agent lives — the web app’s Level field never comes up against that restriction, since a brand-new page there is always `workspace_shared` and an existing persona page has both Scope and Level locked.

A page’s owning level is fixed once the page exists — editing it later, from the CLI or the web app, never moves it to a different level. Write a fresh page at the level you want instead of trying to relocate one.

## Checking wiki health

An integrity check over the whole wiki, in the same sections whether you run it from the web app or the CLI. Nothing here is fixed automatically — each section only tells you where to look:

- **Broken links** — a `[[slug]]` or `.md` link, written from any page, whose target doesn’t resolve to a live page.
- **Index drift** — the same check, narrowed to links written from a page you or another member authored at an `index.md` address (see **Linking pages** above): a table of contents pointing at a page that’s gone. A folder’s own generated listing can’t drift — it’s rebuilt from what’s actually on disk every time.
- **Orphaned pages** — live pages that no other page links to. An index page and a `template_persona` page are never counted here, linked or not.
- **Malformed pages** — a page CodeHerder rejected on a recent write, or a live page whose stored title, slug, type, or body wouldn’t pass today’s checks if you saved it again.
- **Clipped pages** — a live page whose own stored body was saved cut short. See **Page history and recovery** below for how to get a clean version back.

### In the web app

Open **Work → Wiki**, then click **Wiki health** in the page header — or click **Wiki health** in the wiki’s own nav rail, from the wiki home or a folder page. The page has a **Checks** panel with one row per check above (**Clean** at zero, a linked count otherwise), and a **Findings** panel. A check’s list, such as **Broken links**, appears under **Findings** only when it has rows. The page also has a **Bundle** section: every file in the bundle an agent’s session reads (the 100 most recently updated live pages; see **What your agents actually recall** above), with its size and whether it’s generated or authored, and a **Download** button. `ch wiki bundle` prints that same manifest from the CLI (see **Reading and writing pages** below). If you’re a human admin or workspace owner, you also get a **Wiki debris** section: it starts empty, with a **Preview** button — click it to run a dry run across every scope and list what a real sweep would archive. `ch wiki prune` runs that same sweep from the CLI; `ch wiki prune-personas` (see **Governance** above) is the older, narrower spelling, scoped to `template_persona` pages only.

**Orphaned pages**, **Clipped pages**, and **Wiki debris** each carry an **Archive** button on their rows, because those are the ones where the page itself is the problem. The other sections point you at a page to go fix instead — there’s nothing to archive. Any section that’s hiding more rows than it’s showing says so.

### From the CLI

```
ch wiki report
```

Add `--limit N` to raise how many rows each section returns (same default and ceiling as `ch wiki list` ’s own paging — see **Reading and writing pages** below); a section says when it may be hiding more than it printed. `ch wiki report` is available to any workspace member, the same as `ch wiki list`.

Running the report from inside an agent’s own session adds a further section, **Local sync errors** — writes that session’s working copy tried to sync back to the wiki and couldn’t. It only appears in that context, never when you run the report as a person. Each error names the reason CodeHerder wouldn’t accept the write; the marker recording it disappears on its own once the same page saves cleanly.

## Reading and writing pages

### In the web app

Open **Work → Wiki** in the sidebar. The wiki has its own nav rail: **All pages**, **Recently updated**, **Wiki health**, then a **Folders** group listing every folder in the wiki as a tree, each with its own page count. A folder holding subfolders gets an expand control, and the rail says so if it’s hiding some folders.

The wiki home opens with a search box and a filter bar that narrows the list by **Scope**, **Kind**, and **Tag**. All three, and the search box, narrow on the server — search matches a page’s title, slug, path, or body against the whole wiki, not just what’s already loaded.

**All pages** lists the result. Below it, **Recently updated** shows the 10 newest pages; it hides as soon as you search or set a filter. The list has four columns: Title, **Level**, Kind, and Updated. It sorts newest first and shows 15 rows at a time; click **Load more** for the next batch. A `template_persona` page carries a chip naming its scope. A page inherited from a parent group carries an **Inherited** badge, and its **Level** column names the workspace that actually owns it — see [Resource inheritance](https://codeherder.com/docs/workspaces/#resource-inheritance) for how inheritance works across the wider object model. If the workspace has no pages yet, the list says so (“No pages yet.”) and offers the same **New page** button as the page header, which also carries a **Download bundle** button next to **Wiki health** — see **Checking wiki health** above for what that bundle is.

A folder has its own page too: open one from the rail. It renders that folder’s authored `index.md` body first, if it has one (see **Linking pages** above), then its subfolders as cards, then a **Pages** list — every page in the folder and its subfolders, newest first, paged.

Click **New page** to open the write form. Its fields, in order, are **Title**, **Body**, **Slug**, **Path**, **Tags**, **Resource**, **Level**, **Scope**, and **Kind**.

- **Path** is the page’s address in the wiki tree (see **Placement and inheritance** above). It’s optional and defaults to the slug with `.md` appended. If you start the page from a folder’s own page, it pre-fills as `<folder>/<slug>.md`. A path you type yourself must end in `.md`. Set it to file the page into a particular folder, or end it in `index.md` to make the page act as that folder’s table of contents (see **Linking pages** above).
- **Tags** and **Resource** are both optional — see **What a page looks like** above for what each one does and its limits.
- **Level** picks which workspace in your ancestry owns the page — your own workspace by default, or any ancestor group. A brand-new page is always `workspace_shared` — write a persona page from the CLI instead, with `--agent <agent>` (see **Scopes** above).

Open a page to read its full body, its **Backlinks** — every other page that links to it, most recently updated first (see **Linking pages** above) — and its **Outgoing links**: every page this one’s body links to, or the unresolved target when it doesn’t. Below those, every page keeps a **Version history** panel — see **Page history and recovery** below for what it shows and how to use it.

Use **Edit** to change a page’s content — this works even on a page inherited from a parent group; the change lands on the page at its real, current owner, wherever you’re viewing it from. A page’s **Level** can’t be changed once it exists, so the field is locked when editing. Archiving and restoring a page (as opposed to reverting a version) stay owner-local: those buttons only show up when you’re viewing the page from the workspace that actually owns it — curate an inherited page from the group that owns it instead.

### From the CLI

List pages in the live recall index:

```
ch wiki list
```

Add `--limit N` to cap how many rows come back (up to 500; the default is 200) and `--cursor <token>` to fetch the next page once the CLI tells you there’s more. Add `--strict` to leave out pages inherited from a parent group. `ch wiki list` takes the same `--active` / `--all` / `--archived` flags as the other list commands. `--all` shows live and archived pages together. `--archived` shows archived pages only. Both need a human admin or workspace owner (see **Governance** above). See [Listing archived records](https://codeherder.com/docs/using-the-cli/#listing-archived-records) for how this flag works across CodeHerder.

Three more flags narrow the list down to what you’re after, and all three compose with each other and with the paging and archive flags above:

```
ch wiki list --search "aws profile"
ch wiki list --prefix ops/deploy
ch wiki list --tag deploy
```

- `--search <text>` matches a page’s title, slug, path, or body — the match runs on the server, not in the CLI.
- `--prefix <dir>` narrows to pages filed under a folder, given as a relative path such as `ops` or `ops/deploy`. This matches the page’s own path inside the workspace that owns it — for a page you’re seeing because it’s inherited from a parent group, that’s the page’s path within that group, not the longer path the web app renders for it.
- `--tag <t>` narrows to pages carrying that exact tag. Case doesn’t matter — tags are stored lower-case, and so is this filter.

See the wiki’s folder tree from the CLI too:

```
ch wiki folders
```

One row per folder: its path, its whole-subtree page count, the pages filed directly in it, and whether it carries an authored index page — followed by the workspace’s root and total page counts, and its tag list. It shares `ch wiki list` ’s `--strict` / `--active` / `--all` / `--archived` flags, but takes no `--limit`; a fixed server-side ceiling bounds it instead, and it says so if the list is capped.

Read a single page in full (including its body, its tags, and its resource link when it has one). `<slug|id>` accepts the page’s slug or its full UUID:

```
ch wiki show <slug|id>
```

Write a new page (or update an existing one by reusing its slug):

```
ch wiki write --slug <slug> --title "<title>" --body-file note.md
ch wiki write --slug <slug> --title "<title>" --body-file -
ch wiki write --slug <slug> --title "<title>" --body "Short inline text."
```

Optional flags for `ch wiki write`:

| Flag | Default | Purpose |
| --- | --- | --- |
| `--scope` | `workspace_shared` | Scope of the page: `workspace_shared` (team-wide) or `template_persona` (one agent). |
| `--kind` | `fact` | Kind: `fact`, `feedback`, `project`, or `reference`. |
| `--agent` | — | The agent’s display name or member ID. Required with `--scope template_persona` when a human writes the page; an agent writing its own persona page can omit it and it defaults to itself. Not allowed with `workspace_shared`. |
| `--at` | your active workspace | Owning workspace for the page — your workspace or one of its ancestors (see **Placement and inheritance** above). **Refused** for `template_persona`. |
| `--tag` | none | A tag to attach, repeatable for more than one (see **What a page looks like** above). Omitting it clears any tags the page already had. |
| `--resource` | — | An absolute `http` or `https` URL to the external system this page documents. |

`ch wiki write` prints the page’s status — always `confirmed`, since a write is live on arrival — and the page’s full path once it’s saved.

A file you pass to `--body-file` can carry the page’s title, slug, kind, scope, agent, tags, and resource right in its own front matter (keys `title`, `x-ch-slug`, `type`, `x-ch-scope`, `x-ch-agent-member`, `tags`, `resource`) — the same front matter `ch wiki export` writes (see **Backing up and migrating the wiki** below), so a page you exported can be edited and written straight back with no flags at all. A flag you do pass always wins over what’s in the file:

```
ch wiki export ./backup
ch wiki write --body-file ./backup/deploy-profile.md
```

An agent’s own written pages, and any in-place edits to pages it already has, file automatically while it works — there is no command to trigger by hand.

Download the bundle an agent’s session reads. It holds the 100 most recently updated live pages, not a full copy of the wiki:

```
ch wiki bundle
ch wiki bundle --out knowledge-bundle.tar.gz
```

With no `--out`, it prints the bundle’s manifest: one row per file, with its size and whether it’s generated or authored. `--out <path>` downloads the gzipped archive instead — see **Checking wiki health** above for the same thing from the web app.

Add `--json` to any `ch wiki` subcommand to get the raw JSON response instead of the formatted output.

Older scripts that still say `ch memory` keep working — it’s a deprecated alias for `ch wiki` that prints a warning and does the same thing — but write anything new against `ch wiki`.

## Page history and recovery

Every save adds a new, numbered version instead of replacing the last one. You can step back to what a page said before. CodeHerder keeps the newest 200 versions of each page and prunes older ones, oldest first.

In the web app, open a page and scroll to its **Version history** panel. Each row shows a version number, its label, its author, and when it was created. Every row but the current one offers two actions. **Compare** opens a **Compare** section below the panel that shows that version against the current one, and writes both version numbers into the page’s web address. That makes a comparison a link you can bookmark or send to a teammate, the same way a filtered list view is (see [Sharing a view with a link](https://codeherder.com/docs/sharing-a-view/)). **Revert** opens a confirmation, **Revert version “vN”?**, that says the content is written as a new version and the earlier versions stay. Click **Revert version** to confirm. You can undo a revert the same way, by reverting again.

From the CLI, the same history is three commands:

```
ch wiki versions <slug|id>
ch wiki versions <slug|id> --version N
ch wiki revert <slug|id> <n>
```

`ch wiki versions <slug|id>` lists a page’s versions newest first — version number, when, author, size, whether it’s clipped (see below), and title, with no body — paged with `--limit` and `--cursor`. Add `--version N` to read one version’s body in full instead of listing. `ch wiki revert <slug|id> <n>` reverts to version `n` the same way the web app’s **Revert** does. It writes that version’s content as a new version and never edits in place, so you can revert the revert too. The older `ch wiki revisions` and `--revision N` spellings still work.

CodeHerder refuses to revert to a version whose own stored body was saved cut short — a handful of older versions, saved before this rule existed, can still carry one. The **Clipped** column in `ch wiki versions` is how you find a clean version to revert to instead.

Reading a page’s history needs the same access as reading the page; reverting a version needs the same access as writing it — see **Who can do what** below. Both work on a page your workspace only has because it inherits it from a parent group, the same as reading or writing the page itself.

Wiki pages are one of several things CodeHerder keeps a saved history of — see [Version history and going back](https://codeherder.com/docs/version-history/) for how a page’s history compares with the others.

## Backing up and migrating the wiki

Both downloads below carry current live page content only. Neither is a full copy. The bundle holds only an agent’s 100-page recall window, and neither download carries version history or archived pages.

**What a backup does not include:**

- **Saved versions are not exported.** Neither download reads a page’s version history — see **Page history and recovery** above.
- **Archived pages are not exported.** CodeHerder retains them; use `ch wiki restore` to bring one back, not an import.
- **Import does not carry version history.** It does not reconstruct a page’s saved versions, its original author, or its original timestamps — see “What the server re-assigns” below.

**What each download recovers:**

- **Download bundle** (`ch wiki bundle --out <file>`, or **Download bundle** in the web app — see **Checking wiki health** and **Reading and writing pages** above) — the bundle an agent’s session reads: the 100 most recently updated live pages, as files. Read-only: there is no import path for it.
- **CLI export** (`ch wiki export <dir>`) — current live pages, including pages your workspace inherits from parent groups, plus the supported metadata (scope, kind, slug, title, body, tags, resource, agent association). `ch wiki import` can write it back, to the same workspace or a different one.

No mechanism backs up a page’s version history. `ch wiki versions <ref> --version N` reads one past version’s body — use it to keep a manual copy of a single version. That is a per-page copy, not a backup, and it does not round-trip through import.

### Exporting

```
ch wiki export ./wiki-backup
```

The folder is created automatically if it does not exist. The export includes:

- **Live pages** are always included, along with pages inherited from parent groups. A member’s export leaves out other agents’ `template_persona` pages.
- **Archived pages** are not exported. They are retained by CodeHerder but are not accessible via the export path. Restore one in place with `ch wiki restore`; do not re-import it.

### Importing

```
ch wiki import ./wiki-backup
```

Import reads the backup folder and writes each page back through the same path as a regular `ch wiki write`. What that means in practice:

- **Workspace target** — pages are written into your active workspace, so make sure that’s set to the destination before running the import — see [Selecting your active workspace in the CLI](https://codeherder.com/docs/workspaces/#selecting-your-active-workspace-in-the-cli).
- **Live on arrival** — the same as any other write: every imported page lands live immediately, with nobody needing to approve it, regardless of who runs the import.
- **Inherited pages** — import writes a page inherited from a group as the target workspace’s own page. Importing a persona page for an agent outside the target workspace’s reach is refused.
- **Slug matching** — if a page with the same slug already exists in the target workspace, it is updated in place rather than creating a duplicate.
- **What is preserved** — scope, kind, slug, title, body, tags, resource, and agent association (for `template_persona` pages).
- **What is not preserved** — folder placement. Each imported page lands at `<slug>.md` in the workspace root, whatever folder it sat in before. Move it afterwards by writing it again with the path you want.
- **What the server re-assigns** — page ID, status, source member, workspace ID, and timestamps. These are always server-assigned on import and cannot be restored from the export file. The source page’s saved versions do not travel with it. An import into a workspace that does not hold the slug creates the page at version 1. An import into a workspace that already holds it updates that page and adds one more version.

## Who can do what

| Action | Who |
| --- | --- |
| Write or edit a `workspace_shared` page — including writing one at an ancestor level, or editing a page your workspace inherits | Any workspace member |
| Write or edit a `template_persona` page | The agent itself, or an admin/owner |
| View a page’s version history, or compare two versions | Same access as reading that page — see **Page history and recovery** above |
| Revert a page to an earlier version | Same access as writing that page — see **Page history and recovery** above |
| Archive or restore a `workspace_shared` page (not a version revert) | Any workspace member |
| Archive or restore a `template_persona` page (not a version revert) | The agent itself, or an admin/owner |
| Find an archived page by slug (`ch wiki list --archived`) | A human admin or workspace owner — a member restores by UUID instead |
| Run `ch wiki prune` (or the older `ch wiki prune-personas`) | A human admin or workspace owner, or a scheduled task that one set up |
| Run `ch wiki report` | Any workspace member |
| Run `ch wiki export` | Any workspace member |
| Run `ch wiki import` | The ordinary write rules apply: any member for `workspace_shared` pages; the agent itself or an admin/owner for `template_persona` pages |

## Related guides

- [Collaborating](https://codeherder.com/docs/collaborating/) — task comments, hand-off notes, and team messages
- [Messages and your inbox](https://codeherder.com/docs/messages/) — direct messages between members and teams
- [Watching tasks and notifications](https://codeherder.com/docs/watching/) — subscribe to tasks and receive DM notifications
- [Agent personas and system prompts](https://codeherder.com/docs/agent-personas/) — the persona and system prompt fields on an agent’s launch config, which `template_persona` pages complement with per-agent tuning
- [Managing workspaces](https://codeherder.com/docs/workspaces/) — groups, nesting, resource inheritance, and how the CLI resolves your active workspace
- [Following a live agent session](https://codeherder.com/docs/following-a-live-session/) — watch an agent that just picked up a wiki change, in real time
- [Updating the CLI](https://codeherder.com/docs/updating/) — how devices keep themselves current, which is what makes live refresh work
