ashlar-rs 0.1.0

Build fast desktop and web apps in Rust: store, commands, UI, native, agent control
Documentation

ashlar

A lightweight, modern application framework for Rust, powered by egui.

CI crates.io docs.rs MSRV License: BSD-3-Clause

ashlar gives a desktop (and, for its headless core, web) application the parts every app rebuilds: documents with undo and autosave; commands that drive menus, shortcuts, a command palette, a CLI and an MCP server; background jobs; files and settings; native OS features; a component library on egui; and crash safety and telemetry. An idle ashlar app does no work at all.

Status: early (0.1). The API will change between minor versions until 1.0.

Why ashlar

  • Everything is a command. Menus, shortcuts, the palette, the CLI, the control port and MCP all go through one registry and one execute chokepoint, so anything a user can do, a script or an AI agent can do too.
  • Never crashes. No unwrap, panic! or unsafe outside tests (enforced by lints and a CI gate). Panics in a view, a command or a job are caught; the session survives and unsaved work is recovered on the next launch.
  • Zero work when idle. Frames are drawn only when something asks for one: input, a document change, a finished job. No polling.
  • Headless core. Documents, commands, jobs and files never touch the UI, so they run in tests, in a CLI, behind MCP and in the browser.
  • Small crates. Use the umbrella crate, or pick only the layers you need: each ashlar-* crate works on its own.

Quick start

cargo add ashlar-rs

The package is published as ashlar-rs; the library is still imported as ashlar.

use ashlar::prelude::*;

#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
struct Doc {
    notes: Vec<String>,
}

fn add(s: &mut Session<Doc>, p: &Value) -> Result<Value, CommandError> {
    let text = p.get("text").and_then(Value::as_str).unwrap_or("New note").to_string();
    s.edit("Add Note", |d| d.notes.push(text)); // one undo step per command
    Ok(json!(s.doc().notes.len()))
}

fn main() -> Result<(), ashlar::app::Error> {
    App::<Doc>::new("jot", env!("CARGO_PKG_VERSION"))
        .format(Format::new("example.jot", "jot 0.1"))
        .commands([cmd!("note.add", "Add Note", ["Edit"], Some("Mod+Shift+N"), [Param::string("text")], always, add)])
        .view(|ui, cx: &mut Cx<'_, Doc>| {
            for n in &cx.doc().notes {
                ui.label(n);
            }
            if ui.button("Add").clicked() {
                cx.dispatch("note.add", json!({}));
            }
        })
        .run() // undo/redo, save/open/autosave, menus, palette, crash guard, control port
}

App::cli() turns the same definition into a -cli binary with commands, exec, run, mcp and serve. --control <port> lets an agent drive the window. Try the examples:

cargo run -p ashlar-example-notes      # a small document app
cargo run -p ashlar-example-gallery    # every UI component

The umbrella crate's optional features are native-menu (the app's commands in the macOS and Windows menu bar) and telemetry (crash, performance and usage reports to a server you host):

cargo add ashlar-rs --features native-menu,telemetry

Crates

Every crate is published on crates.io under the same version, with its API docs at https://docs.rs/<crate>. Depend on a single layer when that's all you need, for example cargo add ashlar-store for documents and undo in a headless tool.

Crate What it is
ashlar-rs The umbrella crate (use ashlar::…): re-exports the layers below behind features
ashlar-app The runtime: App builder, frame scheduler, crash guard, logging, agent control
ashlar-ui UI components on egui: theme tokens, controls, layout, docking, icons
ashlar-store Documents: Arc snapshots, revisions, undo history, versioned formats, autosave
ashlar-command Commands: registry, typed params, one execute chokepoint, discovery
ashlar-jobs Background jobs: progress, cancel, panic isolation, apply on the UI thread
ashlar-fs Files and settings: app folders, atomic writes, keyed settings, recent files
ashlar-log Logging and crash safety: filters, rotating file, in-memory ring, panic hook
ashlar-native OS features behind one API: dialogs, menus, clipboard, power, notifications, secrets
ashlar-control The agent control port: a hardened JSON-lines server and client
ashlar-cli Standard CLI verbs over the command registry
ashlar-mcp, ashlar-mcp-http An MCP server generated from the command registry (stdio, or HTTP on loopback)
ashlar-agents Connect coding agents to an app: MCP config, skills and rules
ashlar-assistant An in-app AI assistant harness, independent of the model provider
ashlar-integrations Code-signed tool servers installed from a catalog and run over MCP
ashlar-debug Drive a running app's UI from the shell: snapshot, click, wait, screenshot
ashlar-docs Documentation for agents, embedded at build time
ashlar-update Update checks against a releases API
ashlar-print Send a PDF to the system print spooler (CUPS, Windows)
ashlar-obfuscate Compile-time string obfuscation
ashlar-telemetry, ashlar-trace, ashlar-trace-server, ashlar-trace-proto Self-hosted crash, performance and usage telemetry (docs)

How the crates stack is in docs/architecture.md.

Compatibility

Supported
Rust 1.95 or newer (edition 2024). CI tests on the latest stable and checks the MSRV.
egui / eframe 0.36, wgpu renderer
macOS Apple silicon and Intel (CI: macos-latest, arm64)
Windows 10 or newer, x86_64 (CI: windows-latest)
Linux x86_64, X11 and Wayland (CI: ubuntu-latest). Native dialogs use the XDG desktop portal.
Web wasm32-unknown-unknown for the headless core (commands, store, files, jobs, logging; checked in CI). The windowed runtime on the web is experimental.

Linux build dependencies (Debian/Ubuntu names):

sudo apt-get install libgtk-3-dev libxdo-dev libxkbcommon-dev libdbus-1-dev

Native features differ by platform. Where one isn't available, the call returns NativeError::Unsupported and nothing panics. Some highlights (the full matrix is in crates/native):

Feature macOS Windows Linux Web
File dialogs yes yes yes (portal) open only
Native menu bar yes yes in-window menu in-window menu
Clipboard (text, image) yes yes yes no
Notifications bundled apps no yes (D-Bus) no
Secrets (OS keychain) Keychain Credential Manager Secret Service no
Printing CUPS Windows spooler CUPS no

Built on egui, eframe, wgpu, rfd, muda and rustls.

Built with ashlar

  • bay and bay-effects by Marl Studio are built on top of ashlar.

Building something with ashlar? Open a pull request to add it here.

Documentation

Contributing

Contributions are welcome. Read CONTRIBUTING.md first. Every change must pass cargo xtask ci. Please follow the Code of Conduct, and report security issues privately as described in SECURITY.md.

License

ashlar is licensed under the BSD 3-Clause License. Unless you say otherwise, any contribution you submit for inclusion in ashlar is licensed the same way.