Skip to main content
Glama
runit-xze
by runit-xze
README.md
# unix-docs — 4.2BSD, cross-referenced. Ask it anything.

<p align="center">
  <img alt="MCP server" src="https://img.shields.io/badge/MCP-server-0d1117?style=flat-square&logo=modelcontextprotocol&logoColor=white"/>
  <img alt="Tests" src="https://img.shields.io/badge/tests-57%20passing-brightgreen?style=flat-square"/>
  <img alt="Node" src="https://img.shields.io/badge/node-%3E%3D20-339933?style=flat-square&logo=node.js&logoColor=white"/>
  <a href="#license"><img alt="Code license" src="https://img.shields.io/badge/code-CC0--1.0-blue?style=flat-square"/></a>
</p>

You're reading this over a network stack whose ideas were first written, in 1983, inside the file you'll find in five seconds with this tool: `sys/netinet/tcp_input.c`.

The whole 4.2BSD kernel and userland — 3,198 files, 681 manual pages, 152 system calls — indexed, cross-referenced, and served to your AI agent over MCP. Every answer comes with a `path:line` citation from a real index. Nothing is recalled from memory. Nothing is guessed.

**Don't guess what 4.2BSD does. Ask it.**

---

## The kernel your internet grew up on

In 1983, a group at Berkeley ran a VAX 11/780 and shipped the release that invented the modern network stack: the BSD socket API, TCP/IP as we know it, `socket()`, `connect()`, the mbuf. Every connection you make today runs on decisions first made in this tree.

That tree — complete, with all of its period-correct warts — is in this repository. Not a mirror to download. Not a rendering. The source, ingested and cross-referenced so you can *read it like a system*:

- **The complete 4.2BSD source tree** — `sys/` kernel and `src/` userland, 3,198 C/assembly/header files (~23 MB)
- **All 681 manual pages** — sections 1–8, l, n, o, nroff-cleaned to plain text
- **The 4.2BSD System Manual, Networking Implementation Notes, and USENIX supplements**
- **The full syscall table** — with argument counts and kernel handlers, parsed from the actual switch table

The reachable proof it's real: a new 4.2BSD program — `jot`, written in period-correct K&R C — compiled and run inside a booted 4.2BSD VAX emulator. Scroll down; the output is there.

## Watch it work

Read a whole data structure instead of one grep line:

```
read_definition({ symbol: "mbuf", path_filter: "sys/h" })
→ ===== sys/h/mbuf.h:28-35 =====
     28 struct mbuf {
     29 	struct	mbuf *m_next;		/* next buffer in chain */
     30 	u_long	m_off;			/* offset of data */
     31 	short	m_len;			/* amount of data in this mbuf */
     ...
```

Find your way around a subsystem you've never seen:

```
list_source_files({ path: "sys/netinet" })
→ ===== sys/netinet =====
  sys/netinet/tcp_input.c  (934 lines)
  sys/netinet/tcp_output.c  (333 lines)
  ... 33 files in all
```

Search for an exact string a keyword index can't express:

```
grep_source({ pattern: "m->m_len", context: 1 })
→ sys/net/raw_usrreq.c-47- 	m->m_next = m0;
  sys/net/raw_usrreq.c:48: 	m->m_len = sizeof(struct raw_header);
```

Resolve a header the way the 4.2BSD compiler would:

```
resolve_include({ name: "<sys/mbuf.h>" })
→ sys/h/mbuf.h  (113 lines) — <sys/...> is the kernel header directory sys/h
```

Get the whole story on a system call — note that `exit` is implemented by `rexit()` in the kernel, a name you would never have guessed:

```
get_syscall({ name_or_number: "1", include_manpage: false })
→ #1 exit

  ## Switch table
  sys/sys/init_sysent.c:107: 1 argument, implemented by rexit()

  ## Kernel implementation
  sys/sys/kern_exit.c:23: rexit()

  ## libc stub
  src/lib/libc/vax/sys/_exit.c

  ## Manual page
  exit(2) - terminate a process
```

## 18 tools, one reference

