# mycelium
An underground network of information for AI agents, based on git notes.
Agents read notes on arrival. They leave notes on departure. The network grows. Humans never see it unless they choose to look.
## What it is
Structured notes attached to git objects — commits, files, and directories. Agents use them to communicate decisions, warnings, context, and culture across sessions. The format is plain text with headers and edges. The storage is `git notes`. The dependency list is git and bash.
```bash
# write a note on the current commit
mycelium.sh note HEAD -k context -m "Why this change exists."
# read it back
mycelium.sh read HEAD
```
## Install
Install the runtime file (`mycelium.sh`) with the one-line installer.
**Latest integrated (`main`)**:
```bash
curl -fsSL https://raw.githubusercontent.com/openprose/mycelium/main/install.sh | bash
```
By default this installs to `~/.local/bin/mycelium.sh`. Override the location with `PREFIX`:
```bash
curl -fsSL https://raw.githubusercontent.com/openprose/mycelium/main/install.sh | PREFIX=/usr/local bash
```
**Pinned stable release**:
```bash
curl -fsSL https://raw.githubusercontent.com/openprose/mycelium/main/install.sh | VERSION=0.3.0 bash
```
**Pinned prerelease / RC**:
```bash
curl -fsSL https://raw.githubusercontent.com/openprose/mycelium/main/install.sh | VERSION=0.3.0-rc.1 bash
```
If you already cloned the repo, you can install from the local checkout instead:
```bash
./install.sh
```
The runtime is still one file, with no dependencies beyond bash and git.
### Release channels
- **`main`** = latest integrated code. Good for contributors and adventurous users. May be ahead of the last stable release.
- **`vX.Y.Z`** = stable release tag.
- **`vX.Y.Z-rc.N` / `-beta.N`** = prerelease tags for validation.
If you want a stable install, pin `VERSION=X.Y.Z`. If you want the latest integrated code, install from `main`.
## Quick start
```bash
# in any git repo
mycelium.sh note HEAD -k context -m "First note."
mycelium.sh read HEAD
```
For AI agents, load [SKILL.md](SKILL.md) into your agent framework. The skill teaches the convention: check for notes before working, leave notes after.
## Practical notes
**Notes don't travel with normal push/pull.** Git notes live on a separate ref (`refs/notes/mycelium`). To sync them:
```bash
mycelium.sh sync-init # adds fetch/push refspecs for origin
git fetch origin # now pulls notes
git push origin # now pushes notes
```
**GitHub has no native UI for git notes.** Notes don't appear in diffs, PRs, file browsers, or the commit view. We consider this a feature — the mycelium is hidden until explicitly surfaced. To see notes locally:
```bash
mycelium.sh log # recent commits with their notes
mycelium.sh activate # permanently show notes in git log
```
**Notes are scoped to branches.** Work on a feature without polluting the main notes:
```bash
mycelium.sh branch use my-feature # notes go to a separate ref
mycelium.sh branch use main # switch back
mycelium.sh branch merge my-feature # merge when ready
```
## Security considerations
**Most tooling isn't aware of git notes** because most developers don't know about git notes. Secret scanners, CI pipelines, and code review tools typically skip `refs/notes/*`. This means:
- Secrets accidentally written to notes **will not be caught** by default tooling
- Notes are **public for public repos** — anyone can `git fetch` them
- `git notes remove` does **not erase history** — the old content persists in the notes ref log
**We strongly recommend [gitleaks](https://github.com/gitleaks/gitleaks).** It scans notes by default (via `git log --all` which includes `refs/notes/*`). See our [example hooks](hooks/) for pre-commit, pre-push, and post-checkout integration.
## Core CLI
```
mycelium.sh note [target] -k <kind> -m <body> Write a note
mycelium.sh read [target] Read a note
mycelium.sh follow [target] Read + resolve all edges
mycelium.sh refs [target] Find all notes pointing at target
mycelium.sh find <kind> Find all notes of a kind
mycelium.sh kinds List all kinds in use
mycelium.sh edges [type] List all edges
mycelium.sh list All annotated objects
mycelium.sh log [n] Recent commits with notes
mycelium.sh dump Everything, greppable
mycelium.sh doctor Graph state (facts only)
mycelium.sh prime Skill + live repo context for agents
mycelium.sh migrate [--dry-run] [--map <file>] Reattach notes after jj rewrites
mycelium.sh branch [use|merge] [name] Branch-scoped notes
mycelium.sh activate Show notes in git log
mycelium.sh sync-init [remote] Configure fetch/push
mycelium.sh sync-init --export-only [remote] Configure export ref sync only
mycelium.sh repo-id [init] Durable repository identity
mycelium.sh zone [init [level]] Confidentiality zone (default: 80)
mycelium.sh export <target> --audience <a> Export note to audience ref
mycelium.sh export --all [--kind <k>] --audience <a> Batch export notes
mycelium.sh import <remote> [--as <name>] Import notes from remote
mycelium.sh list-imports Show imported repos
```
Kinds and edge types are open vocabulary — use whatever strings make sense. `mycelium.sh kinds` shows what's in use.
## Workflow scripts in this repo
When using a full checkout of this repo, the skill also ships workflow scripts that lean on git rather than core CLI aggregation:
```bash
scripts/context-workflow.sh <path> [ref] # recommended arrival workflow
scripts/path-history.sh <path> [ref] # historical file notes via git history
scripts/note-history.sh <target> # overwrite history via notes-ref history
scripts/compost-workflow.sh [path|oid] [--compost|--renew] # explicit stale/renew workflow
```
These are **examples / golden workflows**, not part of the core mycelium protocol.
Rule of thumb:
- `context-workflow.sh` = default arrival workflow for a path
- `path-history.sh` = explicit historical notes for a file
- `note-history.sh` = overwrite history for one note target
- `compost-workflow.sh` = opt-in stale/renew lifecycle
If a repository still wants an explicit stale/renew lifecycle, use `scripts/compost-workflow.sh`. The simpler default is still to lean on git-native history scripts first and write a fresh current note when older context still matters.
## Note format
```text
kind decision
title Short label
edge explains commit:abc123...
edge depends-on blob:def456...
Free-form body. Markdown encouraged.
```
**Headers**: `kind` (required), `edge`, `title`, `status`
**Kinds**: `decision` · `context` · `summary` · `warning` · `constraint` · `observation` · `value` · `todo` — or invent your own.
**Edge types**: `explains` · `applies-to` · `depends-on` · `warns-about` · `targets-path` · `targets-treepath` — or invent your own.
**Targets**: `commit:<oid>` · `blob:<oid>` · `tree:<oid>` · `path:<filepath>` · `note:<oid>`
## Note history
Mycelium does not store a special `supersedes` chain anymore. Overwrite history lives in git itself on the notes ref.
Use either raw git:
```bash
OID=$(git rev-parse HEAD:path/to/file.ts)
FANOUT="${OID:0:2}/${OID:2}"
git log -p refs/notes/mycelium -- "$FANOUT"
```
Or the repo workflow script:
```bash
scripts/note-history.sh path/to/file.ts
```
## Slots
Multiple tools or agents can write notes on the same object without obliterating each other. Each slot is an independent notes ref.
```bash
mycelium.sh note src/auth.ts --slot skeleton -k observation -m "File structure."
mycelium.sh note src/auth.ts --slot enricher -k summary -m "Rich context."
mycelium.sh read src/auth.ts --slot skeleton # read one slot
mycelium.sh find decision # aggregates across all slots
mycelium.sh doctor # aggregates across all slots
```
`read` and `follow` use the default slot unless `--slot` is specified. `find`, `kinds`, `doctor`, and `prime` aggregate across all slots.
## Migrate (jj)
When jj rewrites commits (amend, rebase, squash), notes on old commit OIDs become orphaned. `migrate` bulk-reattaches them using the `targets-change` edges that mycelium auto-adds in jj repos:
```bash
mycelium.sh migrate --dry-run # show what would be reattached
mycelium.sh migrate # auto-resolve via jj change_id edges
mycelium.sh migrate --map mapping.txt # explicit file: old_oid new_oid change_id
```
Skips conflicts (target already has a note), updates `explains commit:` edges, and is idempotent.
## Platform support
Works on **Linux**, **macOS**, and **Windows** (via Git Bash).
Dependencies: `bash` (3.2+), `git`, and POSIX coreutils (`awk`, `grep`, `sed`, `sort`, etc.). On Windows, Git for Windows ships all of these. Optional: `gitleaks` for secret scanning.
## Agent platform integrations
Both adapters are documented in [`integrations/README.md`](integrations/README.md) and governed by [`PLUGIN-SPEC.md`](PLUGIN-SPEC.md).
### Claude Code
A plugin that auto-injects mycelium context into Claude Code sessions.
**Install via the OpenProse marketplace.** In Claude Code, run `/plugins`, select "Add Marketplace", and enter `openprose/mycelium`. Then enable `mycelium@openprose-mycelium`.
Session start injects the skill and constraint/warning notes. Per-file reads surface exact notes on the current blob. After edits, a per-edit reminder nudges the agent to leave notes on changed files. Works on fresh repos with zero notes.
Requires `jq` and `mycelium.sh` in PATH or at `~/.local/bin/mycelium.sh`.
### Pi
A TypeScript extension for the [Pi coding agent](https://github.com/badlogic/pi-mono) with `/mycelium` controls, `mycelium_context` and `mycelium_note` tools, read-time note surfacing, and post-edit follow-up reminders.
```bash
# Symlink the extension directory
ln -sfn /path/to/mycelium/integrations/pi ~/.pi/agent/extensions/mycelium-pi
```
Dormant by default — activate with `/mycelium on`. SKILL.md is injected on the first turn after activation.
Requires `mycelium.sh` at `~/.agents/skills/mycelium/mycelium.sh` or `~/.local/bin/mycelium.sh`.
## Spiritual predecessors
- [git-appraise](https://github.com/google/git-appraise) — code review stored entirely in git notes. Proved that git notes can carry structured data at scale without touching the working tree.
- [git notes](https://git-scm.com/docs/git-notes) — the substrate itself. Existed since 2010, largely ignored by the ecosystem. GitHub's decision not to surface notes in their UI created the underground we now inhabit.