---
title: "Tools"
description: "Commands, packages, storage paths, and root resolution for the eng.rip tools."
type: reference
canonical_url: https://eng.rip/tools/
---

# Tools

| Tool | Command | Purpose | Documented version | Documentation |
| --- | --- | --- | --- | --- |
| tisket | `tisket` | Issue tracker | 0.2.5 | [tisket](https://tisket.eng.rip/) |
| zettel | `zettel` | Notes with provenance | 0.3.0 | [zettel](https://zettel.eng.rip/) |
| diataxis | `diataxis` | Typed documentation | 0.1.1 | [diataxis](https://diataxis.eng.rip/) |
| gaff | `gaff` | Context re-injection for coding agents and git hook checks | 0.1.4 | [gaff](https://gaff.eng.rip/) |
| almanac | `almanac` | Agent skill libraries | 0.2.5 | [almanac](https://almanac.eng.rip/) |
| missouri | `missouri` | Filesystem-state tests for CLIs | 0.2.5 | [missouri](https://missouri.eng.rip/) |
| tundish | `tundish` | Local queues that deliver program output to agents | 0.1.2 | [tundish](https://tundish.eng.rip/) |
| mdstore | No CLI; Rust import path `mdstore` | Shared storage library under tisket, zettel, almanac, and diataxis | mdstore-core 0.5.0 | [mdstore repository](https://github.com/cjohnhanson/mdstore) |

## Packages and files

### tisket

```sh
cargo install --locked tisket
```

| Package manager | Package |
| --- | --- |
| Homebrew | `cjohnhanson/tap/tisket` |
| uv | `tisket` |
| npm | `tisket` |

| File or setting | Content |
| --- | --- |
| `tisket.yml` at the repository root | One key, `tisket_dir`, with default `.tisket` |
| `.tisket/<project>/` | Issue files |
| `.tisket/<project>/.closed/` | Closed issue files |

### zettel

```sh
cargo install --locked zttl
```

| Package manager | Package |
| --- | --- |
| Homebrew | `cjohnhanson/tap/zettel` |
| uv | `zttl` |
| npm | `@cjohnhanson/zttl` |

| File or directory | Content |
| --- | --- |
| `zettel.yml` | One key, `zettel_dir`, with default `.zettel` |
| `.zettel/` | Notes in one flat directory |

### diataxis

```sh
cargo install --locked diataxis
```

Diataxis is available through crates.io only.

| File or setting | Content |
| --- | --- |
| `diataxis.yml` | `docs_dir`, with default `docs`, and an optional `title` |
| `docs/` | Documentation pages |

### gaff

```sh
cargo install --locked gaff
```

| Package manager | Package |
| --- | --- |
| Homebrew | `cjohnhanson/tap/gaff` |
| uv | `gaffr` |
| npm | `gaffr` |

| File or location | Content |
| --- | --- |
| `.gaff/gaff.yml` | Repository configuration |
| `$HOME/.config/gaff/gaff.yml` | User configuration for every repository; the only location for guards |
| `$HOME/.config/gaff/handlers.yml` | The only location for handlers |
| Gaff's state directory, outside the repository | Session counters |

A repository adds entries to the user configuration. It never overrides a user entry with the same name.

### almanac

```sh
cargo install --locked lmnc
```

| Package manager | Package |
| --- | --- |
| Homebrew | `cjohnhanson/tap/almanac` |
| uv | `lmnc` |
| npm | `@cjohnhanson/lmnc` |

| File or setting | Content |
| --- | --- |
| `almanac.yml` | Manifest with `library`, default `skills`, and pinned `skills` entries |
| Library directory | Skill files |

### missouri

```sh
cargo install --locked missouri
```

| Package manager | Package |
| --- | --- |
| Homebrew | `cjohnhanson/tap/missouri` |
| uv | `msri` |
| npm | `@cjohnhanson/msri` |

| File or setting | Content |
| --- | --- |
| `missouri.yml` at the project root, or `.missouri/missouri.yml` | Project configuration |
| `.missouri/missouri.yml` within each state directory | That state's transitions |
| State directories | Filesystem states and expected results |
| `-d, --dir <DIR>` | Root directory containing states; default `.` |

### mdstore

```sh
cargo add mdstore-core --rename mdstore
```

The crate is `mdstore-core`. The Rust import path is `mdstore`.

`stores.yml` sits beside a tool's marker file and declares other stores. Tisket, zettel, diataxis, and almanac read it.

| Field | Meaning |
| --- | --- |
| `format` | Format version, `2` |
| `shared` | Optional declaration that other users clone the store |
| `stores` | List of store declarations |
| `alias` | Local name for a declared store |
| `path` | Path source |
| `git` | HTTPS git source; optional `rev` |
| `blob` | HTTPS prefix with an `index.txt` |

Each store entry has an `alias` and exactly one source: `path`, `git`, or `blob`.

## Shared commands

| Usage | Tools | Result |
| --- | --- | --- |
| `<tool> docs [topic]` | All six CLIs | Bundled documentation |
| `<tool> docs --all` | All six CLIs | Every bundled page in one stream |
| `<tool> prime` | tisket, zettel, diataxis, gaff, almanac | Short tool description and usage for an agent's context |
| `<tool> store list` | tisket, zettel, diataxis, almanac | Declared stores |
| `<tool> store sync` | tisket, zettel, diataxis, almanac | Remote stores fetched into a local cache |
| `<tool> store root <path>` | tisket, zettel, diataxis, almanac | Configured root store for that tool |
| `<tool> serve` | tisket, zettel, almanac | MCP server |
| `<tool> check` | tisket, zettel, diataxis, almanac, gaff | Reports broken references, links, and store problems; gaff validates `.gaff/gaff.yml` |
| `missouri validate` | missouri | Validates `missouri.yml` files without running tests |

Missouri has no `prime` command. MCP servers are read-only by default; almanac's server is always read-only.

## Root resolution

Tisket, zettel, almanac, and diataxis share the following rule.

| Invocation or condition | Resolution |
| --- | --- |
| `--root <dir>` | Names the directory literally. It must contain the tool's marker file. No walk or fallback occurs. |
| No `--root` | The nearest marker file at or above the working directory wins. |
| No store found, read command | Falls back to the configured root store and reports the fallback on stderr. |
| No store found, write command | Fails and names `--home`; never falls back. |
| `--home` | Uses the configured root store wherever the command runs. |

The marker files are `tisket.yml`, `zettel.yml`, `almanac.yml`, and `diataxis.yml`, respectively.

The walk has two further constraints:

- A marker must be a regular file.
- The walk stops at the first directory the invoking user does not own. A marker in a shared ancestor captures nothing.

| Root setting | Behavior |
| --- | --- |
| `~/.config/<tool>/config.yml` | Fixed config path for that tool |
| `root_store` | Configured root store path |
| `<tool> store root <path>` | Sets the tool's root; changing an existing setting requires `--force` |
| Home directory | Comes from the passwd database, not `$HOME` |
| Environment variables | Take no part in resolution |
| Write target on stderr | Printed unless the target is the working directory's own store or `--root` names it |

Each tool reads its own configuration, so `store root` sets the root for that tool alone. One directory can be the root store for all four tools.

Gaff and missouri do not use this rule. Gaff reads the repository's `.gaff/gaff.yml` plus the user configuration. Missouri reads the directory named by `--dir`.
