2 stable releases

Uses new Rust 2024

new 2.0.0 Aug 8, 2026
1.0.0 Mar 25, 2026

#563 in Artificial intelligence

Apache-2.0 OR MIT

400KB
9K SLoC

bito

CI Crates.io docs.rs MSRV

bito = building in the open.

bito is part of the building-in-the-open approach to AI-assisted development — a set of practices, templates, and tools for teams that work with coding agents. It can be used entirely on its own; the broader framework just gives it more context to work with.

AI coding agents generate documentation as they work — ADRs, design docs, changelogs, handoff notes. The quality varies between sessions. Sometimes you get crisp, well-structured prose. Sometimes you get bloated walls of text that no one wants to review.

bito catches the problems before you commit. It runs 18 deterministic writing checks — readability scoring, token budgets, section completeness, grammar, dialect enforcement, and style analysis. No LLM, no API calls, no network. Same input, same result, every time.

The goal: agent-generated documents that are clean enough to ship.

$ bito analyze docs/architecture.md

docs/architecture.md

  Readability: Grade 12.4, 24 sentences, 390 words
  Grammar:     8 issues, 3 passive (12.5%)
  Sticky:      Glue index 21.5%, 2 sticky sentences
  Pacing:      Fast 62% / Medium 29% / Slow 8%
  Length:      Avg 15.8 words, variety 10.0/10
  Transitions: 0% of sentences, 0 unique
  Overused:    "template" (1.3%), "skill" (1.1%), "design" (1.1%)
  Diction:     2 vague words
  Style:       Score 92/100, 2 adverbs, 0 hidden verbs

What it checks

analyze runs 18 checks in one pass:

Category What it catches
Readability Flesch-Kincaid grade level — flag documents that demand too much of the reader
Grammar Passive voice, double negatives, subject-verb disagreement, missing punctuation
Sticky sentences High "glue word" density — sentences stuffed with is, the, of, in
Pacing Monotonous sentence rhythm — all short punches or all long slogs
Sentence variety Length distribution — a score of 1/10 means every sentence is the same length
Transitions Percentage of sentences using connective phrases — low means choppy reading
Overused words Repeated non-trivial words that make the text feel circular
Repeated phrases Bigrams and trigrams that recur too often
Echoes Same word appearing in adjacent sentences (unintentional repetition)
Complex paragraphs Paragraphs with too many ideas competing for attention
Conjunction starts Sentences opening with But, And, So — fine in moderation, a tic in excess
Cliches "At the end of the day," "move the needle," "low-hanging fruit"
Diction Vague words (things, stuff, very) that add length without meaning
Sensory language Percentage of concrete, sensory words — useful for judging descriptive writing
Consistency Mixed US/UK spelling (color and colour in the same document)
Dialect enforcement Flag spellings that violate your project's chosen dialect (en-us, en-gb, en-ca, en-au)
Acronyms Tracks acronym usage for consistency
Style score Combined metric: adverb density, hidden verbs (nominalizations), overall polish

Every check is deterministic. No API calls, no LLM, no network. The same input produces the same output every time.

Focused checks run individually when you need a specific gate:

# Does this handoff fit in 2,000 tokens?
$ bito tokens handoff.md --budget 2000
PASS: handoff.md is 546 tokens (budget: 2000)

# Is this user guide accessible to a general audience?
$ bito readability getting-started.md --max-grade 8
Error: getting-started.md scores 14.7 (max: 8). Simplify sentences or reduce jargon.

# Does this ADR have all the sections it needs?
$ bito completeness docs/decisions/0001-my-decision.md --template adr
PASS: docs/decisions/0001-my-decision.md (adr completeness check)

# How's the grammar?
$ bito grammar changelog.md
changelog.md: 16 sentences analyzed
  Passive voice: 2 instances (12.5%)
  Grammar issues: 3
    [MEDIUM] Sentence 3: Possible comma splice
    [LOW] Sentence 9: Multiple consecutive spaces found
    [MEDIUM] Sentence 16: Sentence missing terminal punctuation

Installation

Homebrew (macOS and Linux)

brew install claylo/tap/bito

From source

cargo install bito

Pre-built binaries

