Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .github/workflows/release-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Build & Release Linux

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (e.g., v0.3.0)'
required: false
type: string

jobs:
build-linux:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 9

- name: Install Rust
uses: dtolnay/rust-action@stable
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dtolnay/rust-action@stable doesn’t appear to be a valid Rust setup action (the commonly used one is dtolnay/rust-toolchain), so this step may fail and break the Linux release workflow.

🤖 Was this useful? React with 👍 or 👎


- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libnotify-dev \
libnss3-dev \
libxss-dev \
libxtst-dev \
libatspi2.0-dev \
libasound2-dev \
libsecret-1-dev \
rpm \
libarchive-tools

- name: Install dependencies
run: pnpm install

- name: Build Rust binary for Linux
working-directory: apps/desktop
run: |
cd speakmcp-rs
cargo build --release
mkdir -p ../resources/bin
cp target/release/speakmcp-rs ../resources/bin/

- name: Run tests
working-directory: apps/desktop
run: pnpm test:run

- name: Build Electron app
working-directory: apps/desktop
run: pnpm electron-vite build

- name: Build Linux packages
working-directory: apps/desktop
run: pnpm electron-builder --linux AppImage deb
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload AppImage
uses: actions/upload-artifact@v4
with:
name: linux-appimage
path: apps/desktop/dist/*.AppImage
retention-days: 30

- name: Upload deb package
uses: actions/upload-artifact@v4
with:
name: linux-deb
path: apps/desktop/dist/*.deb
retention-days: 30

- name: Upload to Release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
with:
files: |
apps/desktop/dist/*.AppImage
apps/desktop/dist/*.deb
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54 changes: 53 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,23 @@ https://github.com/user-attachments/assets/0c181c70-d1f1-4c5d-a6f5-a73147e75182
**[📥 Download Latest Release](https://github.com/aj47/SpeakMCP/releases/latest)**

> **Platform Support**: macOS (Apple Silicon & Intel) with full MCP agent functionality.
> ⚠️ **Windows/Linux**: MCP tools not currently supported — see [v0.2.2](https://github.com/aj47/SpeakMCP/releases/tag/v0.2.2) for dictation-only builds.
> **Windows/Linux**: Voice dictation fully supported. MCP agent tools not yet available on these platforms.

#### Linux Installation

Download the `.deb` package (Debian/Ubuntu) or `.AppImage` (universal) from the releases page:

```bash
# Debian/Ubuntu - Install .deb package
sudo dpkg -i speakmcp_*.deb
sudo apt-get install -f # Install any missing dependencies

# Or use AppImage (no installation required)
chmod +x SpeakMCP-*.AppImage
./SpeakMCP-*.AppImage
```

After installation, SpeakMCP will appear in your application menu, or run `speakmcp` from terminal.

### Basic Usage

Expand Down Expand Up @@ -179,6 +195,42 @@ If using nvm, switch to the recommended version:
nvm use 20
```

**Linux: GPU-related errors in terminal:**

If you see GPU-related errors when launching SpeakMCP from terminal (e.g., "GPU process isn't usable" or "Passthrough is not supported"), the app should still work. These are warnings from Chromium/Electron that don't affect functionality.

If the app fails to launch due to GPU issues, try disabling GPU acceleration:

```bash
SPEAKMCP_DISABLE_GPU=1 speakmcp
```

**Linux: App not appearing in application menu:**

If SpeakMCP doesn't appear in your application menu after installing the .deb package:

```bash
# Update the desktop database manually
sudo update-desktop-database /usr/share/applications

# Update icon cache
sudo gtk-update-icon-cache /usr/share/icons/hicolor

# Log out and back in, or restart your desktop environment
```

**Linux: Permission denied errors:**

If you encounter permission issues with the keyboard listener on Linux:

```bash
# Add your user to the input group (requires logout/login)
sudo usermod -aG input $USER

# For X11 systems, ensure you have xdotool installed
sudo apt install xdotool
```

## ⚙️ Configuration

**AI Providers**: OpenAI, Groq, Google Gemini
Expand Down
14 changes: 14 additions & 0 deletions apps/desktop/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ import {
makePanelWindowClosable,
WINDOWS,
} from "./window"

// Linux GPU workarounds: Prevent GPU-related errors on various Linux configurations
// These flags help with systems that have problematic GPU drivers or run in VMs
if (process.platform === "linux") {
// Disable GPU sandbox which can cause issues on some Linux systems
app.commandLine.appendSwitch("disable-gpu-sandbox")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disable-gpu-sandbox is applied unconditionally on Linux; this disables part of Chromium’s sandboxing and is usually best kept as an opt-in workaround for affected systems.

🤖 Was this useful? React with 👍 or 👎

// Use ANGLE for better compatibility with different GPU drivers
app.commandLine.appendSwitch("use-angle", "gl")
// Disable GPU compositing if hardware acceleration causes issues
// This can be overridden by users who have working GPU acceleration
if (process.env.SPEAKMCP_DISABLE_GPU === "1") {
app.commandLine.appendSwitch("disable-gpu")
}
}
import { listenToKeyboardEvents } from "./keyboard"
import { registerIpcMain } from "@egoist/tipc/main"
import { router } from "./tipc"
Expand Down