Skip to content
Conduit

mcp server

aileron

A blazingly fast, keyboard-driven web environment for developers. Native tiling. Lua-configurable. Zero-extension ad-blocking. And an integrated AI MCP server so your LLMs can finally see the web. Bui

WyattAu/aileroncommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 21, 2026

Aileron

v1.0.0 -- 1198 lib tests, 257 integration, 4 doc (1459 total), ~56,900 Rust LOC

The terminal for the web. A keyboard-driven, tiling web environment with an embedded native terminal, built for developers who live in terminals. Written in Rust with wry (WebKitGTK) for web rendering and Leptos WASM for the browser chrome overlay.

Features

Core

  • Vim-style keybindings — modal editing (Normal, Insert, Command) with h/j/k/l navigation
  • Tiling pane management — BSP tree layout with vertical/horizontal splits, pane navigation, and close
  • Command palette — Ctrl+P fuzzy search (Nucleo engine) across history, bookmarks, commands, and custom Lua commands
  • Lua scripting — init.lua for custom keybindings, commands, URL redirect rules, and themes
  • Keybinding customization — override default keybindings via config.toml [keybindings] section
  • Workspace persistence — save/restore pane layouts with URLs via :ws-save / :ws-load; auto-save every 30s for crash recovery
  • Tab management — :tab-restore to reopen closed tabs, :tab-unload to free LRU background pane, :tabs to search open tabs
  • Help panel — :help shows full keybinding reference with collapsible sections
  • Crash recovery — :crash-reload reloads a pane after web content crash
  • MCP bridge — built-in Model Context Protocol server (stdio transport) so LLMs can browse the web
  • ARP (Aileron Remote Protocol) — WebSocket server for mobile clients, tab sync, clipboard sharing
  • Sync protocol — Local/SSH transport with delta detection and E2EE encryption (Age); WebDAV transport planned
  • Cross-platform — PlatformOps trait for Linux, macOS, Windows

Internationalization

  • 9 languages — EN, ZH, JA, KO, DE, FR, ES, PT, RU with :language command
  • Runtime switching — :language <code> changes UI language instantly; :language-list shows available languages

Accessibility

  • ARIA labels — all UI chrome elements include ARIA labels for screen reader support

Browsing

  • Ad blocking — EasyList parser with network + cosmetic CSS rules, $redirect/$important/$badfilter support, filter list auto-update, per-site toggle (:adblock-toggle, :adblock-update)
  • HTTPS upgrade — auto-upgrade HTTP for known-safe domains (EasyList HTTPS list)
  • Tracking protection — blocks known tracker domains, sends DNT/GPC headers, strict referrer policy
  • Popup blocker — blocks unwanted window.open() calls, configurable via :popups
  • Cookie management — view (:cookies), clear (:cookies-clear), per-site allow/block
  • Per-site settings — zoom, adblock, JS, cookies, autoplay per domain (exact/wildcard/regex patterns)
  • Download manager — progress tracking, open file, open directory
  • Browser import — :import-firefox / :import-chrome for bookmarks and history
  • Multiple search engines — pre-configured Google, DuckDuckGo, GitHub, YouTube, Wikipedia; switch with :engine <name>
  • Engine selection — choose rendering engine with :engine auto|servo|webkit (servo: experimental, not yet functional)
  • Adaptive quality — auto-reduces rendering quality when over frame budget (:adaptive-quality)
  • Custom CSS — inject custom stylesheets via config or aileron://settings
  • Link hints — press f to reveal clickable hints on all links, type digits to follow
  • Find in page — Ctrl+F incremental search with next/previous navigation
  • Smooth scrolling — native smooth scroll behavior
  • Print support — :print triggers system print dialog
  • PDF viewer — PDFs render inline via WebKitGTK; :pdf <path> opens local files
  • Reader mode — Ctrl+Shift+R strips CSS and extracts article text; toggle per pane
  • Minimal mode — Ctrl+Shift+M hides images/media and removes scripts; toggle per pane

