KDX

KDX Hotline · Packaging & Distribution · Handoff v0.1 · Handoff v0.2 · UI Concept

Packaging & Distribution

Work order for the next session — server daemon + desktop client, ready to ship.

Contents
  1. Context & scope
  2. Current state
  3. Open questions
  4. Server — kdxd
  5. Client — KDX.app
  6. README
  7. Suggested order of work

Context & scope

Repo: ~/claude-code/kdx-hotline · Rust workspace, 7 crates · Server binary: crates/kdxd · Desktop client: apps/kdx-client (Tauri v2, vanilla JS)

All features are shipped and tested (237 tests, 0 TODOs). This session is purely about making both products distributable: clean metadata, a real icon set, bundle config, an example server config, and a tightened README. No new features, no refactoring.

Two products to package:

kdxd daemon

The server binary. Distributed as a compiled executable. SysOps install it on a machine, point it at a TLS cert, run kdxd useradd, start it. Config via kdxd.toml. Traditional port 10700.

KDX desktop app

The Tauri v2 desktop client. Targets macOS first (.app + .dmg), with Windows and Linux as stretch goals. Needs a proper icon set, bundle metadata, and entitlements.

Current state

kdxd — Cargo.toml

namekdxd ✓
version0.1.0 (workspace) ✓
licenseMIT (workspace) ✓
description"KDX server daemon — early-2000s Hotline-style chat and file sharing over TLS 1.3" ✓
authorstheusual ✓
keywordshotline, chat, file-sharing, server, tls ✓
categoriesnetwork-programming, command-line-utilities ✓
readme../../README.md ✓
example configkdxd.example.toml ✓
service filessystemd + launchd ✓

KDX.app — tauri.conf.json

productNameKDX ✓
version0.1.0 ✓
identifiernet.kdx.hotline.client ✓
targetsapp, dmg ✓
icon setfull set (icns, ico, pngs) ✓
shortDescription"Hotline-style chat and file sharing" ✓
copyright© 2024–2026 theusual ✓
categorySocialNetworking ✓
macOS min version10.15 ✓
entitlementsentitlements.plist ✓

README.md

project descriptiongood ✓
workspace overviewgood ✓
build & test instructionsgood ✓
test count243 ✓ (was stale at "~110")
"not yet implemented" sectionreplaced with Status section ✓
config referencepoints to kdxd.example.toml ✓
packaging sectionmacOS stub present ✓ (needs flesh-out)

Open questions — decide before starting

Icon source The current icons/icon.png is a placeholder. Does a real icon design exist, or does one need to be created? cargo tauri icon <source.png> generates the full set (32×32 through 512×512, .icns, .ico) from one 1024×1024 source. The source must be provided before the icon step can run.
App Store category Tauri accepts a macOS app category string. Closest fits: public.app-category.social-networking, public.app-category.utilities, or public.app-category.productivity. Pick one — it affects App Store placement if submitted.
Resolved: SocialNetworking (chat app).
macOS minimum version Tauri v2 supports macOS 10.13+. rustls requires 10.13+. Reasonable targets: 10.15 (Catalina, 2019) or 11.0 (Big Sur, 2020). Most users are 12+; 10.15 is the broadest reasonable floor.
Resolved: 10.15.
Target platforms macOS is confirmed (app + dmg). Windows (NSIS installer) and Linux (AppImage, .deb) are possible with Tauri but each needs its own bundle config block and an OS-specific CI runner. In scope for this session or deferred?
Server distribution format Options: (a) GitHub release pre-built binary only, (b) Homebrew tap formula, (c) Docker image, (d) systemd/launchd service files bundled alongside the binary. Minimum is (a); (b) is the most SysOp-friendly for macOS.
Resolved: (a) GitHub release artifacts per OS (zip + service files), built by the CI matrix; (d) service files ship inside each zip.
Copyright holder / year Tauri bundles a copyright string. Suggest: © 2024–2026 theusual. Confirm the name/entity before writing it into config.
Resolved: © 2024–2026 theusual.

Server — kdxd

1. Cargo.toml metadata done

Add to crates/kdxd/Cargo.toml

The workspace already has version, edition, license, repository. Add the crate-specific fields:

# add inside [package]
description = "KDX server daemon — early-2000s Hotline-style chat and file sharing over TLS 1.3"
authors     = ["theusual"]
keywords    = ["hotline", "chat", "file-sharing", "server", "tls"]
categories  = ["network-programming", "command-line-utilities"]
readme      = "../../README.md"

2. Example config file done

Create crates/kdxd/kdxd.example.toml

Mirrors every field in src/config.rs with its default value and a comment explaining each. SysOps copy it to kdxd.toml and uncomment what they need. Current fields to document:

# KDX server configuration. Copy to kdxd.toml and pass as the first argument:
#   kdxd kdxd.toml

# Address and port to listen on. Traditional KDX port is 10700.
bind                    = "0.0.0.0:10700"

# SQLite database path. Created automatically on first run.
database                = "kdx.db"

# Directory where uploaded file bytes are stored. Created automatically.
files_root              = "files"