Every access path you need is a tool, and every tool tells the agent when to use it:

**Documents**
- `list_documents` — list the prose documents
- `get_document_info` — metadata plus a page-by-page overview
- `search_documents` — ranked full-text search with snippets
- `read_pages` — read a page or range of pages

**Manual pages**
- `list_manpages` — list pages, optionally by section
- `apropos` — search names and NAME-section descriptions, like `apropos(1)`
- `search_manpages` — ranked full-text search, optionally restricted to a section
- `read_manpage` — full text of a page, e.g. `read(2)`

**Source code**
- `list_source_files` — browse a directory, like `ls(1)`
- `search_source` — ranked keyword search; files carrying every term rank first
- `grep_source` — exact substring or regex search with context
- `read_source_file` — read a file or a line range, with line numbers
- `find_symbol` — case-sensitive lookup of definitions, declarations, references
- `read_definition` — a symbol's whole definition: function body, struct body, or macro
- `resolve_include` — map `<sys/mbuf.h>` to its file in the tree

**System calls**
- `list_syscalls` — the table, with argument counts and kernel handlers
- `get_syscall` — a full dossier for one call: table entry, switch table, kernel implementation, libc stub, and man page

**Across everything**
- `search_all` — one query across documents, man pages, and source

### Choosing between the search tools

| You want | Use |
|----------|-----|
| The page that documents a concept | `apropos` |
| Every page that mentions a term | `search_manpages` |
| Where an idea lives in the source | `search_source` |
| An exact string, or a regex | `grep_source` |
| Where a symbol is defined and used | `find_symbol` |
| To read the code of a definition | `read_definition` |

The corpus is also exposed as **MCP resources** — enumerable, fetchable URIs:

| URI | Contents |
|-----|----------|
| `unix-docs://documents` | index of the prose documents |
| `unix-docs://syscalls` | the syscall table, with argument counts and handlers |
| `man://{section}/{name}` | one manual page, e.g. `man://2/socket` |
| `doc://{doc_id}/{page}` | one page of a prose document |
| `source://{path}` | one source file, e.g. `source://sys/netinet/tcp_input.c` |

…and three **prompts** for common 4.2BSD work: `trace_syscall` (follow a call from the libc stub into the kernel), `kernel_subsystem_tour` (survey a kernel directory), and `write_utility` (write a program in period-correct K&R C, verifying every library routine against the tree).

## Proof it's real: a program compiled and run on 4.2BSD

`demo/jot.c` is a new utility written for 4.2BSD in period-correct K&R C — no ANSI headers (4.2BSD has none), no `getopt`, explicit old-style declarations. `jot` first shipped in 4.3BSD, so it is a natural addition to a 4.2BSD system.