Terminal

  • Native terminal — press ` to open a terminal pane using alacritty_terminal + portable_pty + egui rendering (no xterm.js, ~2-5MB/pane)
  • Terminal mouse selection — click and drag to select text, copy to clipboard
  • Visual bell — terminal bell triggers a 200ms visual flash
  • SSH quick-connect — ssh user@host in command palette opens terminal pane and auto-connects
  • Terminal search — :terminal-search <pattern> searches scrollback buffer

Tabs & Panes

  • Tab system — sidebar (default), topbar, or none; shows title, URL, pane type, audio/mute/pin indicators
  • Tab pinning — Ctrl+Shift+P or :pin pins a pane (prevents accidental close)
  • Audio mute — :mute / :unmute to silence a pane
  • Pane swap — :swap swaps URLs between active and previously active pane
  • Detach pane — Ctrl+Shift+D detaches pane to standalone popup window
  • Popup windows — Ctrl+N opens standalone webview (no tiling, no egui overlay)

Theming

  • 7 built-in themes — dark, light, gruvbox-dark, nord, dracula, solarized-dark, solarized-light
  • Custom themes — define themes in config.toml under [themes.<name>]
  • Runtime switching — :theme <name> to switch instantly

Privacy & Settings

  • Settings GUI — aileron://settings page for keyboard-navigable configuration
  • Privacy dashboard — :privacy shows HTTPS upgrade, tracking protection, adblock status
  • Bitwarden integration — bw-unlock / bw-search / bw-autofill / bw-detect for credential management
  • Password manager — built-in credential storage with OAuth detection, multi-step login flow support (:credentials, :credentials-save)

Developer Tools

  • DevTools — F12 opens WebKit inspector
  • Network request log — Ctrl+Shift+N or :network shows intercepted fetch/XHR with status codes
  • Console capture — Ctrl+Shift+J or :console shows console.log/warn/error output
  • Git integration — status bar shows branch with dirty indicator; :gs, :gl, :gd, :grep
  • Project search — :grep <pattern> via ripgrep/grep
  • File browser — :files opens project root (auto-detects git root)
  • Shell commands — :! <command> runs shell commands from the command line

Scripting & Extensibility

  • Content scripts — .lua files in ~/.config/aileron/scripts/ with @match and @match-regexp patterns, @run-at (document_start/end/idle)
  • Lua hooks — aileron.on("navigate", fn) and aileron.on("mode_change", fn) in init.lua
  • Command chaining — :open github.com && mg chains ex-commands
  • Did-you-mean — fuzzy Levenshtein suggestions for mistyped commands
  • Custom protocols — aileron:// for internal pages (welcome, settings, files, error)
  • WebExtensions — 9 API traits, extension loading from disk, :extensions/:extension-load/:extension-info commands

Prerequisites

  • Linux (x86_64) — tested on CachyOS (Wayland + NVIDIA), should work on any distro with WebKitGTK 4.1
  • macOS (aarch64, x86_64) — WebKit built-in; requires Xcode command line tools
  • Windows (x86_64) — WebView2 (Edge); experimental, see com.github.WyattAu.aileron.yaml for Flatpak parity
  • Vulkan-capable GPU — required by wgpu for rendering
  • Rust toolchain — rustc, cargo, pkg-config

Build

cargo build

# Run (with runtime library path for WebKitGTK)
LD_LIBRARY_PATH="/usr/lib:$LD_LIBRARY_PATH" ./target/debug/aileron

Test

# Unit tests (1198 tests)
cargo test --lib -- --test-threads=4

# Integration tests (257 tests, 15 suites)
cargo test --tests -- --test-threads=4

# All tests + clippy (zero warnings)
cargo clippy --all-targets -- -D warnings
cargo test -- --test-threads=4

Install

Binary Download

Pre-built binaries for Linux, macOS, and Windows are available on the releases page.

PlatformArchitectureDownload
Linuxx86_64aileron-x86_64-linux
LinuxARM64aileron-aarch64-linux
macOSApple Siliconaileron-aarch64-macos
macOSIntelaileron-x86_64-macos
Windowsx86_64aileron-x86_64-windows.exe

Cargo

cargo install aileron

Arch Linux (AUR)

paru -S aileron-git

Build from Source

git clone https://github.com/WyattAu/aileron.git
cd aileron
cargo build --release
cargo install --path .

Flatpak (experimental)

A Flatpak manifest is provided at com.github.WyattAu.aileron.yaml:

flatpak-builder build-dir com.github.WyattAu.aileron.yaml --force-clean
flatpak-builder --user --install build-dir com.github.WyattAu.aileron.yaml
flatpak run com.github.WyattAu.aileron

Note: Flatpak support is experimental. Targets Freedesktop 23.08 with Rust and LLVM SDK extensions.

Key Bindings

KeyModeAction
iNormalEnter Insert mode
EscInsert/CommandReturn to Normal mode
Ctrl+PNormalOpen command palette
Ctrl+WNormalSplit vertical
Ctrl+SNormalSplit horizontal
qNormalClose pane
Ctrl+H/J/K/LNormalNavigate panes
Ctrl+Alt+H/J/K/LNormalResize pane (shrink/grow in direction)
j / kNormalScroll down/up
Ctrl+D / Ctrl+UNormalScroll half page down/up
H / LNormalGo back / forward
rNormalReload page
Ctrl+BNormalToggle bookmark
Ctrl+FNormalFind in page
fNormalToggle link hints
Ctrl+ENormalOpen in system browser
F12NormalToggle dev tools
yNormalCopy current URL to clipboard
`NormalOpen terminal pane
Ctrl+= / Ctrl+- / Ctrl+0NormalZoom in / out / reset
Ctrl+NNormalOpen popup window (standalone webview)
Ctrl+Shift+RNormalToggle reader mode
Ctrl+Shift+MNormalToggle minimal mode
Ctrl+Shift+NNormalShow network request log
Ctrl+Shift+JNormalShow captured console output
Ctrl+Shift+DNormalDetach pane to popup window
Ctrl+Shift+PNormalPin/unpin active pane
Ctrl+TNormalNew tab
Ctrl+Shift+WNormalClose tab
/NormalFind in page
FNormalFollow link in new tab
GNormalScroll to bottom
Ctrl+gNormalScroll to top
m + letterNormalSet a scroll mark (a-z; configurable via :bind)
' + letterNormalJump to mark (a-z; configurable via :bind)

