# Configuration Commands Source: https://docs.taho.is/cli-reference/configuration-commands View and validate TAHO configuration ## Viewing Configuration * `taho config` - Display current configuration (TOML format) * `taho config --format json` - Display as JSON * `taho config --format toml` - Display as TOML (default) Configuration commands show active configuration from all sources including overrides, with validation and diagnostics. # Content Commands Source: https://docs.taho.is/cli-reference/content-commands Publish and retrieve content in TAHO ## Publishing Content * `taho publish ` - Publish file to content exchange Publishing returns a content ID for retrieval, uses streaming I/O for large files, and generates content IDs using BLAKE3 hashing. # Daemon Management Source: https://docs.taho.is/cli-reference/daemon-management Start and manage the TAHO host runtime ## Starting the Host * `taho --daemon` - Start in foreground daemon mode (recommended for systemd) * `taho start` - Start host runtime as subprocess * `taho start --verbose` - Enable verbose logging * `taho start --logo-off` - Disable logo display ## Host Management * `taho host reload` - Reload all components without restarting # Getting Started with the CLI Source: https://docs.taho.is/cli-reference/getting-started Learn the TAHO command-line interface basics ## CLI Overview The unified `taho` binary provides both CLI mode and daemon mode (using the `--daemon` flag), with consistent command structure and built-in help via `--help`. ## Configuration Configuration uses `config.toml` with environment variable overrides using the `TAHO__` prefix, following a clear configuration hierarchy and precedence. # Service Commands Source: https://docs.taho.is/cli-reference/service-commands Invoke TAHO services from the command line ## Invoking Services * `taho services invoke ` - Invoke service method from stdin * `taho services invoke --data ''` - Invoke with JSON data Service invocation follows defined method signatures with structured response handling. # AI/ML Inference Source: https://docs.taho.is/core-concepts/ai-ml-inference LLM, ONNX, and Stable Diffusion inference capabilities ## Inference Capabilities TAHO supports Large Language Models (LLMs), ONNX Runtime integration, Stable Diffusion for image generation, and custom model support. ## Model Management Models can be loaded from content exchange with caching and optimization, resource allocation for inference, and multi-model orchestration. ## Inference Workflows TAHO supports single-node inference, distributed inference across The Mesh, and batching and optimization strategies. # Content Exchange Source: https://docs.taho.is/core-concepts/content-exchange Content-addressed storage with automatic peer discovery ## What is the Content Exchange? The Content Exchange is TAHO's content-addressed storage system that identifies content by cryptographic hash rather than by location or filename. When you publish a file, TAHO generates a unique content ID that represents the exact bytes of that file. The same content always produces the same ID, regardless of filename or metadata. This approach provides: * **Integrity verification** - Content ID proves content hasn't been corrupted * **Location independence** - Content can be retrieved from any node holding it * **Efficient caching** - Content can be safely cached and shared across nodes ## Content IDs Content IDs are cryptographic hashes that uniquely identify content. TAHO content IDs are **self-describing identifiers** with size and validation data woven into the hash. Nodes can inspect content properties, preallocate memory, and filter requests - all before a single byte is transferred. Once content is published and a content ID is generated, the content is immutable. The same bytes will always produce the same content ID, and any modification creates a new content ID. This guarantees that when you fetch content by ID, you receive exactly what was published. ## Publishing Content Publish content to the exchange and receive a content ID: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Publish a file taho publish ./model.onnx # Output: 000006VX0Q0HARDX7YPGSCFMY9J7NP1Z6AFNNFDAGKJD1X3A6H6S9E0240 # Publish any file type taho publish ./dataset.tar.gz taho publish ./document.pdf taho publish ./image.png ``` ### What Happens When You Publish 1. **Hash calculation** - TAHO streams the file and calculates its hash 2. **Content ID generation** - The hash becomes the content ID 3. **Local storage** - Content is stored locally in the content exchange 4. **Network announcement** - Your node announces content availability to The Mesh via gossip protocol 5. **ID output** - The content ID is printed for later retrieval Publishing uses streaming I/O, so large files (even multi-gigabyte models) are handled efficiently without loading everything into memory. ### Content Storage Locations TAHO stores published content locally using a multi-tier storage system: * **Memory cache** - Frequently accessed content kept in memory (100MB default limit) * **File storage** - Content persisted to disk in node-specific directories * **Hot promotion** - Frequently accessed content automatically promoted to memory cache Content files are stored by content ID in TAHO's data directory, typically `~/.taho/data/content//`. ## Retrieving Content When you need content, the Content Exchange retrieves it from local storage or automatically fetches it from remote peers. ### Local Retrieval If content exists in local storage, it's returned immediately: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Content available locally - instant retrieval client.get(&content_id).await? // Returns immediately ``` ### Remote Retrieval If content is not available locally, TAHO automatically discovers and fetches it from The Mesh: 1. **Discovery request** - Your node broadcasts a content discovery request via gossip protocol 2. **Holder announcements** - Nodes holding the content respond with announcements 3. **Peer selection** - TAHO selects an optimal peer based on availability 4. **Content fetch** - Content is fetched directly from the holder via request-response protocol 5. **Verification** - Downloaded content is verified against the content ID hash 6. **Local caching** - Content is stored locally for future requests ## Content Discovery The Content Exchange uses The Mesh's gossip protocol for content discovery. ### Content Announcements When a node publishes content or comes online with existing content, it announces availability to The Mesh. These announcements are gossiped across the network, so all nodes maintain an index of content locations. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Node A publishes content taho publish ./model.onnx # Output: 000006VX0Q0HARDX7YPGSCFMY9J7NP1Z6AFNNFDAGKJD1X3A6H6S9E0240 # Announcement gossiped: "Node A has 000006VX0Q0HARDX7YPGSCFMY9J7NP1Z6AFNNFDAGKJD1X3A6H6S9E0240" # Node B receives the gossip # Node B now knows Node A holds this content ``` ### Discovery Process When a node needs content, it broadcasts a discovery request. Holders respond with announcements containing their peer information. The requesting node then initiates a direct fetch from a selected holder. ```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}} flowchart TB NodeA[Node A
needs content] -->|Discovery Request| Mesh[The Mesh
gossip] Mesh -->|Propagate| NodeB[Node B
holder] Mesh -->|Propagate| NodeC[Node C
holder] NodeB -->|Announcement| NodeA NodeC -->|Announcement| NodeA NodeA -->|Fetch| NodeB NodeB -->|Data| NodeA ``` ### Gossip Protocol Integration The Content Exchange leverages The Mesh's gossipsub protocol for efficient content discovery: * **Topic subscription** - Nodes subscribe to the "content-exchange" gossip topic * **Event broadcasting** - Content events are serialized and published to the topic * **Network-wide propagation** - Events spread across The Mesh, reaching all nodes * **Holder index maintenance** - Each node maintains a local index of content holders ## Use Cases ### Large File Distribution Distribute large ML models, datasets, or media files without centralized storage: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Publisher shares a 3.4GB model taho publish ./stable-diffusion-unet.onnx # Output: 000006VX0Q0HARDX7YPGSCFMY9J7NP1Z6AFNNFDAGKJD1X3A6H6S9E0240 # Consumers automatically fetch from any holder # Multiple consumers can fetch from different peers simultaneously ``` ### Distributed AI/ML Models TAHO's inference system uses the Content Exchange for storing and distributing ML models: * **Model partitioning** - Large models (>2GB) are partitioned into smaller subgraphs * **Content-addressed partitions** - Each partition gets its own content ID * **Automatic deduplication** - Common subgraphs across models are stored once * **Distributed loading** - Nodes fetch model partitions from The Mesh as needed See [AI/ML Inference](/core-concepts/ai-ml-inference) for more details. ### Development Asset Sharing Share development assets across team members or build machines: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Share compiled artifacts taho publish ./target/release/binary # Share test fixtures taho publish ./fixtures/test-data.json # Share configuration snapshots taho publish ./config/production.toml ``` ## Storage Backends The Content Exchange supports multiple storage backends that can be composed: ### Memory Store In-memory cache with LRU eviction: * Fast access for hot content * Configurable size limit (100MB default) * No persistence - cleared on restart ### File Store Persistent file-based storage: * Content stored as individual files named by content ID * Per-node isolation via subdirectories * No automatic eviction ### Composite Store Combines memory and file storage with hot content promotion: * Frequently accessed content promoted to memory cache * Memory evictions remain in file storage * Provides both speed and persistence The default configuration uses the composite store for optimal performance and persistence. ## Programmatic Access The Content Exchange can be accessed programmatically in Rust applications: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} use taho_common::{NodeContext, content::Content}; use taho_content_exchange::ContentSystemService; // Get client for the current node let context = NodeContext::default(); let client = ContentSystemService::client(context.clone()); // Store content let content = Content::from_slice(b"data"); let content_id = content.content_id(); client.put(content).await?; // Retrieve content (local or remote) let result = client.get(&content_id).await?; // Check for local presence let has_it = client.has(&content_id).await?; ``` ## Security and Verification ### Content Integrity Content IDs provide cryptographic verification: 1. **Hash verification** - After fetching content, TAHO recalculates the hash 2. **Comparison** - The calculated hash must match the content ID 3. **Rejection** - Mismatched content is rejected and not stored This ensures you always receive authentic, unmodified content. ### Immutability Guarantees Content is immutable once published. Any attempt to modify content results in a new content ID. This provides: * **Tamper evidence** - Modified content has a different ID * **Version clarity** - Each version has a unique, permanent identifier * **Reproducibility** - Same content ID always means same content ## Next Steps * **[The Mesh](/core-concepts/the-mesh)** - Learn about TAHO's P2P network that powers content discovery * **[Content Commands](/cli-reference/content-commands)** - Detailed CLI reference for content operations * **[AI/ML Inference](/core-concepts/ai-ml-inference)** - How inference leverages the Content Exchange # The Mesh Source: https://docs.taho.is/core-concepts/the-mesh Self-forming P2P network for distributed computing ## What is The Mesh? The Mesh is TAHO's self-forming peer-to-peer network that connects nodes automatically for distributed computing. When you start TAHO, your node joins The Mesh and can immediately discover and communicate with other nodes—no configuration required. The Mesh handles: * **Automatic peer discovery** - Find nodes on your local network and across the internet * **Resilient connections** - Maintain connectivity as nodes join and leave * **Content routing** - Efficiently locate and transfer content across the network * **Component coordination** - Enable distributed AI/ML workloads and service invocations ## Peer Discovery The Mesh uses multiple discovery mechanisms to find peers: ### Local Network Discovery Nodes on the same local network (subnet) automatically discover each other through multicast announcements. This enables zero-configuration networking for development and edge deployments. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Start TAHO - automatically discovers local peers taho --daemon ``` ### Remote Peer Discovery For nodes across the internet, The Mesh uses rendezvous points—well-known bootstrap nodes that help peers find each other. You can configure bootstrap peers by setting environment variables or editing your configuration file: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Configure bootstrap peers via environment variable export TAHO__FABRIC__BOOTSTRAP="/ip4/203.0.113.1/tcp/4001/p2p/12D3KooW..." # Or edit your config file (see location with: taho config) # Add bootstrap peers to the [mesh] section ``` ## Network Transports The Mesh supports multiple transport protocols for flexibility across different environments: ### Native Nodes Native TAHO nodes (Linux, macOS) use: * **QUIC** - High-performance UDP-based transport optimized for modern networks * **WebSocket** - TCP-based transport for compatibility with browser nodes and restrictive firewalls Both transports run simultaneously, allowing native nodes to connect to any peer type. ### Browser Nodes Browser-based nodes run entirely in your web browser using WebAssembly. They connect via WebSocket transport, enabling distributed computing without installing software. Browser nodes are perfect for lightweight participation in The Mesh—contribute compute resources or access distributed services directly from your browser. ## Content Distribution The Mesh integrates tightly with TAHO's [Content Exchange](/core-concepts/content-exchange) system for efficient content distribution: ### Content Announcements When you publish content, your node announces its availability to The Mesh via a gossip protocol. Other nodes subscribe to these announcements and maintain an index of content holders. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Publish content - automatically announced to The Mesh taho publish ./model.onnx # Output: abc123def456... # Content availability is gossiped across the network # Other nodes now know you have this content ``` ### Content Fetching When a node needs content, The Mesh automatically locates holders and fetches it: 1. **Discovery** - Query The Mesh for nodes holding the content 2. **Selection** - Choose optimal peer based on latency and availability 3. **Transfer** - Fetch content directly from the holder 4. **Verification** - Validate content integrity via content ID hash This process happens automatically when your application requests content by content ID through the Content Exchange API. ## Distributed Services The Mesh enables nodes to invoke services and components on remote nodes, creating a distributed compute network. ### Port Invocations Components expose service functions that can be invoked remotely. The Mesh routes these invocations to the appropriate nodes and returns results. ### Event Publishing Nodes can publish events to topics, with The Mesh delivering them to all subscribers. This enables reactive distributed systems where components respond to events across the network. ### Component Deployment The Mesh can coordinate component deployment—streaming WebAssembly components from repositories and deploying them across multiple nodes simultaneously. ## Network Resilience The Mesh is designed for reliability in dynamic network environments: ### Fault Tolerance * **Redundant connections** - Maintains multiple peer connections for reliability * **Automatic reconnection** - Re-establishes dropped connections without manual intervention * **Content redundancy** - Content remains available as long as any holder is online ### Mesh Topology The Mesh forms a mesh network where nodes connect to multiple peers. This provides multiple paths for content and messages, ensuring availability even if individual nodes fail. ### Graceful Degradation When network conditions deteriorate: * Adjusts heartbeat intervals to maintain connectivity * Falls back to alternative transports if needed * Continues operating with reduced peer sets ## Mesh Use Cases ### Distributed AI/ML Inference Run large models by distributing inference workload across multiple nodes: ### Content Distribution Networks Create peer-to-peer content distribution for large files like ML models or datasets: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Publisher node taho publish ./dataset.tar.gz # Content ID: ca_blake3_xyz789... # Consumer nodes automatically fetch when they request the content # through the Content Exchange API - no manual fetch command needed ``` ## Next Steps * **[Content Exchange](/core-concepts/content-exchange)** - Learn about content-addressed storage * **[AI/ML Inference](/core-concepts/ai-ml-inference)** - Understand distributed inference capabilities # Installation Source: https://docs.taho.is/getting-started/installation Install TAHO on Linux and macOS platforms ## System Requirements TAHO supports Linux and macOS platforms. ## Installation Methods ### Binary Releases Download pre-built binaries from GitHub releases. ## Quick Start Start the TAHO daemon and verify your installation is working correctly with `taho start` in your terminal. # Quickstart Tutorial Source: https://docs.taho.is/getting-started/quickstart Get started with TAHO and run your first distributed workflow ## Hello, TAHO Get started with TAHO by starting the daemon, publishing your first content, and running an inference model. ## Your First Distributed Workflow Learn the basics of publishing content to The Mesh, discovering peers, and fetching content from remote nodes. # Introduction Source: https://docs.taho.is/index Learn about TAHO, the distributed compute runtime for AI/ML workloads Start the daemon and run your first distributed workflow Learn about the self-forming P2P network architecture Understand content-addressed storage and distribution Complete command-line interface documentation ## What is TAHO? TAHO is a distributed compute runtime that streams, compiles, and runs AI/ML workloads and WebAssembly components from remote repositories. It provides a peer-to-peer network called "The Mesh" for component orchestration and deployment automation. ## Why TAHO? TAHO enables self-adaptive systems for AI/ML workloads with content-addressed storage and automatic peer discovery. The Mesh self-forms across nodes, allowing distributed AI inference, content sharing, and collaborative computing without centralized coordination. ## Key Features * **The Mesh**: Self-forming P2P network for distributed computing with automatic peer discovery and connection * **Content Exchange**: Content-addressed storage with BLAKE3 hashing for deduplication and integrity * **AI/ML Inference**: Native support for LLMs, ONNX models, and Stable Diffusion * **CLI-First Design**: Complete control via command-line interface with daemon mode for services # Introduction to TAHO Lift Source: https://docs.taho.is/lift/index Deployment software from TAHO that keeps your TAHO deployment commits and documentation in sync as you configure, extend, and maintain your infrastructure. Prerequisites and setup How the pipeline works Complete flag reference Deploying TAHO involves real engineering work: configuring the Magnetic PeerMesh, tuning the Piranha Algorithm, writing integration logic, and evolving your setup over time. That work requires a clear record. Commit messages get written in a rush. Deployment documentation falls behind. Over time, pull requests get harder to review, new teammates take longer to get up to speed, and nobody can remember why a configuration changed three months ago. For teams running TAHO in production, that institutional knowledge isn't just convenient, it's critical to administering the platform as it grows and evolves. We ran into this on our own team. What started as a few scripts to clean up commits before review grew into a tool that every TAHO engineer runs on every commit. TAHO Lift is that tool, and it ships with TAHO because it solves a real problem in deployment workflows. Once you commit your deployment code, TAHO Lift reads your diff, writes a thorough commit message, and updates your repo's documentation to match. All of that gets folded back into your original commit. No extra commits, no clutter. A single command kicks off the whole pipeline: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} lift ``` Two tools run in sequence on your latest commit: 1. **Inky** generates an improved commit message from your diff 2. **Doc** updates documentation to reflect your code changes ## Better commits shape better teams We noticed something on our own team: when commits explain themselves clearly, everything else gets easier. Pull request descriptions get better because they're built on commit messages that actually describe the work. When someone runs `git log` six months later to figure out why a decision was made, the answer is right there instead of buried in a Slack thread. New teammates get up to speed faster because the docs match the code as it exists today. We don't think of Lift as a linter or a style enforcer. It just raises the bar on what a "normal" commit looks like. That's been our experience building TAHO, and we wanted to share it. ## Our philosophy **Passive by default.** We built Lift to stay out of your way. It tracks which commits it has already processed. Run it as many times as you want. It skips commits that are already done. Use `-f` to force re-processing or `-p` to get prompted first. **Idempotent.** Running Lift twice on the same commit gives you the same result. The tracking system in `~/.taho/lift/` records each tool's work per commit hash, so there's no risk of doing the same work twice. **Graceful degradation.** If one tool fails, the pipeline keeps going with the rest and tells you what happened at the end. A doc failure won't stop your commit message from being improved. ## Why we share it Lift started as an internal tool. Every commit to TAHO goes through the same pipeline you're reading about here: better messages, up-to-date docs, a commit history that tells the story of how the project grew. We built it because we needed it, and we share it because we think every team deserves the same thing. ## What Lift is not Lift is not a CI gate or a pre-commit hook. It runs *after* you commit, improving what's already there. It won't block your workflow or reject your commits. Think of it as the last part of the climb. You did the hard work, and Lift carries it to the top of the mountain. # Installation & Setup Source: https://docs.taho.is/lift/installation Prerequisites, installation methods, and initial configuration for TAHO Lift. ## Prerequisites Before installing TAHO Lift, ensure the following tools are available on your system: * **[GitHub CLI](https://cli.github.com/)** — Required for VCS integration, pull request workflows, and repository operations. Must be authenticated via `gh auth login`. * **[Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)** — Powers Lift's AI-driven tools. Must be authenticated via `claude auth login`. ## Cloud Marketplace TAHO Lift is available through the following cloud marketplaces: * [AWS Marketplace](https://aws.amazon.com/marketplace) * [Azure Marketplace](https://azuremarketplace.microsoft.com) * [Google Cloud Marketplace](https://cloud.google.com/marketplace) Installation requires **administrator permissions** on your cloud account. Contact your organization's cloud administrator to provision TAHO Lift through your preferred marketplace. Don't have access? Reach out to your cloud administrator or contact [sales@taho.is](mailto:sales@taho.is) to discuss deployment options. # CLI Flag Reference Source: https://docs.taho.is/lift/reference/cli-flags Complete reference for all TAHO Lift command-line flags and options. Every flag you can pass to `lift`. When no flags are given, Lift runs the pipeline tools specified in your config file (or all tools by default) in passive mode on the latest commit. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} lift [flags] ``` ## Processing modes These flags control *whether* Lift processes a commit, not *which tools* run. | Flag | Long | Description | | ---- | ---------- | ------------------------------------------------------------------------------- | | | *(none)* | **Passive mode** (default). Exits silently if the commit was already processed. | | `-f` | `--force` | Force re-processing even if the commit was already processed. No prompt. | | `-p` | `--prompt` | Prompt before re-processing an already-processed commit. | Passive mode is the default so you can run `lift` as often as you like — in a hook, an alias, or muscle memory — without duplicating work. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Re-process a commit that Lift already handled lift -f # Ask first, then re-process if you confirm lift -p ``` ## Tool selection When no tool flag is given, Lift runs the tools from the `pipeline` config setting (default: all four tools). When you pass one or more tool flags, *only* those tools run, overriding the config. | Flag | Long | Description | | ---- | ----------- | ------------------------------------- | | `-m` | `--message` | Run Inky (commit message improvement) | | `-d` | `--doc` | Run Doc (documentation updates) | Tool flags combine freely: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Run only Inky lift -m # Run Inky and Doc lift -m -d ``` ## Task number | Flag | Long | Description | | ---- | ------------ | ---------------------------------------------------------------------- | | `-t` | `--task NUM` | Prepend a task number prefix to the commit message (e.g., `TAHO-123:`) | The prefix defaults to `TAHO` and can be overridden via the `inky.task_prefix` config setting. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Prepend TAHO-123: to the commit message lift -t 123 ``` ## Pull request | Flag | Long | Description | | ---- | ------ | ---------------------------------------------------------------------- | | | `--pr` | Prompt to create or update a pull request after the pipeline completes | After all tools finish, Lift asks whether you'd like to open or update a PR. Stack mode enables this automatically. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Run the pipeline, then prompt for a PR lift --pr ``` ## Cleanup mode | Flag | Long | Description | | ---- | ----------- | --------------------------------------------------------------------------- | | `-c` | `--cleanup` | Revert `.md` file changes and replace the commit message with a placeholder | Cleanup mode is destructive. It reverts all Markdown file changes from the current commit and replaces the commit message with a placeholder. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Undo Lift's changes on this commit lift -c ``` ## Output control | Flag | Long | Description | | ---- | --------- | ------------------------------------------------ | | `-q` | `--quiet` | Suppress progress indicators and minimize output | Useful for scripting or CI environments where animated spinners aren't wanted. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Run silently lift -q ``` ## Common combinations | Command | What it does | | ------------ | ---------------------------------------- | | `lift` | Full pipeline, passive mode | | `lift -f` | Full pipeline, force re-processing | | `lift -m` | Inky only | | `lift -d -f` | Force re-run Doc only | | `lift -s` | Stack mode (all commits, then PR prompt) | | `lift -c` | Cleanup (revert docs and commit message) | ## Configuration | Flag | Long | Description | | ---- | -------------------- | ---------------------------------------------------------------- | | | `--config` | Display the resolved configuration reference and exit | | | `--script-dir DIR` | Override the script directory (overrides config) | | | `--external-scripts` | Use legacy bash scripts instead of internal Rust implementations | Run `lift --config` to see all available configuration options and the resolved merge result. ## Preconditions Lift validates two things before it runs: 1. **Clean working directory** — uncommitted changes cause Lift to exit with an error. Commit or stash your work first. 2. **Not on the main branch** — Lift refuses to run on the configured main branch (default: `main`). Switch to a feature branch first. # Configuration Source: https://docs.taho.is/lift/reference/configuration Layered TOML configuration system for customizing Lift's pipeline, tools, and behavior. Lift uses a layered TOML configuration system. Each layer overrides the previous: 1. **Built-in defaults** — embedded in the binary from `lift.default.toml` 2. **User config** — `~/.taho/lift/lift.toml` 3. **System config** — `/etc/taho/lift/lift.toml` 4. **CLI flags** — highest priority Run `lift --config` to see the resolved configuration with file status. ## Configuration files Create `~/.taho/lift/lift.toml` to customize Lift behavior. All fields are optional — only specify what you want to override. ## Available settings | Key | Type | Default | Description | | ---------------------- | ------------ | ---------------------------------- | ------------------------------------------------- | | `pipeline` | string array | `["inky", "doc", "lint", "vibes"]` | Tools to run in the default pipeline | | `quiet` | bool | `false` | Suppress progress indicators | | `script_dir` | string | `"scripts/mastodon"` | Path to scripts directory | | `use_external_scripts` | bool | `false` | Use legacy bash scripts instead of internal tools | | `main_branch` | string | `"main"` | Main branch name for VCS operations | ### Tool-specific settings | Key | Type | Default | Description | | ---------------------- | ------------ | --------------------------------------------------------- | ------------------------------------------ | | `inky.task_prefix` | string | `"TAHO"` | Prefix for task numbers in commit messages | | `lint.command` | string | `"cargo clippy --fix --allow-no-vcs"` | Lint command to execute | | `lint.file_extensions` | string array | `[".rs", ".toml", ".lock"]` | File extensions that trigger linting | | `doc.paths` | string array | `["README.md", "CLAUDE.md", ".mdx", ".feature", "docs/"]` | Documentation file paths to consider | | `pr.draft` | bool | `true` | Whether to create PRs as drafts | ## Examples Custom pipeline (run only lint and vibes by default): ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} pipeline = ["lint", "vibes"] ``` Python project: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [inky] task_prefix = "PROJ" [lint] command = "ruff check --fix" file_extensions = [".py", ".pyi"] [doc] paths = ["README.md", "docs/"] ``` Go project: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} main_branch = "develop" [lint] command = "go fmt ./..." file_extensions = [".go"] ``` CLI flags always override file config. For example, `lift -m` overrides the `pipeline` setting to run only Inky for that invocation. ## Commit tracking Lift tracks which commits each tool has processed in `~/.taho/lift/`: ``` ~/.taho/lift/ink # Commits processed by Inky ~/.taho/lift/doc # Commits processed by Doc ~/.taho/lift/lint # Commits processed by Lint ~/.taho/lift/vibes # Commits processed by Vibes ``` Tracking is VCS-agnostic and stores commit hashes regardless of backend. # VCS Support Source: https://docs.taho.is/lift/reference/vcs-support TAHO Lift supports both **Git** and **Sapling** through a unified abstraction layer. VCS detection is automatic. ## Detection On startup, Lift walks up the directory tree from the working directory looking for VCS markers in priority order: 1. `.sl` — Sapling 2. `.git` — Git 3. `.hg` — legacy Sapling (Mercurial heritage) If both `.sl` and `.git` exist in the same ancestry, Sapling takes precedence. Detection runs once per invocation and is cached for the lifetime of the process. ## Supported operations Every tool in the pipeline uses the same VCS abstraction. The underlying commands differ per backend, but the behavior is identical. | Operation | Git | Sapling | | ------------------------ | ------------------------------- | ------------------------------ | | Current commit hash | `git rev-parse HEAD` | `sl log -r . -T {node}` | | Main branch hash | `git rev-parse ` | `sl log -r -T {node}` | | Working directory status | `git status --porcelain` | `sl status` | | Commit message | `git log -1 --format=%B` | `sl log -r . -T {desc}` | | Commit diff | `git show HEAD` | `sl show` | | Amend commit | `git commit --amend` | `sl amend` | | Submit PR | `gh pr create [--draft] --fill` | `sl pr submit [--draft]` | The main branch name defaults to `main` and can be overridden via the `main_branch` config setting. PR draft mode is controlled by the `pr.draft` config setting. ## Pull request workflow The `--pr` flag triggers PR creation or update after the pipeline finishes. The workflow differs by backend. ### Sapling Sapling has native PR support. Lift calls `sl pr submit --draft` directly. ### Git Git PR submission requires the [GitHub CLI](https://cli.github.com/) (`gh`). When you submit a PR through Lift: 1. Pushes the current branch with `git push --force-with-lease -u origin HEAD` 2. Checks whether a PR already exists for the branch 3. Creates a new draft PR, or updates the existing one If `gh` is not installed, Lift prints the manual command and continues without creating the PR. ## Dependency validation Lift checks for required dependencies on startup: | Dependency | Required | Purpose | | ---------- | ------------------------ | -------------------------------------------- | | `sl` | When Sapling is detected | All VCS operations | | `git` | When Git is detected | All VCS operations | | `gh` | Optional (Git only) | PR creation and updates | | `claude` | Always | AI-powered commit messages and documentation | Missing required dependencies cause Lift to exit with installation instructions. Missing optional dependencies produce a warning. ## Commit tracking Lift tracks which commits each tool has processed in `~/.taho/lift/`: ``` ~/.taho/lift/ink # Commits processed by Inky ~/.taho/lift/doc # Commits processed by Doc ``` Tracking is VCS-agnostic — it stores commit hashes regardless of backend. This means switching between Git and Sapling on the same repository preserves processing history as long as commit hashes remain stable. ## Preconditions Before running the pipeline, Lift verifies: 1. **Clean working directory** — uncommitted changes cause an error 2. **Not on main** — Lift refuses to amend commits on the main branch 3. **Non-empty diff** — tools skip commits with no changes # Doc 📝 Source: https://docs.taho.is/lift/tools/doc Automatic documentation updates generated via Claude CLI, keeping your docs in sync with every commit. ## How it works Doc is the second step in the Lift pipeline, running after [Inky](/lift/tools/inky) rewrites your commit message. 1. Your latest commit diff is retrieved 2. The diff is sent to Claude CLI for analysis 3. Claude determines which documentation files (if any) need updates 4. If updates are needed, the relevant files are edited directly 5. The changes are left in your working directory for you to review Doc tags your commit with `#doc` so the pipeline knows this tool has run. If the commit has already been processed, Doc skips it in passive mode. ## What Doc considers Doc looks at documentation files that already exist in your repository. The default paths are: * **README.md** — project overview and setup instructions * **CLAUDE.md** — AI context files in the root or subdirectories * **.mdx files** — documentation pages * **.feature files** — BDD/Gherkin specifications These paths are configurable via the `doc.paths` setting in your [lift config](/lift/reference/configuration). Doc only edits existing files. It never creates new documentation files. If your project needs a new doc, you write it — Doc keeps it current after that. ## When Doc makes changes Doc only updates documentation when code changes affect: * User-facing behavior * APIs or endpoints * Configuration options * Workflows or setup instructions Internal refactors, test changes, and code reorganization that don't change how someone uses the project are left alone. Doc matches the existing style and tone of each file it edits, so the updates read like the rest of your docs. ## Running Doc by itself To run only Doc without the rest of the pipeline: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} $ lift -d ``` This is useful when you want to update documentation for a commit without rewriting the commit message. You can combine it with other flags: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Force re-processing even if already processed $ lift -d -f ``` ## Reviewing changes After Doc runs, any modified files appear in your working directory as uncommitted changes. You'll see output like: ```shellsession wrap theme={"theme":{"light":"github-light","dark":"github-dark"}} Temporal modifications detected in the following files: M README.md M taho-swarm/CLAUDE.md Now, carefully inspect the alterations and commit them to the timeline. ``` Review the changes before committing. Doc is good at identifying what needs updating, but you should always verify the edits make sense in context. ## Cleanup mode If Doc made changes you don't want, cleanup mode reverts all `.md` file modifications from the current commit: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} $ lift -c ``` This reverts every `.md` file to its state before the pipeline ran and amends the commit to remove those changes. ## When Doc does nothing If the diff doesn't affect anything user-facing, Doc reports that no updates are needed and exits cleanly: ```shellsession theme={"theme":{"light":"github-light","dark":"github-dark"}} No documentation updates needed. ``` This is the most common outcome for internal changes. No files are modified, no commit amendments happen. # Inky 🐙 Source: https://docs.taho.is/lift/tools/inky Generate improved commit messages from your diffs using Claude CLI. ## How It Works Inky analyzes your commit diffs and generates improved commit messages using Claude CLI. It rewrites your message to follow conventional commit format, adds structured `Summary:` and `Test Plan:` sections, and amends the commit automatically. When you run Inky, it: 1. Validates the working directory is clean and you're not on the main branch 2. Reads the current commit message and diff 3. Checks that the diff is non-empty — Inky won't process empty commits 4. Sends both to Claude CLI with instructions for generating a better message 5. Amends the commit with the improved message 6. Tags the commit with `#inky` for tracking Inky uses the diff to understand *what* changed, then writes a message explaining *what* and *why* rather than restating the code. ## Usage Run Inky through the Lift CLI, either isolated or as part of the full pipeline: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Run only Inky lift -m # Run the full pipeline (Inky runs first, then Doc) lift ``` ### Cleanup Mode Cleanup mode replaces the commit message with a placeholder instead of generating a new one. This is useful when you want to reset a commit message before re-running the pipeline: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} lift -m -c ``` The placeholder message is set to `"please wait: finding something to put here..."` and the commit is still tagged with `#inky`. ## Generated Message Format Inky generates messages that follow these conventions: * **Summary line** under 72 characters * **Conventional commit prefix** when appropriate (`feat:`, `fix:`, `refactor:`, etc.) * **Present tense** ("Add feature" not "Added feature") * **Summary and Test Plan sections** included in the body * **Existing hashtags preserved** (like `#inky`, `#doc`) If Inky determines your existing message is already good, it may keep it mostly as-is rather than rewriting it. ## Flags These flags are passed to Lift and apply when Inky runs: | Flag | Description | | -------- | --------------------------------------------------------------- | | `-m` | Run only Inky (skip other tools) | | `-t NUM` | Prepend a task number to the commit message (e.g., `TAHO-123:`) | | `-c` | Cleanup mode — set a placeholder message instead of generating | | `-q` | Quiet mode — suppress progress indicators | The task prefix defaults to `TAHO` and can be overridden via the `inky.task_prefix` [config setting](/lift/reference/configuration). ## VCS Support Inky works with both Git and Sapling, detected automatically. See [VCS Support](/lift/reference/vcs-support) for details. # Pipeline Overview Source: https://docs.taho.is/lift/tools/overview How TAHO Lift's tools work together in sequence to improve your commits. When you run `lift`, two tools execute in order on your latest commit: 1. **[Inky](/lift/tools/inky)** — rewrites your commit message 2. **[Doc](/lift/tools/doc)** — updates documentation to match the code Each tool tags the commit when it finishes (`#inky`, `#doc`). On subsequent runs, Lift skips tools that have already processed the commit unless you pass `-f` to force re-processing. ## Running individual tools You can run any tool in isolation or combine them: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} lift -m # Inky only lift -d # Doc only lift -m -d # Inky + Doc (same as the full pipeline) ``` Global flags like `-f` (force) and `-p` (prompt) apply to whichever tools are selected. ## When something fails If a tool fails, the pipeline continues with the remaining tools. The summary at the end reports which tools succeeded and which had issues. # Configuration Source: https://docs.taho.is/tui-pantry/configuration Reference for pantry.toml. Theme, colors, typography, and ingredient registration. The Pantry is configured through a single `pantry.toml` file at your widget crate root. ## Full example ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [config] theme = "light" style_source = "my_crate::styles" [colors.brand] deep_purple = "#2E1574" white = "#FFFFFF" [colors.green] 100 = "#DCFCE7" 500 = "#22C55E" 900 = "#14532D" [typography] text = { color = "#FFFFFF", description = "Primary content" } text_dim = { color = "DarkGray", description = "Secondary labels" } [ingredients] source = "my_crate" modules = ["widgets::gauge", "widgets::table"] ``` ## `[config]` | Key | Default | Description | | -------------- | -------- | -------------------------------------------------------------------------------------------------------- | | `theme` | `"dark"` | Chrome palette: `"dark"` (Catppuccin Mocha) or `"light"` (Catppuccin Latte). Toggle at runtime with `t`. | | `style_source` | none | Module path prefix for auto-generated Styles tab ingredients (e.g., `"my_crate::styles"`). | ## `[colors.*]` Each `[colors.]` table becomes a group in the Styles tab. Two key formats are supported: **Named keys** (snake\_case) render as individual swatches with a colored block, display name, and hex value: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [colors.brand] deep_purple = "#2E1574" white = "#FFFFFF" ``` Named color swatches **Numeric keys** render as a horizontal scale strip showing the gradient across values: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [colors.green] 100 = "#DCFCE7" 500 = "#22C55E" 900 = "#14532D" ``` Scale strip rendering ## `[typography]` Each key renders sample text in its specified color with the description alongside. Color values accept hex (`"#FFFFFF"`) or named ratatui colors (`"DarkGray"`). ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [typography] text = { color = "#FFFFFF", description = "Primary content" } text_dim = { color = "DarkGray", description = "Secondary labels" } ``` Colors and typography entries auto-generate into the **Styles** tab with no ingredient code required. The `style_source` value from `[config]` sets the breadcrumb module path for these generated ingredients. ## `[ingredients]` Declares ingredient modules for compile-time discovery via the `pantry_ingredients!()` proc macro. | Key | Description | | --------- | -------------------------------------------------------------------------------------- | | `source` | Crate name used as the module path prefix. | | `modules` | List of module paths. Each expands to `{source}::{module}::ingredient::ingredients()`. | ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [ingredients] source = "my_crate" modules = [ "widgets::gauge", "widgets::node_table", ] ``` For aggregating ingredients from multiple crates, use array-of-tables syntax: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [[ingredients]] source = "crate_a" modules = ["widgets::foo"] [[ingredients]] source = "crate_b" modules = ["widgets::bar"] ``` The `[ingredients]` section is only needed when using the proc macro. For manual aggregation, omit it and pass ingredients directly to `tui_pantry::run!()`. See [Writing Ingredients](/tui-pantry/writing-ingredients#registration) for details. # Introduction to TUI Pantry Source: https://docs.taho.is/tui-pantry/index A component-driven development tool for ratatui. Build, preview, and iterate on terminal widgets in isolation. Get from zero to a running Pantry Tour the UI and navigation Define previews for your widgets TUI Pantry is a component-driven development tool for [ratatui](https://ratatui.rs). It gives every terminal widget a named, browsable preview organized into Widgets, Panes, Views, and Styles tabs. You can build, iterate, and compose without running your full application. If you've used [Storybook](https://storybook.js.org/) for web components, the Pantry should feel familiar. Three steps to get started: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo install tui-pantry cargo pantry init cargo pantry ``` TUI Pantry Widgets tab ## Why terminal UI needs this There's no Storybook for the terminal. Web developers have had component-driven development tooling for a decade: isolated preview, interactive states, design system documentation. The ratatui ecosystem has widget libraries, but zero infrastructure for developing those widgets visually. We built TUI Pantry because we needed it, and the returns are different in the terminal than on the web. **The feedback loop is slower.** Web has hot module reload. Change a prop, see it in 200ms. TUI has `cargo run`. Change a constraint, wait for a compile, navigate to the right screen, squint at whether a border shifted by one cell. The Pantry doesn't give you HMR, but it eliminates the "navigate to the right screen" tax. TUI is the densest UI medium there is, and that tax compounds fast. **Layout failures are silent.** A web component that overflows its container scrolls or clips visibly. A ratatui widget that overflows its `Rect` just doesn't render the overflow. No error, no warning. You discover it when a user resizes their terminal to 80x24 and half your UI disappears. Building widgets against explicit size constraints in isolation forces you to confront those edge cases before they're buried inside nested layouts. **Reusable widgets need a way to be seen.** Most ratatui developers build widgets inside their application and never publish them. It's not that writing a reusable widget is hard. It's that showing one is. A README with screenshots doesn't let someone feel how a gauge behaves at different sizes, or whether a table handles their edge case. A crate that ships a pantry example changes that. Run `cargo run --example pantry`, browse every variant, and decide in thirty seconds whether this is the widget you need or one you'd rather write yourself. ## The character cell problem Design tools lie to TUI developers. Figma, Sketch, and every pixel-based design tool uses square pixels. Terminal cells are roughly 1:2, half as wide as they are tall. Layouts that look balanced in a mockup collapse or stretch in a real terminal. The Pantry puts the actual constraint surface in front of you: real character cells, real ratatui layout, real rendering. It even lets you [cycle through color depths](/tui-pantry/the-pantry#color-depth-cycling) to see how your widgets degrade across terminal capabilities. ## How it works You define `Ingredient` implementations alongside your widgets, gated behind a feature flag so they never compile into production. Each ingredient is one preview: a specific widget configuration with mock data. You declare your ingredients in `pantry.toml`, and `cargo pantry` launches the Pantry. The Pantry renders a two-pane browser. Sidebar navigation on the left, live widget preview on the right. Four tabs organize your ingredients by scope: **Widgets** for atomic components, **Panes** for composed sections, **Views** for full-page layouts, and **Styles** for your color palette and typography. ## Open source TUI Pantry is open source under MIT/Apache-2.0. Source, issues, and example pantry Rust package registry # Installation Source: https://docs.taho.is/tui-pantry/installation Install TUI Pantry and scaffold a component preview for your ratatui widget crate. ## Prerequisites * Rust toolchain (stable) * A crate with [ratatui](https://ratatui.rs) widgets ## Install ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo install tui-pantry ``` This adds the `cargo pantry` subcommand to your toolchain. ## Initialize From your widget crate root: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo pantry init ``` This does four things: 1. Adds `tui-pantry` as an optional dependency (`cargo add tui-pantry --optional`) 2. Creates `pantry.toml` with default config 3. Scaffolds `examples/widget_preview/` with sample **Widgets**, **Panes**, and **Views** ingredients 4. Prints next steps for wiring your own widgets The scaffold compiles and runs immediately. No additional setup required. ## Launch ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo pantry ``` You should see the Pantry open with sample ingredients across three tabs. Navigate with `j`/`k` or arrow keys, switch tabs with `1` to `4`, and press `q` to quit. TUI Pantry Widgets tab From here, explore the sample ingredients, then replace them with previews of your own widgets. See [Writing Ingredients](/tui-pantry/writing-ingredients) for how to define them. ## Workspace usage In a multi-crate workspace, target a specific package: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo pantry -p my-widget-crate ``` # cargo pantry Source: https://docs.taho.is/tui-pantry/reference/cargo-pantry CLI reference for the cargo pantry subcommand. `cargo pantry` is a cargo subcommand that launches and scaffolds TUI Pantry projects. ## Commands ### `cargo pantry` Launch the Pantry. Requires a `pantry.toml` in the current directory (or a `-p` flag targeting a workspace package that has one). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo pantry ``` Runs `cargo run --example widget_preview --features tui-pantry` with inherited stdio so the TUI owns the terminal. Falls back to `--features pantry` if the first feature name is not found. ### `cargo pantry init` Scaffold a new pantry in the current crate. Requires a `Cargo.toml` in the working directory. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo pantry init ``` This creates: * `tui-pantry` as an optional dependency (via `cargo add tui-pantry --optional`) * `pantry.toml` with default config * `examples/widget_preview/main.rs`: entry point using `tui_pantry::run!()` * `examples/widget_preview/widgets.rs`: sample Widget tab ingredients * `examples/widget_preview/panes.rs`: sample Panes tab ingredients * `examples/widget_preview/views.rs`: sample Views tab ingredients Existing files are not overwritten. The scaffold compiles and runs immediately. ## Flags ### `-p ` / `--package ` Target a specific workspace package: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo pantry -p my-widget-crate ``` All other flags are forwarded to `cargo run`. # Keyboard Shortcuts Source: https://docs.taho.is/tui-pantry/reference/keyboard-shortcuts Quick reference for TUI Pantry keyboard and mouse controls. ## Keyboard ### Navigation | Key | Sidebar | Preview | Fullscreen | | --------------------- | ----------------------------- | ----------------------- | ----------------------- | | `j` / `k` / `↑` / `↓` | Navigate entries | Forwarded to ingredient | Forwarded to ingredient | | `h` / `l` / `←` / `→` | Collapse / expand group | | | | `Enter` | Toggle group or focus preview | | | ### Tabs | Key | Action | | ----------- | --------------------- | | `1` to `4` | Jump to tab by number | | `Tab` | Next tab | | `Shift+Tab` | Previous tab | ### Modes | Key | Action | | ----- | --------------------------------------------- | | `f` | Toggle fullscreen for the selected ingredient | | `Esc` | Return to sidebar from preview or fullscreen | | `q` | Quit the Pantry | ### Display | Key | Action | | --- | --------------------------------------------------------------- | | `c` | [Cycle color depth](/tui-pantry/the-pantry#color-depth-cycling) | | `t` | Toggle theme: dark / light | ## Mouse | Action | Behavior | | --------------------------- | --------------------------------------------------------- | | Click sidebar entry | Navigate to that entry | | Click tab label | Switch to that tab | | Scroll wheel in sidebar | Navigate up / down | | Click / interact in preview | Forwarded to interactive ingredients via `handle_mouse()` | # The Pantry Source: https://docs.taho.is/tui-pantry/the-pantry A tour of the TUI Pantry interface. Layout, tabs, navigation, focus modes, color depth, and themes. The Pantry is a two-pane terminal browser. The sidebar on the left shows a navigation tree of your ingredients. The preview area on the right renders the selected widget with its description, props, and source breadcrumb. ## Tabs Four tabs organize ingredients by scope. Each tab maintains its own independent navigation state. Cursor position, expansion, and scroll offset are preserved when you switch between them. ### Widgets Atomic components in isolation. Each ingredient renders one widget configuration with mock data. Widgets tab ### Panes Composed sections combining multiple widgets into cohesive panels: resource gauges, activity feeds, metric panels. Panes tab ### Views Full-page layouts assembling panes and widgets into complete screens. Use views to preview how your components compose at terminal scale. Views tab ### Styles Color palettes and typography driven from `pantry.toml`. Named swatches with hex values grouped by family, plus text hierarchy samples. No code required. The Pantry auto-generates these ingredients from your [configuration](/tui-pantry/configuration). Styles tab ## Sidebar navigation The sidebar displays a collapsible tree. Groups (widget names) expand to reveal variants underneath. Use `j`/`k` or arrow keys to navigate, `h`/`l` to collapse and expand groups, and `Enter` to toggle a group or focus the preview for interactive widgets. Scrolling follows the cursor automatically. The viewport adjusts to keep the selected entry visible. ## Focus modes The Pantry has three focus modes: 1. **Sidebar** (default). Keyboard input controls navigation. 2. **Preview**. Press `Enter` on an interactive ingredient to give it keyboard and mouse focus. The ingredient receives key and mouse events directly. Press `Esc` to return to the sidebar. 3. **Fullscreen**. Press `f` to expand the selected ingredient to fill the entire terminal. Press `f` or `Esc` to return. ## Color depth cycling Not all terminals support TrueColor. SSH sessions, tmux without passthrough, older emulators, and accessibility configurations quantize your palette down to 256, 16, 8, or monochrome. Press `c` to cycle through all five color depths and see exactly how your widget degrades: * **TrueColor** (24-bit): full palette * **256-color**: xterm extended palette * **16-color**: ANSI standard * **8-color**: ANSI basic * **Mono**: no color The quantization applies to the rendered buffer in real time, showing you what your users actually see in constrained environments. ## Theme toggle Press `t` to toggle between dark mode (Catppuccin Mocha) and light mode (Catppuccin Latte). The default can be set in `pantry.toml`. See [Configuration](/tui-pantry/configuration). # Writing Ingredients Source: https://docs.taho.is/tui-pantry/writing-ingredients How to define preview entries for your ratatui widgets using the Ingredient trait. An **ingredient** is one preview: a specific widget configuration with mock data. You implement the `Ingredient` trait for a struct, and the Pantry renders it in the preview pane with navigation, description, and prop documentation. ## The Ingredient trait Four methods are required: | Method | Purpose | | ---------- | ---------------------------------------------------------------------------------------- | | `group()` | Widget name, shown as a collapsible heading in the sidebar. Shared values nest together. | | `name()` | Variant label, the leaf node under the group. | | `source()` | Module path shown as a breadcrumb in the preview pane. | | `render()` | Draw the widget into the preview area. | Optional methods with defaults: | Method | Default | Purpose | | ---------------- | ----------- | ---------------------------------------------------------------- | | `tab()` | `"Widgets"` | Top-level tab: `"Widgets"`, `"Panes"`, `"Views"`, or `"Styles"`. | | `description()` | `""` | One-line summary displayed in the preview pane. | | `props()` | `&[]` | `PropInfo` slice documenting the widget's configurable surface. | | `interactive()` | `false` | Whether the preview captures keyboard and mouse input. | | `animated()` | `false` | Whether the ingredient needs periodic redraws (33ms tick). | | `handle_key()` | `false` | Process a key event while focused. | | `handle_mouse()` | `false` | Process a mouse event while focused. | ## Basic ingredient A static ingredient is a unit struct with mock data: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use tui_pantry::{Ingredient, PropInfo}; struct GaugeDefault; impl Ingredient for GaugeDefault { fn group(&self) -> &str { "Resource Gauge" } fn name(&self) -> &str { "Default" } fn source(&self) -> &str { "my_crate::widgets::resource_gauge" } fn description(&self) -> &str { "Horizontal bar showing resource utilization with color thresholds" } fn props(&self) -> &[PropInfo] { &[ PropInfo { name: "label", ty: "&str", description: "Resource name" }, PropInfo { name: "ratio", ty: "f64", description: "Fill from 0.0 to 1.0" }, ] } fn render(&self, area: Rect, buf: &mut Buffer) { ResourceGauge::new("CPU", 0.34).render(area, buf); } } ``` Each ingredient module exports a factory function: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} pub fn ingredients() -> Vec> { vec![Box::new(GaugeDefault), Box::new(GaugeHigh)] } ``` ## Interactive ingredient Set `interactive()` to `true` to receive keyboard and mouse input when the preview pane has focus. Press `Enter` in the sidebar to focus an interactive ingredient. Press `Esc` to return. ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} struct TableInteractive { selected: usize, } impl Ingredient for TableInteractive { fn group(&self) -> &str { "Node Table" } fn name(&self) -> &str { "Interactive" } fn source(&self) -> &str { "my_crate::widgets::node_table" } fn interactive(&self) -> bool { true } fn handle_key(&mut self, code: KeyCode) -> bool { match code { KeyCode::Up => { self.selected = self.selected.saturating_sub(1); true } KeyCode::Down => { self.selected += 1; true } _ => false, } } fn render(&self, area: Rect, buf: &mut Buffer) { NodeTable::new(Some(self.selected)).render(area, buf); } } ``` Return `true` from `handle_key()` or `handle_mouse()` to consume the event, `false` to let the Pantry handle it. ## Tab assignment Override `tab()` to place ingredients in a different tab: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} fn tab(&self) -> &str { "Panes" } // composed sections fn tab(&self) -> &str { "Views" } // full-page layouts ``` ## Feature gating Gate ingredient modules behind `#[cfg(feature = "tui-pantry")]` so they don't compile into production: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} // widgets/gauge/mod.rs #[cfg(feature = "tui-pantry")] #[path = "gauge.ingredient.rs"] pub mod ingredient; ``` For flat crates, gate at the crate root: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} // lib.rs #[cfg(feature = "tui-pantry")] pub mod ingredient; ``` ## Registration Declare your ingredient modules in `pantry.toml`: ```toml theme={"theme":{"light":"github-light","dark":"github-dark"}} [ingredients] source = "my_crate" modules = [ "widgets::gauge", "widgets::node_table", ] ``` Each entry expands at compile time to `my_crate::widgets::gauge::ingredient::ingredients()` via the `pantry_ingredients!()` proc macro. The entry point uses this automatically: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} // examples/widget_preview/main.rs fn main() -> std::io::Result<()> { tui_pantry::run!() } ``` For crates without an `[ingredients]` section in `pantry.toml`, pass the factory directly: ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}} fn main() -> std::io::Result<()> { tui_pantry::run!(my_crate::ingredient::ingredients()) } ``` For multi-crate workspaces, see the [array-of-tables syntax](/tui-pantry/configuration#ingredients) in the configuration reference. ## Example pantry The TUI Pantry repository includes a complete [example pantry](https://github.com/taho-inc/tui-pantry/tree/main/examples/example-pantry) showcasing ratatui's stock widgets with a Catppuccin Mocha theme. It demonstrates all four tabs (Widgets, Panes, Views, and Styles) and serves as a reference for the full integration pattern. Run it with: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} cargo run -p example-pantry ```