Files
ai-app/server/Cargo.toml
T
iris b172c464ea ai-app: a phone interface to Claude Code and llama.cpp sessions
A Rust backend that owns the sessions and an Android app that reads them.
The server spawns and adopts CLI processes, normalises everything they emit
into one event model, keeps the transcript, and serves it over pinned TLS on
a WireGuard interface; the phone streams that, replies, sends images, and
imports conversations the machine already has.

`AGENTS.md` is the working guide -- what runs where, what has been measured,
and the faults that were expensive to find. `PLAN.md` is the design record.

History before this point was squashed away. It was a personal project's
running commentary and carried a name and a couple of machine paths that
have no business in a public repository; the tree is what mattered and the
tree is here.
2026-08-31 20:29:07 -04:00

55 lines
2.3 KiB
TOML

[package]
name = "ai-server"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "ai-server"
path = "src/main.rs"
[dependencies]
# The link both this and dev-updater need in order to be reached from a
# phone: wg binding, the pinned CA, QR enrollment, owner-only files, and
# the RON house rules. Extracted from the two copies that had drifted --
# see that repo's README for the evidence and the bug the extraction found.
wg-app-link = { path = "../wg-app-link/server" }
axum = { version = "0.8", features = ["json", "multipart"] }
axum-server = { version = "0.8", features = ["tls-rustls"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "sync", "time", "process", "io-util", "signal"] }
# `sync` for BroadcastStream: the notifications route turns the manager's
# broadcast channel straight into an SSE body, which is the one place here a
# broadcast receiver has to be a Stream rather than something to poll.
tokio-stream = { version = "0.1", features = ["sync"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# The config file's format. Not JSON, because this file is written and read
# by hand and RON says a sum type as syntax. The two house rules both
# projects write it under live in wg-app-link; this is here for the error
# types the schema's own signatures name.
ron = "0.12.2"
clap = { version = "4", features = ["derive"] }
anyhow = "1"
thiserror = "2"
# Verifying a downloaded model against HuggingFace's published digest.
sha2 = "0.11"
# Naming a session directory, and an attachment inside one.
rand = "0.10"
# Decoding the images a phone attaches, and encoding them for a driver.
base64 = "0.23"
# Outbound HTTPS for the usage endpoint. A small blocking client fits an
# every-few-minutes poll better than pulling in reqwest's tower stack;
# rustls-backed like the rest of the TLS here.
ureq = { version = "3", features = ["json"] }
# Direct dependency only to pick the process-level CryptoProvider in main:
# ureq pulls rustls-with-ring, axum-server rustls-with-aws-lc-rs, and with
# both in the graph rustls refuses to auto-select one.
rustls = "0.23"
libc = "0.2.189"
[dev-dependencies]
tempfile = "3"
# ServiceExt::oneshot, to drive the auth middleware without a socket.
tower = { version = "0.5", features = ["util"] }