# Hound Antivirus A premium, freemium antivirus for Linux. One engine, three faces: a Rust daemon (`houndd`), a CLI (`hound`), and a Tauri GUI with a system-tray sentinel that changes color with your security state. Built for the distros people actually run: **Ubuntu, Debian, Linux Mint**, and anything else that ships ClamAV. ## Repository layout ``` antivirus/ ├── Cargo.toml # Rust workspace ├── crates/ │ ├── hound-api/ # shared wire types + socket client (daemon/CLI/GUI all use it) │ ├── houndd/ # the daemon: Unix-socket API over a pluggable engine │ └── hound/ # CLI client ├── assets/icons/ # dog-head brand mark + 4-state tray ladder └── gui/ # Tauri 2 desktop app (system tray + scan UI) ``` ## Architecture ``` houndd (Rust daemon — the engine) ┌──────────────────────────────────┐ │ ScanEngine trait │ │ ├─ L1 ClamAV signatures (now) │ │ ├─ L2 Curated threat packs(Pro)│ │ ├─ L3 Behavioral monitor (Pro) │ │ └─ L4 Supply-chain checks(Pro) │ └──────────────┬───────────────────┘ Unix socket (JSON-RPC, line-delimited) ┌───────────┼───────────┐ hound CLI GUI (Tauri) future modules ``` The daemon is the only process that touches a scanning engine. CLI and GUI are thin clients — so future suite tools (firewall, updater, …) plug into the same socket. ### Swapping the engine (the ClamAV seam) ClamAV is a **temporary** dependency. Everything ClamAV-specific — version probe, signature freshness, the `clamscan` subprocess + output parsing, `freshclam` — lives in one file behind a four-method trait: ``` crates/houndd/src/engine.rs trait ScanEngine { name; probe; scan; update } struct ClamAvEngine // today const ENGINE: ClamAvEngine // ← flip this line when the native // engine lands; nothing else in the // daemon, CLI, GUI, or wire API moves ``` The wire stays engine-agnostic: `Status.engine` names the implementation (`"clamav"` today) and `Status.db` carries what any signature store has — a file name and a timestamp. When our own Rust engine ships, it's a new `ScanEngine` implementation, a one-const flip, and the tray/CLI/GUI simply start reporting the new engine name. ## Icon system The brand mark is a solid dog head (`assets/icons/hound.svg`), a single flat fill. It ships in two treatments: - **Brand ladder** `hound-{16,22,24,32,48,256}.png` — native periwinkle `#9896E0`, for the window icon, About box, and marketing. - **Tray-state ladder** `state--{16,22,24,32,48}.png` — the same path re-tinted per security state, for the system-tray sentinel: | State | Fill | Meaning | |---|---|---| | `protected` | `#22C55E` green | up-to-date / protected / clean | | `scanning` | `#F59E0B` amber | scan in progress / signatures need update | | `threat` | `#EF4444` red | infection found | | `paused` | `#6B7280` gray | real-time monitor off | Green is the *good* state; amber is *work in progress*, never a failure. ## Quickstart (development) Prereqs: Rust (see `rust-toolchain.toml`), Node 20+, ClamAV, and the Tauri system libs (`libwebkit2gtk-4.1-dev`, `libgtk-3-dev`, `libayatana-appindicator3-dev`). ```sh # 1. Signatures (needs the clamav freshclam DB) sudo freshclam # 2. Daemon (terminal 1) cargo run -p houndd # 3. Scan (terminal 2) cargo run -p hound -- status cargo run -p hound -- scan ~/Downloads # 4. GUI cd gui && npm install && npm run tauri dev ``` ### Verifying the engine with the EICAR test file EICAR is the industry-standard 68-byte test signature — every AV that works will flag it. Generate it and scan it: ```sh printf 'X5O!P%%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > /tmp/eicar.com cargo run -p hound -- scan /tmp/eicar.com # expect: exit code 1, "Eicar-Test-Signature FOUND" ``` ### Updating signatures `hound update` wraps `freshclam` (trying `sudo freshclam` first, since plain-user runs can't write `/var/lib/clamav` and `/var/log/clamav`). The GUI's "Update Signatures" button drives the same RPC and shows the log. ```sh cargo run -p hound -- update # or: hound update --json ``` ## The GUI (`gui/`) A Tauri 2 desktop app — a thin view over the *same* `houndd` socket the CLI uses (via the shared `hound-api` client), so the window and the command line never disagree about your security state. ``` gui/ ├── dist/ # the front-end (vanilla HTML/CSS/JS, premium dark shell) └── src-tauri/ # Tauri 2 shell + system-tray sentinel ``` The tray sentinel swaps the 4-state icons (green/amber/red/gray) as your state changes; the window shows a live protection hero, a scan progress bar, a results table, and the signature-update log. Build it: ```sh cd gui npm install npm run tauri dev # dev with hot reload npm run tauri build # → .deb in src-tauri/target/release/bundle/ ``` ## Git conventions - Branch `main` is deployable; small, focused commits. - **No hardcoded secrets.** For pushes, the bot token lives in a repo-local credential file (never tracked): ```sh git config credential.helper 'store --file=.git/.git-credentials' chmod 600 .git/.git-credentials echo 'https://:@git.joelovestech.com' >> .git/.git-credentials ``` - Commits: imperative subject, ≤ 72 chars. Example: `houndd: add line-delimited JSON-RPC socket API` ## License TBD — core daemon likely proprietary (freemium), shared CLI possibly OSS. Decision pending; `workspace.package.license = MIT` is a placeholder.