Commands

CommandDescription
:open <url>Navigate to URL
:help / :?Show keybinding reference panel
:! <command>Run shell command, show output
:set <key> <value>Change config at runtime (search_engine, homepage, adblock, https_upgrade, tracking_protection, popup_blocker)
:m<letter> <url>Set quickmark
:g<letter>Go to quickmark
:swap / :tab-swapSwap URLs between active and previously active pane
:onlyClose all panes except current
:back / :forward / :reloadHistory navigation
:reader / :minimalToggle reader/minimal mode
:settingsOpen aileron://settings
:site-settingsView per-site settings for current URL
:site-settings set <key> <value>Set per-site setting (zoom, adblock, js, cookies, autoplay)
:site-settings listList all per-site settings
:site-settings delete <id>Delete a site setting
:site-settings clear <domain>Clear all settings for a domain
:theme <name>Switch theme
:theme listList available themes
:pinPin/unpin active pane
:mute / :unmuteMute/unmute active pane
:printPrint current page
:pdf <path>Open PDF
:popups [on|off]Toggle popup blocker
:cookiesView cookies for current site
:statsShow adblock, tab, and memory statistics
:cookies-clearClear cookies for current pane
:cookies-block <domain>Block cookies for a domain
:cookies-allow <domain>Allow cookies for a domain
:adblock-toggleToggle adblock for current site
:adblock-countShow blocked request count
:privacyShow privacy settings (HTTPS, tracking, adblock)
:https-toggleCheck HTTPS upgrade status for current domain
:engine <name>Switch search engine (google, ddg, gh, yt, wiki)
:bw-unlock <password>Unlock Bitwarden vault
:bw-search <query>Search vault for credentials
:bw-autofillAuto-fill credentials for current site
:bw-detectDetect login forms on current page
:bw-lockLock Bitwarden vault
:network / :network-clearShow/clear network request log
:console / :console-clearShow/clear console output
:downloads / :downloads-clearShow/clear download history
:downloads-open [id]Open downloaded file
:downloads-dirOpen downloads directory
:import-firefox / :import-chromeImport bookmarks/history from browser
:inspectOpen WebKit inspector
:proxy <url>Set proxy (socks5://, http://)
:clear history|bookmarks|workspaces|cookies|allClear stored data
:grep <pattern>Search project with ripgrep/grep
:gs / :gl / :gdGit status/log/diff
:files / :browseOpen file browser
:ssh <host>SSH in terminal pane
:scriptsList loaded content scripts
:config-saveSave config to disk
:terminal-clear / :clsClear terminal pane
:terminal-search <pattern>Search terminal scrollback
:layout-save <name> / :layout-load <name>Save/load window layout preset
:ws-save <name> / :ws-load <name> / :ws-listWorkspace management
:cmd1 && :cmd2Chain commands
:extensionsList loaded extensions
:extension-load <path>Load extension from path
:extension-info <id>Show extension details
:language <code>Set UI language (en, zh, ja, ko, de, fr, es, pt, ru)
:language-listList available languages
:engine auto|servo|webkitSelect rendering engine
:compat-override add|remove|listManage compatibility overrides
:adaptive-qualityToggle adaptive quality rendering
:adblock-updateUpdate adblock filter lists
:credentialsManage stored credentials
:credentials-saveSave credentials for current site
:perfShow performance overlay
:perf-on / :perf-offToggle performance overlay
:memoryShow memory usage statistics
:tab-restore [n]Restore recently closed tab
:tab-unloadUnload least-recently-used background pane
:crash-reloadReload pane after web content crash
:replace <old> <new> [case]Find and replace in page content
:arp-start / :arp-stop / :arp-statusStart/stop/status of Aileron Remote Protocol

Configuration

config.toml

Aileron looks for ~/.config/aileron/config.toml:

# ── General ──────────────────────────────────────
homepage = "aileron://welcome"         # Start page URL
window_width = 1280                    # Default window width (px)
window_height = 800                   # Default window height (px)
devtools = false                      # Enable WebKit devtools

# ── Privacy ─────────────────────────────────────
adblock_enabled = true                # Block ads from filter lists
adblock_filter_lists = ["https://easylist.to/easylist/easylist.txt", "https://easylist.to/easylist/easyprivacy.txt"]
adblock_cosmetic_filtering = true     # Hide ad elements via CSS
adblock_update_interval_hours = 24    # Filter list update frequency
https_upgrade_enabled = true          # Auto-upgrade HTTP to HTTPS
tracking_protection_enabled = true    # Block tracker domains + DNT headers
popup_blocker_enabled = true          # Block unwanted window.open()

# ── Appearance ──────────────────────────────────
theme = "dark"                        # "dark" | "light" | custom name
tab_layout = "sidebar"                # "sidebar" | "topbar" | "none"
tab_sidebar_width = 180.0             # Sidebar width in pixels
tab_sidebar_right = false             # Sidebar on right side
language = "en"                       # UI language (ISO 639-1)
custom_css = ""                       # Inline CSS or path to CSS file

# ── Rendering ──────────────────────────────────
render_mode = "offscreen"             # "offscreen" (texture) | "native" (window)
engine_selection = "webkit"            # "auto" | "webkit" | "servo"
adaptive_quality = true               # Reduce frame rate when slow

# ── Search ──────────────────────────────────────
search_engine = "https://duckduckgo.com/?q={query}"

[palette]
max_results = 20                    # Command palette result limit

# ── Session ─────────────────────────────────────
restore_session = false               # Restore last workspace on startup
auto_save = true                      # Auto-save workspace for crash recovery
auto_save_interval = 30               # Auto-save interval (seconds)
init_lua_path = ""                    # Path to custom init.lua

# ── Proxy ───────────────────────────────────────
# proxy = "socks5://127.0.0.1:1080"

# ── Sync ────────────────────────────────────────
sync_target = ""                      # SSH target or local path
sync_encrypted = false                # E2EE for sync
sync_auto = false                     # Auto-sync via filesystem watcher
sync_auto_interval_sec = 60           # Auto-sync interval

# ── ARP (Remote Protocol) ──────────────────────
arp_port = 19743                      # WebSocket server port

# ── Keybinding overrides (applied on top of defaults) ──
[keybindings]
# Format: "<key>" = "<Action>"
# Keys: crossterm notation — j, <C-p>, <A-S>, <C-S-i>, <F1>-<F12>
# Actions: PascalCase or shorthand (ScrollDown, vs, sp, Hints)
# "k" = "ScrollUp"
# "<C-S-k>" = "ScrollUp"

# ── Per-domain engine overrides ────────────────
[compat_overrides]
# "example.com" = "webkit"

# ── Custom themes ──────────────────────────────
[themes.mytheme]
bg = "#1a1a2e"
fg = "#e0e0e0"
accent = "#4db4ff"

init.lua

aileron.keymap.set("normal", "Ctrl+Shift+R", "reload")

aileron.cmd.create("open-rust", "Open Rust documentation", function()
    aileron.navigate("https://doc.rust-lang.org")
end)

aileron.url.add_redirect("github.com", "ghproxy.com")

aileron.on("navigate", function(url)
    print("Navigating to: " .. url)
end)

Content Scripts

Place .lua files in ~/.config/aileron/scripts/:

-- ==UserScript==
-- @name        Dark Mode for GitHub
-- @match       https://*.github.com/*
-- @match-regexp    ^https://.*\.github\.com/.*
-- @run-at      document_idle
-- @grant       none
-- ==/UserScript==

return [[
  document.body.style.background = '#1a1a1a';
  document.body.style.color = '#d4d4d4';
]]

Use :scripts to list loaded scripts.

Architecture

src/
  main.rs              -- Event loop, wry pane management, Leptos WASM chrome bridge
  app/mod.rs           -- AppState (mode machine, palette, keybindings, dispatch bridge)
  app/dispatch.rs      -- Pure action dispatch (Action -> ActionEffect)
  app/commands.rs      -- Ex-command handler (60+ commands)
  app/events.rs        -- Key event routing, panel keyboard navigation
  input/               -- Key mapping, mode transitions, keybinding registry with config overrides
  wm/                  -- BSP tree (tiling), rectangle math, pane metadata
  servo/               -- PaneStateManager, PaneRenderer trait, WryPaneManager, ServoPane (skeleton)
  terminal/            -- Native terminal (alacritty_terminal + portable_pty + egui painter)
  ui/                  -- Command palette (Nucleo fuzzy search), panels, omnibox, find bar, help panel
  db/                  -- SQLite: history, bookmarks, workspaces, downloads, site_settings
  lua/                 -- Lua sandbox, API bindings (cmd, keymap, theme, url)
  arp/                 -- Aileron Remote Protocol (WebSocket server, tab sync, clipboard sharing)
  mcp/                 -- MCP JSON-RPC server, tools, stdio transport
  net/                 -- AdBlocker (EasyList parser), filter_list (network/cosmetic), privacy (HTTPS upgrade, tracking protection)
  downloads/           -- Download manager (async, resume, progress tracking)
  extensions/          -- WebExtensions support (9 API traits, extension loading, lifecycle)
  i18n/                -- Internationalization (9 languages, locale resolution, message catalog)
  passwords/           -- Password manager (credential storage, OAuth detection, multi-step login flows, Bitwarden client)
  platform/            -- PlatformOps trait, Linux/macOS/Windows platform implementations
  scripts.rs           -- Content script manager (Lua to JS injection, @match/@match-regexp, @run-at)
  gfx/                 -- wgpu surface + renderer setup
  git.rs               -- Git repo detection, status bar integration
  popup.rs             -- Standalone popup window management
  frame_tasks.rs       -- Frame-level task execution, auto-save, ARP sync
  offscreen_webview.rs -- Offscreen webview texture compositing
  wry_actions.rs       -- WryAction queue utilities
  sync/                -- Sync protocol (delta sync, E2EE via Age, transports)
  profiling/           -- Memory profiling, performance monitoring
  event_handlers.rs    -- Shared key-to-JS event conversion
  workspace_restore.rs -- Workspace save/restore with crash recovery
  bootstrap.rs         -- Application bootstrap, panic hook, environment diagnostics
chrome/
  src/lib.rs           -- Leptos WASM chrome UI (StatusBar, UrlBar, TabSidebar, FindBar, CommandPalette)
shared/
  src/lib.rs           -- Shared types for Rust <-> WASM IPC (Mode, Action, KeyEvent, PaneInfo)
tests/
  integration_smoke.rs -- Cross-module integration tests

Action Dispatch Pattern

Key event -> AppState.process_key_event()
         -> KeybindingRegistry.lookup() -> Action
         -> dispatch_action(Action) -> Vec<ActionEffect>
         -> execute_action() applies effects to AppState
         -> WryAction queue consumed by main.rs

License

Apache-2.0

↑↓ navigate openesc close