Fahh Editor docs
A desktop code editor built on Tauri 2, Rust, React 18 and Monaco. It plays fahh.mp3 when a language server reports an error, at most once per cooldown window.
The sound is src-tauri/assets/fahh.mp3, and src/lib/fahh.ts loads it by that exact name. Renaming the file silences the editor.
Status in v0.5.0
Works
File tree, Monaco editor with tabs, previews (Markdown, HTML, images, SVG, CSV), a built-in localhost browser, Quick Open, terminal, Run panel, Git sidebar, AI panel with Apply-to-file, themes, extensions list, first-run welcome, optional-tools installer, and diagnostics from language servers with the sound.
In progress
Completion, hover and go-to-definition from language servers (the replies are received but not yet shown), and the step-through debugger (the panel and commands exist; event handling is incomplete).
Quick start
Prerequisites
| Tool | Version | Notes |
|---|---|---|
| Rust and Cargo | stable | Tauri 2 needs Rust 1.77.2 or newer. rustup is the easiest install. |
| Node.js | 18 or newer | Vite 5 requires 18; 20 or newer is recommended. |
| pnpm | 9 | The lockfile is version 9.0. npm install -g pnpm |
| Windows only | - | Visual Studio Build Tools with the C++ workload (for the MSVC linker), and the WebView2 runtime, which Windows 11 already has. |
| Linux only | - | sudo apt install libwebkit2gtk-4.1-dev libssl-dev libayatana-appindicator3-dev |
Clone, install, run
git clone https://github.com/Arnav1771/fahh-ide.git
cd fahh-ide
pnpm install
pnpm tauri dev # Vite on :1420, compiles Rust, opens the window
The front end on its own
Useful for UI work. The interface loads in a normal browser, but anything that calls the Rust backend (files, terminal, Git, language servers) will not work there.
pnpm dev # http://localhost:1420
pnpm build # type-check and bundle to dist/
pnpm test # Vitest unit tests
Two processes, one contract
The Rust backend owns the operating system: files, processes, language servers, Git. The React front end owns the interface. They talk over Tauri IPC: the front end calls commands with invoke(), and the backend pushes events the front end receives with listen(). The shared payload types live in src/lib/types.ts, which the Rust structs follow.
┌───────────────────────────────────────────────────────────────┐
│ Front end: the system web view (WebView2 / WebKit) │
│ React 18 · TypeScript · Monaco · Zustand · Tailwind · xterm │
│ FileTree EditorPane + TabBar Terminal Run Git AI │
│ LspBridge (no UI) ── diagnostics → markers → sound │
├────────────────────── invoke() ↓ ↑ events ───────────────────┤
│ Back end: Tauri 2, Rust │
│ workspace editor terminal runner git formatter │
│ lsp_client debugger installer plugin state │
│ error_detector ── emits fahh://error │
└───────────────────────────────────────────────────────────────┘
file system · processes · language servers
Module reference
Rust: src-tauri/src/
lib.rs | Tauri builder, plugins and the registration of all 39 commands. |
core/workspace.rs | File tree and file operations: read, write, create, delete, rename. |
core/editor.rs | Open-document bookkeeping and language detection by extension. |
core/terminal.rs | Runs a command through cmd /C on Windows or sh -c elsewhere; emits terminal://output. |
core/runner.rs | Runs the current file in any of 19 languages (Python, JavaScript, TypeScript, Go, Rust, Java, C, C++, Ruby, PHP, Shell, Lua, Perl, R, Dart, Kotlin, Elixir, Haskell, Zig) with its installed runtime, and streams runner://output. |
core/lsp_client.rs | Starts the language server for a language over stdio and forwards every message as lsp://message. |
core/lsp.rs | Detects rust-analyzer, typescript-language-server, pyright and pylsp on the PATH. |
core/error_detector.rs | The cooldown on the Rust side; emits fahh://error. |
core/git.rs | Status, current branch, stage, unstage, commit and diff. |
core/formatter.rs | Formats a file with an external formatter. |
core/debugger.rs | Debug Adapter Protocol session: start, breakpoints, step, continue, stop; emits dap://event. |
core/installer.rs | Optional tools: checks what is installed and installs on request; emits installer://progress. |
core/plugin.rs | The built-in catalogue of themes, language packs, formatters and snippets. |
core/state.rs | Loads and saves ~/.fahh/config.json. |
TypeScript: src/
lib/types.ts | The payload types both sides agree on. |
lib/tauri.ts | Typed wrappers around invoke(). |
lib/fahh.ts | Decodes fahh.mp3 once with the Web Audio API and plays it on fahh://error. |
lib/cooldown.ts | The front-end cooldown: at most one play per window, no queueing. |
lib/diagnostics.ts | Converts LSP diagnostics to Monaco markers and decides whether any is an error. |
components/LspBridge/ | Starts language servers for open files, draws their diagnostics and triggers the sound. |
components/ | Editor, FileTree, Terminal, RunPanel, GitSidebar, AIPanel, DebugPanel, ThemePanel, ExtensionsPanel, InstallerWizard. |
store/ | Zustand stores for the editor, files, terminal, Git, runner, debugger, AI and theme. |
From diagnostic to sound
The whole path, in order. You can watch steps 3 to 5 happen in the simulator.
- The language server publishes.
lsp_client.rsrelaystextDocument/publishDiagnosticsto the window aslsp://message. - LspBridge draws. The diagnostics become Monaco markers. An empty list clears the file.
- Is any of them an error? Severity 1, or a missing severity, which the LSP specification says to treat as the most severe. Warnings, information and hints stop here.
- Is the cooldown ready? One module-level cooldown for the life of the app. A refused call does not extend the window.
- trigger_error_sound. The command reaches
ErrorDetector, which applies the same cooldown on the Rust side and emitsfahh://error. - fahh.ts plays. The buffer decoded at start-up goes to an
AudioBufferSourceNode, so there is no loading delay.
Tauri commands
All 39 are registered in src-tauri/src/lib.rs, grouped here by the module that implements them.
| Module | Commands |
|---|---|
| workspace | get_file_tree read_file write_file create_file delete_file rename_file |
| editor | open_document close_document get_open_documents |
| terminal | execute_command write_stdin |
| runner | run_file stop_run |
| lsp_client | lsp_start lsp_send lsp_stop |
| error_detector | trigger_error_sound |
| git | git_status git_current_branch git_stage git_unstage git_commit git_diff |
| formatter | format_file |
| debugger | debug_start debug_set_breakpoints debug_step_over debug_step_in debug_continue debug_stop |
| installer | get_tool_status install_tool |
| plugin | get_plugins get_themes get_language_packs get_formatter_plugins get_snippet_plugins |
| state | load_config save_config |
Events
Emitted by Rust, received in the front end with listen() from @tauri-apps/api/event.
| Event | From | Received by |
|---|---|---|
fahh://error | error_detector.rs | lib/fahh.ts - plays the sound. No payload. |
lsp://message | lsp_client.rs | LspBridge - one raw JSON-RPC message from a server. |
runner://output | runner.rs | Run panel - output of the running file. |
terminal://output | terminal.rs | Terminal - stdout, stderr and exit code. |
dap://event | debugger.rs | Debug panel - events from the debug adapter. |
installer://progress | installer.rs | Installer wizard - {tool, status, message}. |
~/.fahh/config.json
Created on first run and safe to edit by hand. Every field is optional.
{
"sfx_cooldown_secs": 3,
"installed_tools": ["gh"],
"last_workspace": "/path/to/project",
"theme": null
}
| Field | Meaning |
|---|---|
sfx_cooldown_secs | Seconds between sounds. Default 3 when the field is missing; 0 plays on every error. |
installed_tools | Tools installed through the wizard. |
last_workspace | Stored, but not yet used to reopen a folder at start-up. |
theme | Reserved. The theme you pick is currently kept in the app's local storage. |
Environment variables
| Variable | Effect |
|---|---|
RUST_LOG | Backend log level: error, warn, info, debug, trace. |
TAURI_ENV_DEBUG | Set by the Tauri CLI for debug builds: turns off minifying and turns on source maps. |
TAURI_ENV_PLATFORM | Set by the Tauri CLI: picks the Vite build target for the platform's web view. |
The installer wizard
Open it from the gear button at the bottom of the activity bar. It checks which tools are already on your PATH, then runs the install command you choose on your own machine, with progress streamed as it goes.
| Tool | Installed with |
|---|---|
| n8n | npm install -g n8n |
| browser-use | pip install browser-use |
| Flowise | npm install -g flowise |
| GitHub CLI | winget install GitHub.cli |
The wizard also offers one AI coding assistant's command-line tool, installed with npm.
Building and packaging
pnpm tauri build # all bundle targets for this OS
cd src-tauri && cargo test # Rust unit tests
cargo clippy --all-targets -- -D warnings # the CI lint gate
Bundles land in src-tauri/target/release/bundle/. The v0.5.0 release was built into:
| Platform | Files |
|---|---|
| Windows | _x64-setup.exe (NSIS), _x64_en-US.msi |
| macOS | _aarch64.dmg, _x64.dmg, and .app.tar.gz for each |
| Linux | _amd64.AppImage, _amd64.deb, x86_64.rpm |
App identifier com.fahh.editor, default window 1400 × 900. Everything runs locally; there is no server and no account.