Stitch is a lightweight desktop utility that lets you select a precise slice of a codebase and “stitch” it into a single, shareable text block. It’s designed for LLM chat interfaces you already use—pasteable, auditable, and editor-agnostic.
Originally prototyped in Python/Tk. Now rewritten in Rust + Slint for speed, portability, and a cleaner UX.
- Fast native UI (Slint) with a responsive tree even on large projects.
- Deterministic context packing: you decide exactly which files/dirs are included and how they’re scrubbed.
- Powerful filtering
- Include by extension:
.rs,.toml - Exclude by extension (leading
-):-.lock,-.png - Include takes precedence over exclude when both are present.
- Dotfiles are visible by default.
- Include by extension:
- Language-specific filters (appear dynamically when relevant files are detected)
- Rust: Remove inline comments (
//,/* */), doc comments (///,//!,/** */), extract function signatures only with wildcard filtering - Slint: Remove line comments (
//), block comments (/* */)
- Rust: Remove inline comments (
- Two “only” modes
- Hierarchy Only – just the tree
- Directories Only – only directory names (no file contents)
- “Select from Text…”: paste a previously generated tree to auto-reselect the same files.
- Scrubbing tools
- Remove lines starting with prefixes (e.g.
#, //, --) - Remove regex (wrapped as
(?ms)under the hood) to delete spans/blocks
- Remove lines starting with prefixes (e.g.
- Auto refresh
- Event-driven (via
notify) with a lightweight periodic check; only triggers when changes are relevant given your filters.
- Event-driven (via
- One-click copy of the final output.
- Token & character stats
- Uses
tiktoken-rs(o200k_base) when thetokensfeature is enabled.
- Uses
- Use the chat models you already have—no API keys.
- Full control & auditability: you see exactly what the model sees.
- A curated, minimal context often beats generic retrieval on long-tail tasks.
- Rust (stable) + Cargo
- Optional packaging helpers:
- macOS DMG:
cargo-bundle(auto-installed byjust dmg) justif you want the packaging shortcuts used by CI
- macOS DMG:
cargo run --features ui,tokens
# or optimized:
cargo run --release --features ui,tokensThe default crate features already include
uiandtokens.
Headless builds for tests:cargo test --no-default-features.
cargo build --release --features ui,tokensRequires just:
cargo install just --locked- macOS (.app + .dmg)
just dmg # -> dist/Stitch-<version>.dmg - Windows (.zip with stitch.exe)
just exe # -> dist/stitch-<version>-windows-x86_64.zip - Linux (.tar.gz)
just tgz # -> dist/stitch-<version>-linux-<arch>[-musl].tar.gz
Cross-compile by setting TARGET=<triple> (e.g. x86_64-unknown-linux-musl) before running the recipe.
macOS Gatekeeper note
If you see “Stitch is damaged and can’t be opened”:xattr -cr /Applications/Stitch.app
- Select Folder – choose your project root.
- Adjust Filters (optional):
- Filter Extensions (comma-separated):
- include only:
.rs,.toml - exclude some:
-.lock,-.png - mixing (include wins):
.rs,.md,-.lock
- include only:
- Exclude Directories / Files (comma-separated basenames)
- sensible defaults are pre-filled (e.g.
.git,node_modules,target,LICENSE, lockfiles, etc.)
- sensible defaults are pre-filled (e.g.
- Filter Extensions (comma-separated):
- Select Items – check files or directories. Directory checks cascade; you can override at any level.
- Choose Mode
- Hierarchy Only – emits only the tree
- Directories Only – emits only selected dirs (no file contents)
- Generate Output – you’ll get:
=== FILE HIERARCHY ===(unicode tree)=== FILE CONTENTS ===(unless an “only” mode is active)
- Copy Output – copies the entire output (even if the UI truncates display for very large results).
Paste a Stitch-generated hierarchy (first line = root folder name). Stitch parses it and reselects the files.
Works with CRLF/LF line endings and is tolerant of trailing whitespace/blank lines.
Stitch keeps per-project state in a .stitchworkspace folder (auto-excluded from scans).
- Workspace settings (
workspace.json): the “— Workspace —” entry in the selector. - Profiles: save named selections and settings.
- Shared profiles →
.stitchworkspace/profiles/*.json
Commit these to version control to share with the team. - Local/Private profiles →
.stitchworkspace/local/profiles/*.json
Not for VCS (per-user, machine-specific).
- Shared profiles →
- UI actions:
- Save Workspace Settings (when “— Workspace —” is selected)
- Save / Save As… (choose Shared vs Local)
- Delete, Discard Changes
- The current profile is remembered in
workspace.json.
Git tip
When Stitch creates.stitchworkspacefor the first time, if a root.gitignoreexists, Stitch appends:# Stitch workspace (per-user) .stitchworkspace/local/(only if not already present). This keeps local, per-user state out of your repo while letting you commit shared profiles and workspace defaults.
Stitch is great for team workflows—you can standardize “what to share” for PRs, issues, and LLM prompts.
- Commit the workspace (excluding local):
- Add and commit
.stitchworkspace/to your repo - The
local/subfolder is per-user and should stay ignored (Stitch helps by auto-appending it to.gitignoreon first creation)
- Add and commit
- Share named profiles:
- Create profiles (e.g.,
bug-4321,release-notes,llm-minimal) as Shared - Commit the resulting JSON files under
.stitchworkspace/profiles/ - Teammates pull and select the same profile to get an identical file selection and scrub settings
- Create profiles (e.g.,
- Common patterns:
- PR review kit:
pr-1234profile that captures only the touched areas + relevant context - Minimal repro:
repro-foo-crashprofile that trims the repo to what matters - LLM prompt packs:
api-client-minimal/frontend-depsprofiles you can swap between quickly
- PR review kit:
Why it works well
Profiles are plain JSON and diff nicely in PRs. Everyone can audit exactly what goes in the stitched output. No proprietary format or editor plugin needed.
Stitch provides both language-specific filters (for Rust and Slint files) and generic text-based scrubbing tools. Language-specific filters are applied first, followed by generic text processing.
- Remove lines starting with: comma-separated prefixes (e.g.,
#, //, --).- Full-line comments are removed (leading whitespace allowed).
- Inline comments are removed only when immediately preceded by whitespace (incl. Unicode spaces & tabs).
- Protected regions: content inside normal strings, raw strings (
r#"..."#with hashes), and triple quotes ("""..."""/'''...''') is preserved.
- Remove regex: your pattern is compiled as
(?ms)<your-pattern>(multi-line + dot-matches-newline).- You may quote it with single/double or triple quotes; Stitch will strip the quotes before compiling.
- Language-specific filters (Rust/Slint) - when applicable files are detected
- Generic text scrubbing (prefix removal, regex removal)
- Output formatting (hierarchy generation, content assembly)
⚠️ Generic scrubbing is text-only; it doesn't parse language syntax. Language-specific filters use proper parsing for accurate results. Double-check semantics before pasting back into a compiler.
Stitch includes intelligent language-specific filters that appear dynamically in the UI when relevant file types are detected in your selection. These filters complement the generic scrubbing tools and are applied before text-based processing.
When Rust files are present, you'll see a Rust-specific filters section with these options:
- Remove inline regular comments: Strips
//and/* */comments while preserving content inside strings and raw strings - Remove doc comments: Removes documentation comments (
///,//!,/** */) - Function signatures only: Extracts only function signatures, replacing function bodies with
{ ... }- Signature-only files/folders: Optional wildcard filter (e.g.,
src/*,tests/*,main.rs) to apply signature-only mode to specific paths - Uses
synparsing for accurate AST-based processing with textual fallback
- Signature-only files/folders: Optional wildcard filter (e.g.,
The Rust filters use proper parsing to avoid removing comments inside string literals, raw strings (r#"..."#), and other protected regions.
When Slint UI files are present, you'll see a Slint-specific filters section with:
- Remove single-line comments: Strips
//comments - Remove multi-line comments: Removes
/* */block comments
Slint filters preserve content inside string literals and handle the language's specific comment syntax.
Note: Language-specific filter sections only appear when the corresponding file types (
.rsor.slint) are detected in your current selection. This keeps the UI clean when working with other languages.
- LLM context packing: curate a minimal, auditable set of files.
- Minimal repros: share only the relevant sources + a tree.
- Reviews & handoffs: generate a portable snapshot for PRs/issues/email.
- LLM-guided selection: let a model propose a minimal tree; paste via “Select from Text…”.
- Tech: Rust 2024 edition, Slint,
rfd,notify,regex,chrono,serde/serde_json,dunce,arboard,syn,quote. - Language-specific processing:
- Rust filters use
synfor AST-based parsing with textual fallback for malformed code - Slint filters use custom state machine parsing to handle comment syntax
- Language filter UI sections appear dynamically based on detected file types in the current selection
- Rust filters use
- Auto refresh:
- Event-driven (
notify) pump that filters out irrelevant changes (e.g., excluded dirs/files). - A lightweight periodic check is also in place.
- Event-driven (
- Display limits: the UI shows up to ~50k characters for responsiveness; Copy Output always copies the full text.
- Token counting:
- With the
tokensfeature, Stitch usestiktoken-rs(o200k_base) and counts special tokens. - For very large outputs (>16 MB) or without
tokens, it falls back to a cheap approximation.
- With the
- Extension matching semantics:
- Case-insensitive (
.TXTmatches.txt).
- Case-insensitive (
-
Tests (headless)
cargo test --no-default-featuresCI runs these on Linux/macOS/Windows and also checks the UI build path.
-
Benchmarks (Criterion with HTML reports)
cargo bench # results under target/criterion
- CI:
.github/workflows/ci.yml- Lints (fmt + clippy), tests headless, and verifies the UI build path.
- Releases:
.github/workflows/release.yml- Tag
v*to build portable artifacts for Linux (.tar.gz), Windows (.zip), and macOS (.dmg), then attach to a GitHub Release.
- Tag
ui(default): build the Slint desktop app.tokens(default): enable accurate token counting withtiktoken-rs.
Headless library/test builds:
cargo build --no-default-features
cargo test --no-default-featuresWhen built without
ui, thestitchbinary only prints a helpful message; the core library remains available for tests.
- Very large repos: first scan can be heavy—lean on filters early.
- Binary/huge files: not specially parsed; consider excluding them.
- Multi-dot extensions: only the last segment is considered (e.g.,
.tar.gz→.gz). - Scrubbing: may remove content inside comments/strings in ways that matter to your code—review before sharing.
Issues and PRs welcome—especially around defaults (exclusions), performance, UI polish, and integrations.
If adding assets, place third-party licenses in LICENSES/.
This project is licensed under the MIT License — see LICENSE for details.
It also bundles third-party assets:
- JetBrains Mono font, licensed under the
SIL Open Font License 1.1.
All third-party licenses are collected in the LICENSES/ folder.