Skip to main content

missouri

Show-me state. End-to-end testing as directed graphs of filesystem states.

Missouri tests a CLI tool by modeling its behavior as a directed graph of filesystem states. A state is a directory. It holds the exact files that must exist at that point in the test. A transition is a shell command. Missouri runs the command, then compares the resulting directory against the target state directory, byte for byte.

There is no assertion language. The expected state is the directory.

How it works

A test suite is a set of directories, and each directory is a state. Each state's .missouri/missouri.yml declares its transitions. A transition names a command to run and the state directory that the filesystem must match after the command. Missouri finds every path through the graph, runs each path in a temp directory with a cleared environment, and diffs the result against the target.

clean/                  # starting state (empty project)
  .missouri/
    missouri.yml        # transitions: [{command: "echo hello > out.txt", target: ../built}]
built/                  # expected state after command
  .missouri/
    missouri.yml
  out.txt               # file that should exist: contains "hello"
$ missouri run
✓ [1/1]
PASS clean → built 14ms

1 passed, 0 failed, 1 step in 14ms

A state can have several outgoing transitions, which is branching, and several states can point at the same target, which is convergence. The directory tree is the test suite.

Isolation

Every command runs with env_clear(). The process inherits no environment variable from the host. Declare every variable a test needs in the test config. The test then behaves the same on your machine and in CI.

For stronger isolation, missouri also runs a command inside a nix shell or a Docker container.

Beyond filesystem diffs

A state can also declare assertions. An assertion is a shell command, and its exit code and output decide whether it passes. A transition can declare a custom comparator for a file that a byte-for-byte diff reads wrong, and a background service for a command that needs a server running. An agent assertion hands a judgment call to an LLM.

Install

The package is msri on PyPI and npm, because missouri was taken. On npm it carries the scope, @cjohnhanson/msri, because the registry refuses msri as too close to names it already holds. The command is missouri everywhere, and both names install together.

cargo install --locked missouri
brew install cjohnhanson/tap/missouri
uv tool install msri
npm install -g @cjohnhanson/msri

cargo install builds from source. It needs Rust 1.88 and a C compiler. The other three carry a prebuilt binary for macOS and Linux, x86-64 and arm64, published by a tagged release.

To build the unreleased main branch:

cargo install --locked --git https://github.com/cjohnhanson/missouri

Or run it without installing:

uvx msri run
npx @cjohnhanson/msri run

From that point the releases page also carries prebuilt archives and a .deb. Each archive holds the binary and the man page. Install a .deb with dpkg -i: it is a file, not a repository, so apt-get install does not reach it.

Check the install with missouri --version.

Usage

missouri init              # set up a new project
missouri state add <name>  # create a state directory
missouri run               # execute all test paths
missouri run -v            # verbose output
missouri list              # show states, transitions, paths
missouri validate          # check graph is well-formed
missouri report            # generate a report from a recorded run
missouri docs [topic]      # bundled documentation

Documentation

Related

  • tisket. An issue tracker. Markdown issues with YAML frontmatter, in the repository.
  • zettel. Zettelkasten notes for a repository.
  • almanac. An agent skill index over pluggable sources.
  • gaff. A context-lifecycle handler for coding agents.
  • mdstore. The frontmattered markdown library that tisket, zettel, and almanac store documents with.

License

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

msri-0.2.3.tar.gz (125.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

msri-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl (3.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64musllinux: musl 1.1+ x86-64

msri-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl (2.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64musllinux: musl 1.1+ ARM64

msri-0.2.3-py3-none-macosx_11_0_arm64.whl (2.8 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

msri-0.2.3-py3-none-macosx_10_12_x86_64.whl (2.9 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file msri-0.2.3.tar.gz.

File metadata

  • Download URL: msri-0.2.3.tar.gz
  • Upload date:
  • Size: 125.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for msri-0.2.3.tar.gz
Algorithm Hash digest
SHA256 182286afe04ede245ec5117642d5ffbbd8ea4a15bbcfb4dff7d40138dd5641eb
MD5 9325a74846386e7fd01192c55692708a
BLAKE2b-256 7b020f0641ba0c705797357c59ead1c0c1b018edca680b47c8134f5e791b1ddb

See more details on using hashes here.

File details

Details for the file msri-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: msri-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 3.2 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for msri-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 4d887f6f1d93b4d38b7fd5e84db5c665af4316a092c3bd743bcbb96ba2868f89
MD5 e02d12b8862d4e5a3a0e46a20e230cc5
BLAKE2b-256 8805f40815508d56373f6b0285be47f45189c6caa28c5f7d293ec31af59de43c

See more details on using hashes here.

File details

Details for the file msri-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl.

File metadata

  • Download URL: msri-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl
  • Upload date:
  • Size: 2.9 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64, musllinux: musl 1.1+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for msri-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ec08b4d964ffd7c25b06a47b024f06ae0657ec1bbbae547a6a1a78c63ae0a89d
MD5 85099142b9e58530868f2abe13954e1a
BLAKE2b-256 e1d55f5fc381ffe4a304d54bc7539ce07775ecaee3f84d2f385034fdcdd88e2d

See more details on using hashes here.

File details

Details for the file msri-0.2.3-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: msri-0.2.3-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 2.8 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for msri-0.2.3-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 10999af90ca3fb0f352667ad63e9bece32966a745d33c809c84c945bf9f80b30
MD5 4159c64561cb0a7f8507d9bfc1a68597
BLAKE2b-256 671875c3ba602bcdfd0394023e8ac5688d1c82115f69a24eebf8d7384371fed4

See more details on using hashes here.

File details

Details for the file msri-0.2.3-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: msri-0.2.3-py3-none-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 2.9 MB
  • Tags: Python 3, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for msri-0.2.3-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 fd7752df93865f4c21bd7e52f4e42b8e4139aed8bd81c76dae7e9f053397063b
MD5 4ffb7d8008f2a87ec66583f0944a0df1
BLAKE2b-256 006ea0819061e0a010b4384d80575ef91a9126d5d73fd302f8dacc04bc7566ba

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.3 This release

5 files

0.2.2

5 files

0.2.1

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page