As an avid Ubuntu user I was horribly disgusted with the lack of support for Linux in the ChatGPT app, alternative open source projects suffer from feature bloat. So I told Claude to make the best Linux AI app for my own use. Enjoy if works for you too. :)
-
We are not competing in the agentic coding realm. Just use Cursor bro.
-
This will always be free open software with no paid subscription tiers with locked features.
-
This is not a local-ai monolith to run all your niche weirdo local AI LLMs and tinker with CUDA.
This is an app for integrating AI intelligence into your Linux computer.
π Documentation: https://christophertrimboli.github.io/linux-ai/
A Linux-first AI chat app that can act on your computer through a small set of built-in tools, available as both a desktop app and a CLI. Bring your own API key (Anthropic, OpenAI, or any OpenAI-compatible endpoint, including a local one).
- Desktop app β Tauri 2 (Rust) + Svelte 5. Tiny, fast, native WebKitGTK.
- CLI (
lai) β one-shot prompts, stdin piping, and an interactive chat REPL. - Shared Rust core (
la-core) β both front ends use the exact same engine: multi-provider streaming, tool execution, approval gating, and local history.
| Tool | Risk | What it does |
|---|---|---|
system_info |
read-only | OS, kernel, CPU, memory, disk usage |
read_file |
read-only | Read a text file (within allowed roots) |
list_dir |
read-only | List a directory |
search_files |
read-only | Recursive name/content search |
write_file |
mutating | Create/overwrite a file (needs approval) |
run_shell |
mutating | Run a shell command (needs approval) |
open |
mutating | Open a file/URL with xdg-open (needs approval) |
Read-only tools run automatically. Mutating tools require explicit approval (an
inline card in the desktop app, a [y/N] prompt in the CLI) unless you enable
auto-approve. File access is restricted to configured roots (your home directory by
default) and shell commands are screened against a deny-list.
The desktop app has a mic button in the composer. Click it to record from your
default input device (it turns red while listening), click again to stop β the
audio is encoded to WAV locally and transcribed via an OpenAI-compatible
/audio/transcriptions endpoint, then dropped into the input box for you to edit
and send. The provider and model are configurable under Settings β Voice input.
It defaults to the openai provider with gpt-4o-transcribe (OpenAI's current
best transcription model β lower word-error-rate than whisper-1 at the same
price). Other suggested options: gpt-4o-mini-transcribe (cheaper/faster) or
whisper-1 (legacy).
Other STT providers work too:
- OpenRouter β select the
openrouterprovider and a slugged model likeopenai/gpt-4o-transcribeoropenai/whisper-1(uses OpenRouter's JSON audio API and your existing OpenRouter key). - Local / offline β point a provider at a whisper.cpp / faster-whisper server and
use its model name (
whisper-large-v3,whisper-large-v3-turbo, β¦).
linux-ai/
crates/
core/ # la-core: providers, tools, agent loop, SQLite store, config
cli/ # `lai` binary
desktop/
src/ # Svelte 5 + Vite frontend
src-tauri/ # Tauri 2 Rust app (depends on la-core)
- Rust stable 1.88 or newer (developed on 1.96). Install/upgrade with
rustup update stable. - For the desktop app only, Node.js 18+ and the Tauri Linux system libraries:
# Debian/Ubuntu
sudo apt update
sudo apt install -y \
libwebkit2gtk-4.1-dev build-essential curl wget file \
libxdo-dev libssl-dev libdbus-1-dev libasound2-dev \
libayatana-appindicator3-dev librsvg2-dev pkg-config# Fedora
sudo dnf install -y webkit2gtk4.1-devel openssl-devel curl wget file \
libxdo-devel dbus-devel libappindicator-gtk3-devel librsvg2-devel alsa-lib-develThe CLI and core do not require any of the above β only a Rust toolchain.
# from the repo root
cargo build --release -p linux-ai-cli # builds ./target/release/lai
cargo install --path crates/cli # installs `lai` onto your PATHcd desktop
npm install
npm run tauri dev # dev build with hot reload
npm run tauri build # produces a .deb and an AppImage under src-tauri/target/release/bundleA snap/snapcraft.yaml is included for building/distributing
as a snap (strict confinement). Build it locally with snapcraft, or let the
Snap workflow build/publish it. Note that strict
confinement sandboxes the computer-access tools to your home directory β for full
system access prefer the .deb/AppImage. See the
Snap guide for details.
The desktop bundle targets (deb, appimage) and icons are configured in
desktop/src-tauri/tauri.conf.json. Icons are
generated by desktop/src-tauri/gen_icons.py.
Installed .deb / AppImage builds register their own icon. But when running
npm run tauri dev (or any unpackaged binary) on Wayland, GNOME shows a
generic dock icon because it resolves icons by matching a window's app_id to an
installed .desktop file. The app sets its app_id to dev.linux-ai.app
(enableGTKAppId in the Tauri config); run this once to install a matching
desktop entry + themed icons for your user:
desktop/install-desktop-entry.sh # install (re-run anytime)
desktop/install-desktop-entry.sh --uninstallRestart the app (or log out/in) and the dock will show the real icon.
lai "what is using port 8080?" # one-shot prompt
cat error.log | lai "explain this" # pipe stdin into the prompt
lai chat # interactive REPL (Ctrl-D / 'exit' to quit)
lai providers # list providers and whether a key is set
lai models openai # list known models for a provider
lai auth anthropic # store an API key in the OS keyring
lai config # show config + data file locations
lai -p openai -m gpt-4o "hello" # override provider/model for one run
lai -y "tidy up ~/Downloads" # auto-approve tool actions for this run- Config:
~/.config/linux-ai/config.toml(created on first run). - History:
~/.local/share/linux-ai/linux-ai.db(SQLite). - API keys are resolved in this order: OS keyring β environment variable
(
ANTHROPIC_API_KEY,OPENAI_API_KEY,OPENROUTER_API_KEY, ...) β plaintextapi_keyin the config. Store keys withlai auth <provider>or via the desktop Settings panel.
Out of the box there are providers for Anthropic, OpenAI, OpenRouter
(access 400+ models behind one key, e.g. openrouter/auto), and a local
OpenAI-compatible endpoint (Ollama). You can add any other OpenAI-compatible endpoint
by editing the [providers.*] tables in the config and pointing base_url at it.
- Mutating tools are gated behind explicit approval by default.
- Filesystem tools are confined to configured roots (home directory by default).
- Shell commands are screened against a configurable deny-list.
- Everything runs locally; the only network calls are to the LLM provider you configure.
Pushing a version tag builds and publishes a GitHub Release with the production
artifacts for both x86_64 and aarch64 Linux (CLI tarball + .deb +
AppImage per arch) via .github/workflows/release.yml:
git tag v0.1.0
git push origin v0.1.0You can also trigger it manually from the Actions tab (provide the tag as input).
The workflow uses the committed Cargo.lock and desktop/package-lock.json, so
make sure those are committed.
The git tag is the single source of truth for a release's version. Tags must
be semver (vMAJOR.MINOR.PATCH, optionally -rc.1 etc.); the workflow rejects
anything else. At build time it strips the leading v and stamps that version
into the workspace Cargo.toml (which every crate and the CLI inherit) and
desktop/package.json. The desktop bundle has no version of its own in
tauri.conf.json β it inherits the workspace crate version β so the CLI, the
crates, and the .deb/AppImage all carry the exact tag version with nothing to
keep in sync by hand. The 0.1.0 checked into the repo is just the dev default.
- MCP client support for external tools
- Voice input/output
- Vision-based computer use (screenshot + mouse/keyboard control)
MIT β see LICENSE.