Download from the releases page. Binaries are available for macOS (Apple Silicon and Intel), Linux (x86_64 and ARM64), and Windows.

Usage

Config-driven linting

Define rules in your config file to map file paths to checks, then run them with one command:

bito lint docs/handoff.md
bito lint --json docs/handoff.md   # structured output for CI

If no rules match the file, it exits cleanly. See docs/README.md for rules configuration, accumulation, specificity, and inline suppressions.

Full analysis

bito analyze my-document.md

Add --dialect en-gb to enforce British spelling. Add --checks readability,consistency to run only specific checks. Add --exclude style,jargon to skip specific checks.

Output format

--format takes auto (the default), text, or json. auto means text on a terminal and JSON everywhere else, so redirecting or piping any command gives you a machine-readable document without a flag:

bito analyze doc.md                 # text, you are at a terminal
bito analyze doc.md > report.json   # JSON, stdout is a file
bito --format text analyze doc.md > report.txt   # force text

--json remains as an alias for --format json. If you are upgrading and a script parsed bito's text output from a pipe, see docs/UPGRADING.md.

Quality gates

Quality gates are pass/fail checks designed for CI, pre-commit hooks, and automation:

# Token counting with budget enforcement
bito tokens <file> --budget <max>

# Readability with grade ceiling
bito readability <file> --max-grade <max>

# Section completeness against a template
bito completeness <file> --template <name>

# Grammar and passive voice analysis
bito grammar <file>

Built-in completeness templates: adr, handoff, design-doc. Define your own in a bito config file.

Every command writes structured JSON when stdout is redirected, and works in pipes.

Exit codes

Code Meaning What to do
0 Every check passed Continue
1 A check ran and the input missed a threshold Read the output and fix the prose
2 bito could not run Fix the invocation; retrying unchanged will not help

Exit 2 covers a malformed config, unreadable or oversized input, an unknown check name, and command-line errors. Nothing was measured, so there is no result to act on. Findings print without an Error: prefix; failures keep it.

bito schema publishes this contract as machine-readable JSON.

Diagnostics

bito doctor            # config sources, environment, resolved directories
bito doctor --json     # same report, machine-readable
bito doctor --bundle   # redacted bito-debug-<ts>.tar.zst for bug reports
bito info              # version, features, config file paths

doctor reports the resolved log file alongside the config, cache, and data directories, so it answers "where are my logs?" directly. --bundle writes the report to a compressed archive with secrets redacted; the archive path appears in the JSON as bundle rather than on stdout, so the document stays parseable.

info and doctor are the only commands that reach the network, checking for a newer release with a 24-hour cache. Set BITO_NO_UPDATE_CHECK=1 to disable it. A failed check never fails the command.

Dialect enforcement

Set a project dialect and bito flags wrong-dialect spellings alongside mixed-spelling inconsistencies:

# Via flag
bito analyze README.md --dialect en-us

# Via environment variable
export BITO_DIALECT=en-gb

# Via config file (.bito.toml)
dialect = "en-ca"

Supported dialects: en-us, en-gb, en-ca (Canadian hybrid: US -ize/-ise, UK for the rest), en-au.

MCP server

bito includes a built-in MCP server, so AI coding assistants can call quality gates directly during writing sessions:

{
  "mcpServers": {
    "bito": {
      "command": "bito",
      "args": ["serve"]
    }
  }
}

This exposes eight tools: analyze_writing, count_tokens, check_readability, check_completeness, check_grammar, lint_file, get_info, and get_custom. The lint_file tool resolves path-based rules from your config, so the agent can check quality before writing. See docs/README.md for per-tool details.

Configuration

Drop a config file in your project and it takes effect automatically:

  1. .config/bito.toml (or .yaml, .json) in the current directory or any parent
  2. .bito.toml in the current directory or any parent
  3. bito.toml (without dot prefix) in the current directory or any parent
  4. ~/.config/bito/config.toml (user-wide defaults)

Closer files win. All formats (TOML, YAML, JSON) work interchangeably.