`demo/sim42.py` and `demo/emulator-jot.py` boot a real 4.2BSD VAX 11/780 on an [Open SIMH](https://opensimh.org) emulator, transfer `jot.c`, compile it with the 4.2BSD C compiler, and run a demonstration suite:

```
$ python3 demo/emulator-jot.py
== compiling with 4.2BSD cc ==
-rwxrwxr-x  1 root        10240 Aug  4 23:39 /tmp/jot
$ /tmp/jot 5                    ->  1 2 3 4 5
$ /tmp/jot 8 1 8 -s ' '         ->  1 2 3 4 5 6 7 8
$ /tmp/jot -c 5 97              ->  a ` _ ^ ]
$ /tmp/jot -r 4 1 10            ->  4.74837 9.21693 9.57097 7.52004
$ /tmp/jot -b hello 3           ->  hello hello hello
$ /tmp/jot -w "n=%g;" 4 1 2 0.25 ->  n=1; n=1.25; n=1.5; n=1.75;
$ /tmp/jot -p 2 4 0 1 0.3       ->  0 0.3 0.6 0.9
$ /tmp/jot 4 4 1                ->  4 3 2 1
```

The whole cycle is unattended — `sim42.py` drives the emulator console over a PTY, handling the kernel's automatic-reboot halts and csh's here-doc quirks. This is not a screenshot of the past; it is a system you can still compile against.

`demo/syscall-dossier.mjs` shows the corpus doing its job: a small MCP *client* that assembles a fully-cited dossier for any syscall — table entry, man page, kernel routine, callers, and related prose — in one run:

```
$ node demo/syscall-dossier.mjs socket
## 1. The call
> MCP: get_syscall("socket", include_manpage: true)
#97 socket
sys/sys/init_sysent.c:203: 3 arguments, implemented by socket()
sys/sys/uipc_syscalls.c:24: socket()
src/lib/libc/vax/sys/socket.c
socket(2) - create an endpoint for communication
```

## Get it running in two minutes

```bash
git clone https://github.com/runit-xze/unix-docs-mcp
cd unix-docs-mcp
yarn
yarn start          # launch the MCP server over stdio
yarn test           # run the test suite (57 passing)
```

Configure it as an MCP server for any MCP client, e.g. in `opencode.json`:

```json
{
  "mcp": {
    "unix-docs": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/unix-docs-mcp/src/index.js"]
    }
  }
}
```

Memory is honest: the server lazy-loads each corpus on first use. Indexing the full source tree takes ~1.7 s and brings resident memory to ~390 MB (the man-page corpus adds ~20 MB). Clients that only use the man pages never build the source index. If you run many MCP servers in one session, keep this in mind when sizing the host.

## Under the hood

`scripts/ingest.mjs` builds the prose corpus from OCR'd PDFs. `scripts/ingest-dev.mjs` builds the man page, source, and syscall corpora from a 4.2BSD distribution. Two things are derived at runtime rather than baked into `data/`, so they can never drift from the committed tree: the argument counts and kernel handlers come from parsing `sys/sys/init_sysent.c`, and the `apropos` descriptions come from the NAME section of each man page.

The cross-reference index (`find_symbol`, `read_definition`) is what makes this different from a pile of text: a symbol's definitions, declarations, and every reference, ranked and `path:line`-cited, so an agent can answer "what calls `tcp_input`" by reading, not by guessing.

## Build on it

This project's own code is dedicated to the public domain under [CC0](LICENSE) — take it, adapt it, ship it. The bundled 4.2BSD material is a different story; see the [license section](#license).

Good first contributions: new ingest targets, better symbol classification, and demos that push the emulator further. The test suite is 57 tests and the e2e test drives the real stdio protocol.

## License

Two different licenses apply to different parts of this repository:

- **This project's own code** — the server, library, script, test, and demo files under `src/`, `scripts/`, `test/`, and `demo/` — is dedicated to the public domain under [CC0 1.0 Universal](LICENSE).
- **The bundled 4.2BSD material** under `data/` (source code, man pages, and prose documentation) is *not* covered by the CC0 dedication. It carries a mix of Berkeley and AT&T copyrights and has no single clean license; see [LICENSE.data](LICENSE.data) for the details, the TUHS [4.2BSD distribution](https://www.tuhs.org/Archive/Distributions/UCB/4BSD/4.2BSD/) for provenance, and the individual file headers for the applicable terms.

TDQS

A4.2/5.0

Scored across 13 tools

Disambiguation5/5

Each tool targets a distinct corpus (documents, manpages, source, syscalls) with distinct actions (list, get, search, read, find). The descriptions clearly differentiate between search_documents, search_manpages, and search_source, so there is no real ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern (list_, get_, search_, read_, find_). Even search_all fits the verb+noun pattern with 'all' as the object. No mixed naming conventions are present.

Tool Count5/5

13 tools is well-scoped for a multi-corpus documentation server. Each corpus (documents, manpages, source, syscalls) has just the right set of operations, and search_all provides a cross-corpus entry point. No redundant tools exist.

Completeness4/5

The tool set covers the full read-only lifecycle for documents (list/get/search/read), manpages (list/search/read), source (search/read/find), and syscalls (list/get). A minor gap is the lack of a directory listing for source files, but search_source and find_symbol partially mitigate this.

Maintenance

ActivityMaintained
ResponsivenessSyncing