Scratchpad is a Windows-first plain-text editor written in Rust. It is built as a safer, more capable Notepad replacement for everyday text work: notes, logs, exports, terminal output, reports, encoded files, and temporary scratch work.
The app is deliberately not an IDE. It focuses on fast local editing, resilient session restore, visible file-format risk, and multi-file workspaces without language servers, plugin execution, or cloud sync.
Windows remains the primary desktop and release target. Scratchpad also builds and runs on Linux, with first-class NixOS/Hyprland packaging and a Hyprland platform profile for compositor-managed window behavior.
- Opens files as separate tabs or into the active workspace as editor tiles.
- Lets a workspace tab contain multiple tiled views, including several views of the same file.
- Supports tile splitting, divider resizing, tile promotion, tab combining, drag/drop tab ordering, multi-tab selection, and tab overflow.
- Provides search and replace across the selection, active file, current workspace tab, or all open tabs.
- Supports plain-text and regex search, case-sensitive matching, whole-word matching, replace current, and guarded replace-all.
- Detects BOMs and common encodings, preserves supported BOM and line-ending metadata, and warns before saves that may lose or corrupt characters.
- Makes control characters and artifact-heavy text visible, including ANSI escape sequences, carriage-return output, overprint patterns, and other non-printing characters.
- Keeps per-document undo/redo history plus a text-history dialog for reviewing and navigating recent edit operations.
- Restores sessions, open buffers, workspace layout, settings, tab placement, pane layout, and file metadata.
- Includes in-app settings for text formatting, appearance, opening behavior, tab placement, status bar visibility, undo memory budgets, platform profile, and shortcut overrides.
- Supports command-line startup switches for clean launches, session restore, opening files, and adding files into an existing workspace.
- Supports Windows, generic Linux, and Hyprland platform profiles so native window decorations, app-rendered caption buttons, drag regions, and resize behavior can match the current desktop environment.
- Keep everyday text editing fast, predictable, and local.
- Show risky encoding, newline, and disk-state decisions before bytes are written.
- Treat restored state as important user data, especially unsaved work.
- Keep the product centered on plain text instead of drifting into a coding workflow.
- Use profiling, capacity probes, benchmarks, and CI as regular development inputs.
- Let the operating system or compositor own global window-management shortcuts; Scratchpad owns only in-app actions while focused.
Prerequisites:
- Rust via
rustupor the provided Nix development shell - Windows for the primary app target and MSI release flow
- Linux desktop libraries for Linux builds (
gtk3, Wayland/X11, fontconfig, OpenGL/Vulkan loader, and relatedegui/winitruntime dependencies) - .NET local tools when packaging the Windows MSI
Common development commands:
cargo run --release
cargo test
cargo clippy --lib --all-features -- -D warnings
cargo fmt --check
cargo build --releaseNix development and Linux runs:
nix develop
cargo check
nix run .#scratchpad
nix run .#scratchpad-hyprlandThe Hyprland wrapper sets WINIT_UNIX_BACKEND=wayland and
SCRATCHPAD_PLATFORM_PROFILE=hyprland so Scratchpad hides app-rendered caption
buttons and leaves compositor-level window management to Hyprland.
Linux defaults to eframe's wgpu renderer on egui 0.35+. Set
SCRATCHPAD_RENDERER=glow to force the OpenGL renderer when diagnosing driver
or compositor issues.
Optional egui inspection / MCP support is available for UI automation and accessibility-tree debugging:
cargo run --features inspection
EGUI_INSPECTION=1 cargo run --features inspectionWith EGUI_INSPECTION=1, eframe listens on egui's inspection port so tools such
as egui_mcp can inspect and drive the running app.
Useful runtime switches:
scratchpad.exe /help
scratchpad.exe /version
scratchpad.exe /clean "C:\notes\a.txt"
scratchpad.exe /here "C:\notes\a.txt"
scratchpad.exe /addto:active /files:"C:\notes\a.txt","C:\notes\b.txt"
scratchpad.exe /addto:index:2 "C:\notes\c.txt"Scratchpad stores user-editable settings in settings.toml under the platform
settings root (%APPDATA%\Scratchpad on Windows and
$XDG_CONFIG_HOME/scratchpad or ~/.config/scratchpad on Linux). The platform
profile defaults to automatic detection but can be pinned explicitly:
[platform]
profile = "hyprland" # auto, windows, linux_generic, or hyprlandTop-level in-app shortcuts can be overridden without changing compositor/global shortcuts:
[shortcuts]
open_file = "ctrl+o"
save_file = "ctrl+s"
close_tab = "ctrl+w"
toggle_tab_list = "ctrl+alt+b"
split_tile = "alt+enter"
split_left = "alt+ctrl+left"
split_right = "alt+ctrl+right"
split_up = "alt+ctrl+up"
split_down = "alt+ctrl+down"
move_tile_left = "alt+left"
move_tile_right = "alt+right"
move_tile_up = "alt+up"
move_tile_down = "alt+down"
resize_tile_left = "alt+shift+left"
resize_tile_right = "alt+shift+right"
resize_tile_up = "alt+shift+up"
resize_tile_down = "alt+shift+down"Tiling shortcuts all hang off a single alt leader — the in-app stand-in for
the compositor's super key, which Hyprland reserves globally. The base key
mirrors the equivalent Hyprland bind, so muscle memory carries over: where
Hyprland uses super+enter to spawn a tile, Scratchpad uses alt+enter to
split; super+arrow ↔ alt+arrow to move a tile, and so on. The editor leaves
all alt-modified keys to this layer, so they never clash with text editing
(word-wise navigation stays on ctrl+arrow).
Shortcut strings are case-insensitive. Supported modifiers are ctrl, shift,
alt, and command/super/win. Multiple bindings can be separated with
commas, so you can add focused-app super bindings such as
split_tile = "alt+enter, super+enter" if those keys are not reserved by the
compositor.
The release workflow builds Windows and Linux artifacts in parallel, then publishes them together only after both jobs pass. It checks formatting, clippy, tests, Cargo/Nix version consistency, and the Nix flake. Windows produces a signed MSI when signing is configured; Linux produces an x86_64 archive with generic and Hyprland launchers, a desktop entry, an icon, and a checksum.
Release tags use the vX.Y.Z format, matching the package versions in both
Cargo.toml and flake.nix.
Local Windows installer packaging:
dotnet tool restore
cargo build --release --locked
.\scripts\package-windows-installer.ps1 -Version 0.40.0Linux/Nix packaging entry points:
cargo build --release --locked
./scripts/package-linux-release.sh 0.40.0
nix build .#scratchpad
nix build .#scratchpad-hyprland
nix run github:pmfleming/scratchpad#scratchpad-hyprlandThe flake also exposes homeManagerModules.default, which can install the
regular package or the Hyprland wrapper, write ~/.config/scratchpad/settings.toml,
and generate Hyprland autostart, binds, and window rules:
programs.scratchpad = {
enable = true;
profile = "hyprland";
hyprland = {
autoStart = true;
workspace = "5";
};
};This starts Scratchpad tiled on regular workspace 5 at login without changing
the active workspace. A Waybar icon assigned to workspace 5 remains the direct
entry point for Scratchpad. For a non-Nix installation, install the GitHub
release archive and add the equivalent Hyprland settings:
exec-once = scratchpad-hyprland
windowrule = match:class ^(scratchpad)$, workspace 5 silentThe release workflow publishes scratchpad-vX.Y.Z-linux-x86_64.tar.gz and its
SHA-256 checksum. See
the Hyprland configuration notes for the
full Home Manager module and plain compositor configuration.
Scratchpad owns the Rust probes and benchmarks that compile against the app. The reusable measurement producers and dashboard live in sibling repositories.
Scratchpad-owned measurement entry points include:
src/bin/capacity_probe.rssrc/bin/frame_metrics.rssrc/bin/resource_probe.rssrc/bin/profile_*.rsbenches/search_speed.rsbenches/frame_budget.rs
Generated measurement artifacts are written under target/analysis/ for the
sibling dashboard to consume.
The current measurement boundary is documented in docs/measurement-tools.md.
src/
main.rs Desktop entry point and native window setup
lib.rs Public crate surface
app/
app_state/ Frame loop, workspace state, settings, search state
chrome/ Custom window chrome and caption buttons
commands/ Command dispatch and workspace operations
domain/ Buffers, piece-tree storage, panes, tabs, views
services/ File IO, search, sessions, settings, background work
startup/ Command-line parsing and startup options
ui/ Editor, dialogs, settings, search/replace, tabs
platform.rs Platform profile detection and desktop capabilities
platform_file.rs Platform-specific file dialogs and reveal/open actions
bin/ Profiling, resource, frame, and capacity probes
crates/
linux_file_watch/ Linux file-change watching helper crate
windows_file_watch/ Windows file-change watching helper crate
benches/ Criterion benchmark targets
scripts/ Release and analysis helper scripts
packaging/
nix/ Home Manager module and Linux packaging helpers
windows/ Windows installer definition and support files
.github/workflows/ CI and release automation
docs/ User manual, architecture notes, and reviews
assets/ Project artwork
fonts/ Bundled editor and control-symbol fonts
- Stack: Rust 2024,
eframe/egui,egui-phosphor,rfd,serde,encoding_rs,chardetng,regex,smallvec,sysinfo, and a local Windows file-watch crate. - Unsafe Rust is forbidden at the crate level.
- Text storage uses a piece-tree-backed document model with undo/redo history and cheap snapshots for save and session flows.
- Runtime logs are written under
log/. - Settings use the platform settings root; session state uses
%LOCALAPPDATA%\Scratchpadon Windows and$XDG_STATE_HOME/scratchpador~/.local/state/scratchpadon Linux, with the legacy temp directory used as a fallback/migration source.