# Session idle timeout in seconds before the server closes the connection.
session_ttl_secs        = 1800

# Per-transfer throttles in bytes/sec. 0 = unlimited.
max_upload_bytes_per_sec   = 0
max_download_bytes_per_sec = 0

# Tracker directory display name and description.
server_name        = "KDX Server"
server_description = ""
max_users          = 256

# TLS certificate and private key (PEM). When omitted, a self-signed
# dev certificate is generated at startup — fine for local testing only.
# [tls]
# cert_pem = "/etc/kdx/cert.pem"
# key_pem  = "/etc/kdx/key.pem"

3. Service files done

Create crates/kdxd/kdxd.service (systemd, Linux) stretch

Standard [Unit]/[Service]/[Install] unit. Runs as a dedicated kdx system user. Restarts on failure.

Create crates/kdxd/net.kdx.hotline.server.plist (launchd, macOS) stretch

Standard launchd plist for /Library/LaunchDaemons/. Runs at boot under a dedicated user.

Client — KDX.app

1. Icon set done

Generate via cargo tauri icon

Tauri CLI generates all required sizes from one 1024×1024 PNG source. Produces: 32x32.png, 128x128.png, 128x128@2x.png, icon.icns (macOS), icon.ico (Windows), and square PNGs for Linux. Destination: apps/kdx-client/src-tauri/icons/.

cargo tauri icon apps/kdx-client/src-tauri/icons/source-1024.png

After running, update tauri.conf.json bundle.icon to the full list:

"icon": [
  "icons/32x32.png",
  "icons/128x128.png",
  "icons/128x128@2x.png",
  "icons/icon.icns",
  "icons/icon.ico"
]

2. Bundle metadata done

Add to apps/kdx-client/src-tauri/tauri.conf.json → bundle

Fields that are currently missing from the "bundle" block:

"shortDescription": "Hotline-style chat and file sharing",
"longDescription":  "KDX is a modern rebuild of the early-2000s Hotline client — private servers, chat rooms, file browsing, and resumable transfers, all over TLS 1.3 with challenge-response auth.",
"copyright":        "© 2024–2026 theusual",
"category":         "SocialNetworking",  // or "Utilities" — open question
"macOS": {
  "minimumSystemVersion": "10.15",
  "entitlements":         "entitlements.plist"
}

3. Entitlements plist done

Create apps/kdx-client/src-tauri/entitlements.plist

Required for macOS app sandboxing and network access. KDX needs outbound TCP connections only.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>com.apple.security.network.client</key><true/>
  <key>com.apple.security.files.user-selected.read-write</key><true/>
</dict></plist>

files.user-selected.read-write is needed for the file-open/save dialogs used in upload and download. Add other entitlements only if sandboxing requires it at build time.

4. Windows / Linux bundle config done (CI)

Windows (NSIS installer) stretch

Add "windows": { "nsis": { "displayLanguageSelector": false } } inside bundle. Requires a Windows runner to build; cross-compilation from macOS is not supported by Tauri.

Linux (AppImage + deb) stretch

Add "linux": { "deb": { "depends": [] } }. Requires a Linux runner. Add "appimage" and "deb" to targets.

README.md

Fix stale test count done

Line says ~110 tests. Current count is 237. Update inline.

Remove "Not yet implemented" section done

Lists tracker and in-app account management as missing. Both shipped (commits b4cef10, da0a43a). Delete the section entirely or replace it with a brief "what's missing" note limited to identity fields (display name / description not yet server-enforced).

Replace hand-wavy config note with pointer to example file done

Current text: "Pass a TOML config path to either to override — see Config in crates/kdxd/src/config.rs for the fields." After creating kdxd.example.toml, update to: "Copy crates/kdxd/kdxd.example.toml to kdxd.toml and edit as needed."

Expand "Package the client" section done

Current section only covers macOS. After the bundle config work, update it with the full build command and note which platforms are supported. Mention that cargo tauri icon only needs to be run once.

Suggested order of work

1. Decide the open questions

Icon, category, copyright holder, macOS min version, target platforms, server distribution format. These gate everything else.

2. Get or create the icon source

1024×1024 PNG. If designing from scratch, do it before touching any configs so the icon step isn't blocked.

3. Run cargo tauri icon

Generates the full icon set in icons/. One command, no manual resizing.

4. Update tauri.conf.json

Add shortDescription, longDescription, copyright, category, macOS block, updated icon list.

5. Create entitlements.plist

Two entitlements: network.client + files.user-selected.read-write.

6. Update crates/kdxd/Cargo.toml

Add description, authors, keywords, categories, readme.

7. Create crates/kdxd/kdxd.example.toml

All config fields documented with defaults and comments.

8. Fix README.md

Test count, remove stale section, update config note, expand packaging section.

9. Smoke-test the build

Run cargo tauri build from apps/kdx-client/src-tauri. Verify the .app launches, the DMG mounts, the app icon appears correctly in Finder and the Dock. Check cargo build -p kdxd --release still compiles clean.

10. Service files (if in scope)

systemd unit (kdxd.service) and/or launchd plist. Drop them in crates/kdxd/ with install instructions appended to the README.