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
16 changes: 8 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,19 @@ jobs:
include:
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
artifact: webmux-node-linux-x64
artifact: offdesk-node-linux-x64
use-cross: true
- target: aarch64-unknown-linux-musl
os: ubuntu-latest
artifact: webmux-node-linux-arm64
artifact: offdesk-node-linux-arm64
use-cross: true
- target: x86_64-apple-darwin
os: macos-latest
artifact: webmux-node-darwin-x64
artifact: offdesk-node-darwin-x64
use-cross: false
- target: aarch64-apple-darwin
os: macos-latest
artifact: webmux-node-darwin-arm64
artifact: offdesk-node-darwin-arm64
use-cross: false

runs-on: ${{ matrix.os }}
Expand All @@ -74,16 +74,16 @@ jobs:
if: matrix.use-cross
uses: taiki-e/install-action@cross

- name: Build webmux-node
- name: Build offdesk-node
run: |
if [ "${{ matrix.use-cross }}" = "true" ]; then
cross build --release --bin webmux-node --target ${{ matrix.target }}
cross build --release --bin offdesk-node --target ${{ matrix.target }}
else
cargo build --release --bin webmux-node --target ${{ matrix.target }}
cargo build --release --bin offdesk-node --target ${{ matrix.target }}
fi

- name: Rename binary
run: cp target/${{ matrix.target }}/release/webmux-node ${{ matrix.artifact }}
run: cp target/${{ matrix.target }}/release/offdesk-node ${{ matrix.artifact }}

- name: Upload to Release
if: startsWith(github.ref, 'refs/tags/')
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:

- run: pnpm install --frozen-lockfile

- run: pnpm --filter @webmux/shared build
- run: pnpm --filter @offdesk/shared build

- run: cd packages/app && npx expo export --platform web

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ concurrency:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/webmux-server
IMAGE_NAME: ${{ github.repository_owner }}/offdesk-hub

jobs:
publish:
Expand All @@ -35,7 +35,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Smoke-test container runtime
run: ./scripts/verify-container-runtime.sh webmux-runtime-smoke-ci
run: ./scripts/verify-container-runtime.sh offdesk-runtime-smoke-ci

- id: meta
uses: docker/metadata-action@v6
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/mobile-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ on:
workflow_dispatch:
inputs:
hub_url:
description: "WEBMUX_MOBILE_HUB_URL baked into the build"
default: "https://webmux.nas.chareice.site"
description: "OFFDESK_MOBILE_HUB_URL baked into the build"
default: "https://offdesk.nas.chareice.site"
required: false

permissions:
Expand All @@ -18,7 +18,7 @@ jobs:
build-apk:
runs-on: ubuntu-22.04
env:
WEBMUX_MOBILE_HUB_URL: ${{ github.event.inputs.hub_url || 'https://webmux.nas.chareice.site' }}
OFFDESK_MOBILE_HUB_URL: ${{ github.event.inputs.hub_url || 'https://offdesk.nas.chareice.site' }}

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -66,10 +66,10 @@ jobs:
run: pnpm install --frozen-lockfile=false

- name: Build shared package
run: pnpm --filter @webmux/shared build
run: pnpm --filter @offdesk/shared build

- name: Build web bundle (loaded as launch shell, replaced at runtime)
run: pnpm --filter @webmux/app build
run: pnpm --filter @offdesk/app build

- name: Set release version from tag
id: version
Expand Down Expand Up @@ -201,7 +201,7 @@ jobs:
base=$(basename "$src" .apk)
abi=$(echo "$base" | sed -E 's/^app-//; s/-release.*$//')
[ -z "$abi" ] && abi="universal"
cp "$src" "artifacts/webmux-${version}-${abi}.apk"
cp "$src" "artifacts/offdesk-${version}-${abi}.apk"
done
ls -lh artifacts/
{
Expand All @@ -213,7 +213,7 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: webmux-android-apks
name: offdesk-android-apks
path: artifacts/*.apk

- name: Create or update release
Expand All @@ -225,7 +225,7 @@ jobs:
if ! gh release view "$tag" >/dev/null 2>&1; then
gh release create "$tag" \
--title "Mobile ${tag}" \
--notes "Tauri-based Android client. Sideload via 'install from unknown sources'. Pick the **arm64-v8a** APK on modern phones; the **universal** APK works on any architecture but is larger. The app loads the configured webmux URL on launch, so all UI changes ship automatically without a new APK."
--notes "Tauri-based Android client. Sideload via 'install from unknown sources'. Pick the **arm64-v8a** APK on modern phones; the **universal** APK works on any architecture but is larger. The app loads the configured offdesk URL on launch, so all UI changes ship automatically without a new APK."
fi
for apk in artifacts/*.apk; do
gh release upload "$tag" "$apk" --clobber
Expand Down
71 changes: 71 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Contributing

## Layout

- `crates/hub` — the hub. Axum + WebSocket + SQLite. Serves the web app as an
SPA, brokers terminal I/O between clients and machines, owns auth
(GitHub/Google OAuth + `odk_` API tokens) and the per-machine control lease.
Binary: `offdesk-hub`.
- `crates/machine` — the machine agent. Registers with a hub, hosts terminals
as tmux sessions (one `tmux attach` per client, so views and scroll position
are independent), reports stats. Binary: `offdesk-node`.
- `crates/cli` — the CLI. Remote `tmux send-keys` + `capture-pane` through the
hub. Binary: `offdesk`.
- `crates/protocol` — wire types shared by all three, plus the config-directory
helper.
- `packages/app` — the only frontend. Expo Router + React Native Web +
xterm.js 6. Built with `expo export --platform web`, served by the hub,
wrapped by Tauri for desktop (`packages/desktop`) and Android.
- `packages/shared` — TypeScript wire contracts.

The Cargo workspace is `crates/*`. `packages/desktop/src-tauri` is excluded
from it and builds on its own.

## Running it locally

```bash
# hub — serves the API and the exported web build on :4317
OFFDESK_DEV_MODE=true cargo run -p offdesk-hub

# machine agent — registers on first run
offdesk-node register --hub-url http://127.0.0.1:4317 --token <register-token>
offdesk-node start

# web app — Expo dev server; proxy.mjs forwards /api and /ws to the hub
pnpm install && pnpm --filter app dev:web
node proxy.mjs
```

`OFFDESK_DEV_MODE=true` enables `GET /api/auth/dev`, a token-less local login.
It returns 404 otherwise.

## Tests

```bash
cargo test --workspace # Rust
pnpm test # vitest
pnpm typecheck # tsc -b
pnpm e2e:test # Playwright, in containers
```

E2E rules live in `AGENTS.md`. The short version: browser verification runs
Playwright and Chromium inside the `runner` container, via `pnpm e2e:test`
locally or `pnpm e2e:ci` in automation. Do not run `playwright test` directly
for routine checks. `pnpm e2e:test:debug-host` uses a host browser and is for
debugging container startup only — say so explicitly if you use it.

## Design records

- `DESIGN.md` — the design system the app actually ships.
- `docs/plans/`, `docs/superpowers/` — dated design specs and reports. They are
a record of what was decided when, so they still use the pre-rename names
(`webmux`, `tc-hub`, `WEBMUX_*`, `wmx_`). Read `docs/facts.md` for the
current names.
- `docs/facts.md` — verified facts about the shipping system, each citing the
file it came from. README and site copy may only assert things on that list.
- `docs/deployment/runbook.md` — operating the production deployment.

## Conventions

- Every factual claim in user-facing docs must be backed by code in this repo.
- Product name is `offdesk`, lowercase, always.
181 changes: 91 additions & 90 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading