# repos-as-docs (rasd) — full documentation

> This is the complete documentation for repos-as-docs, as plain markdown,
> for LLMs and agents. It mirrors https://repos-as-docs.com/docs. The tool it
> describes works the same way: plain files, greppable, no server.

repos-as-docs ("rasd") keeps real git clones of your direct dependencies in a
shared machine-wide store, matched to the versions your project installs —
tests, docs, examples, full history — and writes a plain-markdown index into
your project that any coding agent can grep. It also tracks explicit
non-dependency "reference" repositories you study for architecture. Files, not
servers: no MCP server, no daemon.

- Homepage: https://repos-as-docs.com/
- Source: https://github.com/chunkzer/repos-as-docs
- Package: https://www.npmjs.com/package/repos-as-docs
- Concise markdown: https://repos-as-docs.com/llms.txt
- License: MIT

Every command answers `--help`, and `rasd help <cmd>` works too.

## Install

Two ways, pick one.

The npm package ships the Bun-powered `rasd` bin — you need Bun on your PATH:

```sh
bun add -g repos-as-docs   # or: bunx repos-as-docs
```

Or grab a standalone single-file binary for your platform from the GitHub
Releases page (https://github.com/chunkzer/repos-as-docs/releases). Built with
`bun build --compile`, it embeds the runtime — nothing else to install, no Bun
required.

## Which projects work

Any project with a `package.json` — that's the manifest rasd reads, and its
absence is the only hard blocker. Exact-version pinning additionally uses a
supported lockfile: `bun.lock`, `package-lock.json` (v2/v3, npm >= 7), or
`pnpm-lock.yaml`.

No lockfile? Sync still runs. Without one, rasd pins each dependency's default
branch instead of an installed version, and says so in the index.

Only direct dependencies are cloned, gated by the blocklist and a size check
(fail-closed: a repo whose size can't be confirmed under the threshold is a
visible skip, not a silent clone). There's no daemon — the network is touched
only when you run an acquisition command (`sync`, reference-adding `ref`,
`water`).

## Quickstart

```sh
cd your-project
rasd init
```

That's it — your dependencies' repos are cloned into the shared store and
indexed in `.rasd/index.md`, and your `CLAUDE.md`/`AGENTS.md` tell agents where
to look. For a big dependency list, run `rasd login` first so repo-size checks
aren't rate-limited.

## rasd init

```sh
rasd init [--no-sync] [--verbose]
```

Sets up rasd for the project, in four steps:

1. Ensures `.rasd/` is gitignored — its symlinks have absolute targets, so
   committing them breaks on other machines.
2. Writes a starter `rasd.json` showing every knob (never overwrites yours).
3. Runs a sync (skip with `--no-sync`).
4. Appends a discovery block to `CLAUDE.md`/`AGENTS.md` — whichever already
   exist. The block is what makes agents read the clones unprompted:

```
## Dependency source (rasd)

This project's direct dependencies are cloned locally. Before
fetching a dependency's source or docs from the web, read
`.rasd/index.md`: it lists a local path per dependency (installed
version and default branch) to grep and read directly — full
source, tests, and git history, no rate limits. …
```

Idempotent: re-running refreshes the block in place (it lives between
`<!-- rasd:begin -->`/`<!-- rasd:end -->` markers) and adds nothing twice.

If you keep neither file, rasd prints the block rather than creating one. That
file is your project's instruction surface for every agent that touches it —
appending a removable block to one you maintain is fair, opening one with a
section about rasd is not.

## rasd sync

```sh
rasd sync [--refresh] [--mode global|project] [--verbose]
```

Reads your manifest and lockfile, updates the shared store, and regenerates
`.rasd/index.md` (for agents and humans) and `.rasd/index.json` (for tools).
Run it after dependency changes.

The first sync clones each direct dependency's repo (bare, `blob:none`
partial) and adds two worktrees: one pinned at your installed version, one at
the default branch. Warm syncs fetch and re-point only what moved, make zero
forge API calls for repos already in the store, and stay near-silent —
steady-state lines are suppressed unless you pass `--verbose`. A first sync
logs one line per dependency:

```
✓ execa 9.6.0        cloned
✓ zod 3.25.76        cloned
– typescript 5.8.3   skipped: blocklisted (rasd.json or shipped defaults)
```

Skipped dependencies appear in the index with their reason — the blocklist,
the size gate (`repo is 2381 MB, over the 100 MB size gate`), no repository URL
in the registry metadata, or a transient failure (registry lookup, clone, size
check). Size checks fail closed: an unconfirmed size means skip, not clone, and
the sync summary tells you to `rasd login` (or set `GITHUB_TOKEN`) and re-run.

`--refresh` bypasses the registry cache (npm metadata 24h, repo sizes 7d).
`--mode project` materializes real worktrees under `.rasd/` instead of
symlinks, for sandboxes that refuse to traverse symlinks outside the project;
`--mode` overrides `rasd.json` for this run only.

## rasd login / rasd logout

```sh
rasd login [--status [--json]]
rasd logout
```

Authorizes this machine with GitHub via OAuth device flow and stores a
rasd-owned token used only for public repo size checks. The token requests no
scopes — public read-only — and lifts the size-check budget from 60 anonymous
requests/hour to 5,000. If `GITHUB_TOKEN`/`GH_TOKEN` is set, the environment
always takes precedence.

`rasd login --status` shows the stored token state and which auth rung sync
will use; `rasd logout` removes the token from this machine.

## rasd ref

```sh
rasd ref list [--json]
rasd ref add <repository[#ref]> [--as <name>] [--why <purpose>]
              [--directory <path>] [--allow-large]
rasd ref remove <name>
rasd ref review <name> [--checkout baseline|candidate]
rasd ref review --all
rasd ref reviewed <name> [--checkout ...] [--exclude <path>...]
rasd ref unreview <name> [--checkout ...]
```

Adds, lists, or removes reference repositories — source you study or borrow
ideas from without depending on it. A reference never masquerades as a package:
it doesn't participate in semver upgrade ranking, and it lives in its own
section of the index. It's for keeping an inspiring project on disk (and
greppable by your agent) without pretending it's a dependency.

```sh
rasd ref add honojs/hono --why "Product architecture inspiration" --allow-large
rasd ref add owner/repo#v1.2.0 --as architecture
```

Adding resolves the selected ref (the default branch when omitted) to an exact
commit and records that accepted reference point in `rasd.json`, so every
collaborator shares the same baseline. It then creates
`.rasd/references/<name>` (the accepted commit) plus a refreshable
`.rasd/reference-heads/<name>` (the current default-branch review candidate).
References go through the same first-clone size gate as dependencies, but not
the blocklist, and they share bare clones and worktrees with any dependency at
the same repo/ref.

With no repository argument, `rasd ref` lists the configured references
(`--json` for machine output).

- `--as` — project-local alias (defaults to the repository name)
- `--why` — short purpose shown to humans and agents in `.rasd/index.md`
- `--directory` — expose a safe monorepo subdirectory from `rasd path`
- `--allow-large` — explicitly bypass the first-clone size gate
- `--checkout` — review the accepted baseline (default) or exact indexed candidate
- `--review` — gather licensing signals without changing policy
- `--review-all` — gather every unreviewed/review-required checkout
- `--reviewed` — record a complete verdict; repeated `--exclude` paths replace the set
- `--clear-review` — explicitly un-review the selected commit and block inheritance
- `--exclude` — literal POSIX subtree omitted from reads-by-default; requires `--reviewed`
- `--remove` — remove a configured reference and regenerate the index

For review operations, an existing alias wins; otherwise a repository spec
updates the uniquely matching configured repository. See "Reference licensing
boundaries" below for the review workflow.

Track a reference over time with `rasd whatsnew <name>` (what changed since you
accepted it) and `rasd water <name>` (refresh the candidate; `--accept` to
advance the baseline after review).

## Reference licensing boundaries

A reference checkout starts `unreviewed`, and absence of review data never means
license-clean. This matters because reference repos are code you might borrow
from — unlike a dependency, which you merely consume. `.rasd/index.md` is the
authority for the accepted baseline and candidate statuses.

`rasd ref review <name>` gathers the signals — root and nested license files,
root-license path tokens, and conventional enterprise pocket directories — and
changes no policy. rasd does not classify licenses or promise compliance. A
person decides, then records the complete verdict:

```sh
rasd ref review hono                    # gather licensing signals
rasd ref reviewed hono --exclude ee     # record the human verdict
rasd ref review hono --checkout candidate   # when re-review is required
```

Repeated literal `--exclude` paths *replace* the set rather than adding to it.
Excluded subtrees are then absent from ordinary `rg`, recursive grep, `find`,
and agent exploration: rasd uses a real sparse worktree whenever a boundary
exists, and keeps the last known excludes provisionally applied when a `water`
candidate's signals change. It also writes `.rasd-licensing.md` into real
worktrees as a secondary reminder — the generated index stays the source of
truth.