Environment variables override a discovered config file. A file named explicitly with -c/--config outranks them.

  • BITO_LOG_PATH — log file path
  • BITO_LOG_DIR — directory (file name defaults to bito.jsonl)
  • BITO_ENV — environment tag (default: dev)
  • BITO_NO_UPDATE_CHECK — set to 1 to disable release update checks
  • RUST_LOG — log filter, e.g. debug or bito=trace

The two log variables are the exception to the rule above: they decide where logs get written even when -c names a config file that sets log_dir. Where a process writes its logs is an operational question, so an operator can redirect them without editing anyone's config.

Every config field also has a BITO_-prefixed form: BITO_DIALECT, BITO_MAX_GRADE, BITO_TOKEN_BUDGET, and so on. See docs/README.md for the full list.

The live log keeps a stable name, so tail -f bito.jsonl follows it across days. On the first write of a new day the previous day's log is renamed to bito.YYYY-MM-DD.jsonl and compressed to .zst. Rotated logs are deleted after seven days; set log_retention_days to change that window, or to 0 to keep them forever.

# .bito.toml
dialect = "en-us"
token_budget = 2000
max_grade = 12.0
log_level = "warn"

Shell completions

Included in Homebrew installs and release archives. For manual setup:

# Bash
bito completions bash > ~/.local/share/bash-completion/completions/bito

# Zsh
bito completions zsh > ~/.zfunc/_bito

# Fish
bito completions fish > ~/.config/fish/completions/bito.fish

Development

crates/
├── bito/       # CLI binary
└── bito-core/  # Core library

Prerequisites

Quick Start

just check       # fmt + clippy + test
just test        # tests only (nextest)
just cov         # coverage report

Build Tasks

Command Description
just check Format, lint, deny, and test
just fmt Format code with rustfmt
just clippy Run clippy lints
just test Run tests with nextest
just doc-test Run documentation tests
just cov Generate coverage report

xtask Commands

The project includes an xtask crate for build automation:

# Generate man pages
cargo xtask man

# Generate shell completions
cargo xtask completions

# Generate for specific shell
cargo xtask completions --shell zsh

Architecture

Crate Organization

  • bito — The CLI binary. Handles argument parsing, command dispatch, MCP server, and user interaction.
  • bito-core — The core library. Configuration loading, writing analysis, lint engine, and all 18 deterministic checks.

Error Handling

  • Libraries use thiserror for structured error types
  • Binaries use anyhow for flexible error propagation
  • All errors include context for debugging

Configuration System

Configuration discovery is handled by config::load:

use camino::Utf8Path;
use bito_core::config;

let cwd = Utf8Path::new(".");
let (cfg, sources) = config::load(cwd, None)?;

Pass an explicit path as the second argument to override discovery:

let (cfg, sources) = config::load(cwd, Some(Utf8Path::new("my-config.yaml")))?;

Features:

  • Walks up directory tree looking for config files
  • Stops at repository boundaries (.git by default)
  • Merges multiple config sources with clear precedence
  • Supports explicit file paths for testing

CI/CD

This project uses GitHub Actions for continuous integration:

  • Build & Test — Runs on every push and PR
  • MSRV Check — Verifies minimum supported Rust version
  • Clippy — Enforces lint rules
  • Coverage — Tracks test coverage

Dependabot

This project uses Dependabot for security monitoring, but not for automatic pull requests. Instead:

  1. Dependabot scans for vulnerabilities in dependencies
  2. A weekly GitHub Actions workflow converts alerts into issues
  3. Maintainers review and address updates manually

This approach provides:

  • Full control over when and how dependencies are updated
  • Opportunity to batch related updates together
  • Time to test updates before merging
  • Cleaner git history without automated PR noise

Security alerts appear as issues labeled dependabot-alert.

Contributing

Contributions welcome. See Development above for the build and test loop, and docs/README.md for the full command and configuration reference.

Commit Messages

This project uses Conventional Commits:

  • feat: — New features
  • fix: — Bug fixes
  • docs: — Documentation changes
  • perf: — Performance improvements
  • chore: — Maintenance tasks

Code Style

  • Rust 2024 edition
  • #![deny(unsafe_code)] — Safe Rust only
  • Follow rustfmt defaults
  • Keep clippy clean

License

MIT (LICENSE-MIT)

Dependencies

~25–34MB
~548K SLoC