# Meshy

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

Meshy is a GTK4/libadwaita client for [MeshCore](https://meshcore.io/). The goal is to provide the best Linux experience.

The app is already fairly feature complete and stable, but note it is still in active development, so things may still significantly change. Feedback with missing features, ideas and bugs is welcome.

<img src="web/screenshot1.png" width="500" alt="Meshy screenshot">
<img src="web/screenshot4.png" width="500" alt="Meshy screenshot">

## Installation

### Flatpak repo

1. Add the repo:
```
flatpak remote-add --if-not-exists meshy https://meshy-app.org/meshy.flatpakrepo
```

2. Install Meshy:
```
flatpak install meshy page.codeberg.sesivany.Meshy
```

Note that if you installed Meshy from the flatpak bundle (provided before), you have to uninstall it and install it from the repo to recieve updates in the future.

### Building from source

#### Flatpak

Install `flatpak-builder` and the GNOME SDK:

```
flatpak install flathub org.gnome.Sdk//50 org.gnome.Platform//50
```

Build and install:

```
flatpak-builder --force-clean --user --install builddir page.codeberg.sesivany.Meshy.json
```

Or to create a `.flatpak` bundle:

```
flatpak-builder --force-clean --repo=repo builddir page.codeberg.sesivany.Meshy.json
flatpak build-bundle repo meshy.flatpak page.codeberg.sesivany.Meshy master
```

All dependencies (including third-party Python packages and native libraries) are handled by the Flatpak manifest automatically.

#### AppImage

Meshy also includes a local AppImage build path intended for packaging tests and release automation.

Build dependencies are the same as the native build, plus:

* `linuxdeploy` (required for AppImage bundling; the script can download it automatically)
* `curl` or `wget` if you want the script to download missing AppImage tools automatically

Build a local AppImage:

```
uv run ./build-aux/appimage/build-appimage.sh --download-tools
```

This is the normal full build path. It writes a staged AppDir and the final AppImage to `dist/`.

If `linuxdeploy` is already installed on your machine, you can skip the download step:

```
uv run ./build-aux/appimage/build-appimage.sh
```

When the script downloads `linuxdeploy` as an AppImage, it runs it with `APPIMAGE_EXTRACT_AND_RUN=1` so CI and other FUSE-less environments do not need `/dev/fuse`.

The final artifact is named like `dist/Meshy-YYYYMMDD-x86_64.AppImage`.

Useful variants:

```
# Stop after producing dist/AppDir for inspection
uv run ./build-aux/appimage/build-appimage.sh --appdir-only --download-tools

# Build an AppImage without QR scanner support
uv run ./build-aux/appimage/build-appimage.sh --download-tools --no-qr
```

The generated AppImage uses the same packaging flow that CI uses, so local runs exercise the release path directly.

#### Native build

##### Dependencies

Build dependencies:

* meson (>= 0.62.0)
* ninja
* python3
* glib2 (gio-2.0, glib-compile-resources, glib-compile-schemas)
* gtk4 (gtk4-update-icon-cache)
* desktop-file-utils (desktop-file-validate)
* appstream (appstreamcli)
* gettext (msgfmt)

Runtime dependencies:

* gtk4
* libadwaita
* gstreamer
* libshumate
* geoclue2
* zbar (optional, for QR code scanning)
* python3-gobject (PyGObject)
* python3-pycryptodome (pip: `pycryptodome`)
* python3-pyzbar (pip: `pyzbar`) (optional, for QR code scanning)
* python3-pyserial
* python3-segno (pip: `segno`)

On Fedora:

```
sudo dnf install meson ninja-build python3 glib2-devel gtk4-devel libadwaita-devel \
  gstreamer1-devel libshumate-devel geoclue2-devel zbar-devel \
  python3-gobject python3-pyserial desktop-file-utils appstream gettext
pip install pycryptodome pyzbar segno
```

On Debian/Ubuntu:

```
sudo apt install meson ninja-build python3 libglib2.0-dev libgtk-4-dev libadwaita-1-dev \
  libgstreamer1.0-dev libshumate-dev libzbar-dev \
  python3-gi python3-pycryptodome python3-pyzbar python3-serial python3-segno \
  desktop-file-utils appstream gettext
```

##### Build options

| Option | Default | Description |
|--------|---------|-------------|
| `qr_scanner` | `true` | Enable QR code scanning support (requires zbar and pyzbar) |
| `shortcuts_dialog` | `true` | Enable keyboard shortcuts dialog (requires libadwaita >= 1.8) |

To build without QR code scanning (e.g. if zbar or pyzbar are not available on your distribution):

```
meson setup builddir --prefix=/usr -Dqr_scanner=false
```

The "Scan QR Code" option will be hidden from the UI when built without this feature.

To build without the keyboard shortcuts dialog (e.g. on systems with libadwaita < 1.8 such as Debian Stable):

```
meson setup builddir --prefix=/usr -Dshortcuts_dialog=false
```

The "Keyboard Shortcuts" menu item will be hidden from the UI when built without this feature.

##### Build and install

```
meson setup builddir --prefix=/usr
meson compile -C builddir
sudo meson install -C builddir
```

## Development

### Code Quality Tools

The project uses automated code quality checks via [pre-commit](https://pre-commit.com/) hooks:

**Setup** (one time):

```bash
# Install pre-commit (Fedora)
sudo dnf install pre-commit ruff

# Or with pip
pip install --user pre-commit ruff

# Install git hooks
pre-commit install
```

**What the hooks do**:
- **Ruff linter** - Fast Python linter checking code style, imports, and common issues
- **Ruff formatter** - Automatic code formatting for consistent style
- **i18n check** - Validates that UI strings are marked translatable
- **Standard checks** - Trailing whitespace, EOF fixes, YAML validation, merge conflict detection

**Usage**:

Hooks run automatically on every commit:
```bash
git commit -m "Fix: something"
# Hooks run automatically and may modify files
```

Manual run on all files:
```bash
pre-commit run --all-files
```

Run just ruff:
```bash
ruff check src/
ruff format src/
```

See [.pre-commit-hooks.md](.pre-commit-hooks.md) for detailed documentation.

### Running Tests

Currently the project uses manual testing via the GUI. Automated unit tests for core modules (protocol, crypto, storage) are planned for future development.

### Project Structure

- `src/` - Python source code
  - `views/` - UI view components (chat, channels, contacts, map, device, settings)
  - `protocol.py` - MeshCore protocol implementation
  - `mesh_crypto.py` - Cryptographic operations
  - `storage.py` - SQLite database management
  - `models.py` - Data models
- `data/` - GTK resources, UI files, icons, schemas
- `po/` - Translation files
- `build-aux/` - Build scripts (AppImage)

## Translations

Meshy uses [Codeberg Translate](https://translate.codeberg.org/) (Weblate) for translations. If you'd like to help with translations, go check [existing ones](https://translate.codeberg.org/projects/meshy/application/). If your language is in the list, you can start translating as a registered user. If it isn't among existing translations, [file a ticket](https://codeberg.org/sesivany/meshy/issues/new) and request it.