This is friction, not an information barrier. The shared Git object store keeps
full history, so an operator can reconstruct excluded code with Git. What rasd
enforces is a recorded human reference-use verdict, and it tells agents to stop
before crossing it.

## rasd list

```sh
rasd list [repo-or-package] [--json]
```

Inside a rasd project: this project's dependencies as rasd sees them — which
have backing clones (and the latest published version if you're behind), and
which were skipped and why.

```
 clone  execa@9.6.0
 clone  zod@3.25.76        (latest: 4.1.8)
  skip  typescript@5.8.3   blocklisted (rasd.json or shipped defaults)

2 cloned, 1 skipped — full paths and details: .rasd/index.md
```

Anywhere else: the machine-wide view — every repo in the shared store, grouped
by host, with its worktrees and the projects using it. Pass `owner/repo` (or,
inside a project, a package name) for one repo's full paths; `--json` for
machine-readable output.

```
shared store ~/.local/share/rasd — 14 repos, 29 worktrees

github.com
  colinhacks/zod   main  v3.25.76  → 2 projects (rasd list colinhacks/zod)
  honojs/hono      main  v4.8.3    → your-app
  sindresorhus/execa  main  v9.6.0  → your-app
```

## rasd path

```sh
rasd path <pkg-or-reference> [--head]
```

Prints the local worktree path for a dependency or reference and nothing else,
so it composes: `cd $(rasd path execa)`. The pinned version (or a reference's
accepted commit) by default, the default branch with `--head`. Exits 1 with the
reason on stderr when the source isn't cloned.

## rasd whatsnew

```sh
rasd whatsnew [pkg-or-reference] [--head] [--json] [--stat|--diff]
```

Without a name: dependencies ranked by how far behind your installed version is
(majors > minors > patches), followed by any reference repositories changed
since their last accepted point.

```
zod    3.25.76 -> 4.1.8   (1 major behind)
hono   4.8.3   -> 4.9.0   (1 minor behind)
execa  9.6.0   -> 9.6.1   (1 patch behind)
```

With a dependency: the deep dive — the commit log between your pinned ref and
the latest published tag, straight from the store clone. Pipe it to an LLM and
ask what upgrading buys you. `--head` diffs against the default branch instead;
`--json` makes the ranking machine-readable.

With a reference: commits from its exact accepted baseline to the current
default-branch candidate. `--stat` adds changed-file statistics, `--diff` emits
the complete patch, and diverged/rewritten upstream history is reported
explicitly.

No network: refs are as fresh as your last `rasd sync` or `rasd water`.

## rasd fork

```sh
rasd fork <pkg> [--into <path>] [--branch <name>] [--upstream-as <name>]
          [--no-watch-upstream] [--dry-run] [--yes]
rasd fork publish <pkg> [--to <url>] [--public] [--org <org>] [--dry-run] [--yes]
```

Turns a cloned dependency into a local fork you can edit. Clones the upstream
repo into `./forks/<repo>` (override with `--into`; the clone borrows objects
from the store, so it's fast), checks out a working branch (default
`rasd/patches`), gitignores the fork directory, records the fork in `rasd.json`
so `rasd water` can find it, and prints the `package.json` wiring:

```
"hono": "file:./forks/hono"
```

It never edits `package.json` — that wiring is yours to apply. If the package
has a build step, a `file:` install may need its built output or a `prepare`
script; the command warns you to check. `--dry-run` prints the whole plan
without executing anything.

Keeping an eye on upstream. Once you rewire `package.json` to the fork, the
original package leaves your manifest — and rasd reads the manifest, so the
next `sync` would drop the upstream clone and stop tracking it. That is the
moment you most need it: watering a fork means merging in what upstream did
after you forked.

So `fork` also registers upstream as a reference repository named
`fork-<pkg>`, pinned at the exact commit you forked from. Because references
live in `rasd.json` rather than the manifest, that clone survives the
dependency's removal, and the fork point is the baseline the delta is measured
against:

```sh
rasd whatsnew fork-hono   # what upstream did since you forked
rasd water fork-hono      # refresh the upstream review candidate
rasd water hono           # merge upstream into the fork itself
```

- `--upstream-as <name>` — name for the upstream reference (default `fork-<pkg>`)
- `--no-watch-upstream` — do not register the upstream reference or sync

Registration is best-effort: if it fails — most often because the name is
already taken by an earlier fork of the same package — the fork is still
complete and rasd prints the `rasd ref` command to run yourself.

Publishing is its own verb. `rasd fork publish <pkg>` pushes the fork to a remote and prints the dependency
spec to use instead. The remote comes from `--to`, else `publishTemplate` in
`rasd.json`, else the same key in `~/.config/rasd/config.json` —
`{owner}`/`{repo}` placeholders, e.g. `"forgejo:me/{owner}--{repo}.git"`. Repo
creation is the forge's job (Forgejo/Gitea push-to-create makes it automatic,
private by default). With none set, it falls back to GitHub via `gh`: a private
standalone copy. `--public` makes a real public GitHub fork instead (GitHub
can't make forks of public repos private); `--org` publishes under an org.

Tiny change? You don't need a fork — your package manager's patch feature
(`bun patch <pkg>`) is lighter.

## rasd water

```sh
rasd water [pkg-or-reference] [--head] [--accept]
           [--accept-unreviewed] [--force] [--json]
```

Waters local forks by merging upstream into them. With a name, waters that fork
or reference; with none, every fork and reference recorded in `rasd.json`. For
a fork, the merge target is the latest published tag (`--head` for the default
branch instead).

Dirty forks are skipped so every merge starts from a revertible state, and a
clean merge prints the exact `git reset --hard` to undo it. Conflicted merges
are left in place — conflicted files, merge-base, and the upstream log printed
— ready for you or an agent to resolve, with the `merge --abort` escape hatch
alongside.

For a reference repository, watering refreshes its default-branch review
candidate without moving the accepted baseline — so the delta you'd review
stays intact. After review, `--accept` advances the committed baseline to that
exact reviewed candidate, no re-fetch.

Acceptance records the candidate you actually reviewed. Two independent
overrides gate the edge cases: `--force` permits diverged or rewritten Git
history, and `--accept-unreviewed` is separately required to accept
licensing-unknown code. Neither implies the other.

## rasd skill

```sh
rasd skill [install|remove|status] [--project] [--all]
```

Installs a bundled skill that teaches coding agents how to use rasd — which
command answers which question, and where the licensing boundaries are. Claude
Code, Codex, and Cursor all read the same `SKILL.md` format from their own
directory, so one bundled file serves every agent on the machine.

The skill ships inside the package, so it always matches your installed rasd —
no fetch, nothing to drift. By default only agents already present are offered.

- `--project` — install into `./.claude/skills` instead of your home directory
  (committed, so everyone on the project gets it)
- `--all` — install for every known agent, even ones not detected here

The first `rasd init` on a machine offers this once and records the answer
either way, so it never asks twice. The prompt is skipped entirely without a
terminal — rasd is routinely run by agents and in CI, where an offer must never
block. `RASD_NO_PROMPT=1` or `CI` opt out explicitly.

`rasd skill status` shows what is installed where. `rasd skill remove` and
`rasd uninstall` remove only the files rasd wrote, never skills you added
yourself.

## rasd footprint

```sh
rasd footprint [--json]
```

Inside a synced project (the nearest parent with `.rasd/index.json`): the unique
shared bare repos and worktrees that project points at. Elsewhere: the
machine-wide store for all projects.

Size snapshots are cached at project and machine scope, invalidated by sync and
refreshed after a successful one, so the common case costs no disk walk. Known
stale projects are always measured live and reported with the sync they need,
and indexed checkout paths that can't be resolved are reported explicitly rather
than silently omitted from the total.

Also available as `rasd --footprint`.

## rasd clean

```sh
rasd clean
```

This project is done with rasd: drops its `.rasd/`, releases its claims on the
store, and prunes what nothing else uses.

## rasd gc

```sh
rasd gc
```

Prunes store entries that no project references anymore. `sync` and `water`
run this themselves when they finish, so you rarely need it by hand — a
refreshed reference candidate supersedes the previous checkout, and for a large
repo those add up fast. `RASD_NO_AUTO_GC=1` opts out of the automatic sweep.

## rasd evict

```sh
rasd evict [--days <n>] [--dry-run] [--yes] [--json]
```

Delete worktrees rasd has not handed out in a while (default 60 days). This is
not gc: gc removes what nothing *references*, evict removes checkouts that are
still referenced but have gone *cold*.

Safe because the bare clone keeps all the history — an evicted worktree costs a
`rasd sync` to rebuild, not the data. `--dry-run` lists what would go.

Usage is recorded by rasd itself, not read from filesystem access times, which
any backup or search-indexing pass would refresh. A worktree with no recorded
use is never evicted: no record means rasd has not been watching it long enough
to judge, not that it is unused.

## rasd uninstall

```sh
rasd uninstall [--yes]
```

Deletes the whole store and every project's generated files, with
confirmations (`--yes` to skip). Also removes the rasd-owned GitHub token at
`~/.config/rasd/auth.json`.

## Configuration

`rasd.json`, committed in your project root. `rasd init` writes a starter
showing every knob:

```json
{
  "blocklist": [],
  "allowlist": [],
  "sizeGateMb": 100,
  "leanAboveMb": 250,
  "mode": "global",
  "refTemplate": {},
  "references": {},
  "publishTemplate": ""
}
```

- `blocklist` — packages never to clone, on top of the shipped defaults
  (`@types/*`, `typescript`, `bun-types` — types-and-tooling repos that cost
  gigabytes and answer no "am I using this library well?" question). Patterns
  are exact names or a trailing-`*` prefix glob.
- `allowlist` — opt specific packages past the size gate, including repos whose
  size can't be confirmed.
- `sizeGateMb` — repos larger than this are skipped, with the measured size in
  the skip reason. Default 100.
- `leanAboveMb` — at or above this repo size, only your installed version is
  checked out; the default-branch worktree is left for `sync` to materialise
  when something asks. Default 250, `0` disables. Nothing is lost: `whatsnew`
  reads the bare clone, and the index states why the checkout is absent.
- `mode` — `global` (symlinks into the shared store, the default) or `project`
  (real worktrees under `.rasd/`, for sandboxes that refuse symlink traversal).
- `refTemplate` — per-package tag template for repos with unusual tag schemes,
  e.g. `{"left-pad": "release-{version}"}` (`{version}` and `{name}`
  placeholders).
- `publishTemplate` — default remote for `rasd fork --publish`, with
  `{owner}`/`{repo}` placeholders.
- `references` — written by `rasd ref`: each reference repository with the exact
  accepted commit and its recorded licensing verdict. It's committed, so every
  collaborator shares one baseline and one review decision.
- `forks` — written by `rasd fork`: the recorded path and branch of each local
  fork, which is how `rasd water` finds them.

Machine-level defaults live in `~/.config/rasd/config.json` (honors
`XDG_CONFIG_HOME`); today that's `publishTemplate`. The project file wins.

## Generated files

`.rasd/` is gitignored and rebuilt on every sync: `index.md` (the agent-facing
index), `index.json` (its machine-readable twin, used by
`list`/`path`/`whatsnew`), and `sources/` / `heads/` — per-dependency views of
the pinned version and the default branch. Configured references add
`references/<name>` (the accepted commit) and `reference-heads/<name>` (the
review candidate). In `global` mode those are symlinks into the shared store
(`~/.local/share/rasd`, honors `XDG_DATA_HOME`); in `project` mode, real
worktrees.

The index is plain markdown — one entry per direct dependency, skips visible,
never silent:

```markdown
## zod (3.25.76)

- installed version (v3.25.76): /Users/you/app/.rasd/sources/zod
- default branch: /Users/you/app/.rasd/heads/zod
- latest published: 4.1.8 (run `rasd whatsnew zod`)

## typescript (5.8.3)

- not cloned: blocklisted (rasd.json or shipped defaults)

# Reference repositories

## hono  (Product architecture inspiration)

- accepted commit (a1b2c3d): /Users/you/app/.rasd/references/hono
- baseline licensing: **REVIEWED** (explicit from a1b2c3d4e5f6)
  - absent by policy: ee
- default branch: /Users/you/app/.rasd/reference-heads/hono
- candidate licensing: **REVIEW-REQUIRED** (provisional)
```

References sit in their own clearly-separated section — never mixed in with
packages. Forked dependencies get an extra line pointing at the local fork.
Each reference checkout carries its licensing status, any subtrees absent by
policy, and declared excludes that matched no path. Paths with no boundary may
be symlinks into the shared store; boundary-bearing paths are real sparse
worktrees backed by that same store.

Everything under the listed paths is third-party text; the index says so to
agents explicitly — data, not instructions.

## A note on trust

Repo contents are third-party text, and the `repository` field on a registry is
unverified metadata. rasd is for understanding your dependencies, not auditing
them — and the generated index reminds agents to treat what they read in cloned
repos as data, not instructions. (An agent browsing github.com has the same
exposure; rasd just says it out loud.)
