Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
895b4d1
Add runtime identity and connector contracts
yannelli Oct 9, 2026
a4dff5d
Start listening before the first watcher scan
yannelli Oct 9, 2026
9faebfa
Show runtime stderr in desktop startup errors
yannelli Oct 9, 2026
f3a4ce4
Serve runtime identity and bind a random port
yannelli Oct 9, 2026
7903d66
Add the Runtime page and one-tap cloud button on web
yannelli Oct 9, 2026
1bd7db6
Add keep-alive lease and WebSocket ping
yannelli Oct 9, 2026
21a5aa0
Add the Runtime page to the desktop app
yannelli Oct 9, 2026
0ea2976
Browse _oxbit._tcp runtimes with NWBrowser
yannelli Oct 9, 2026
a3134dc
Key runtime credentials by runtime id
yannelli Oct 9, 2026
0ebf506
Pass keep-alive to SSH-started runtimes and reattach on resume
yannelli Oct 9, 2026
e7dfa96
Expose runtime discovery, runtime ids, and keep-alive in host-ios
yannelli Oct 9, 2026
f167013
Document runtime discovery and SSH runtime keep-alive on iOS
yannelli Oct 9, 2026
202fa99
Add the linux-arm64 remote runtime and accept arm64 SSH hosts
yannelli Oct 9, 2026
36287fd
Publish Linux desktop packages for x64 and arm64
yannelli Oct 9, 2026
8485486
Add LAN mode with Bonjour advertising
yannelli Oct 9, 2026
acafa50
Document runtime identity, LAN mode, and keep-alive
yannelli Oct 9, 2026
a6cf861
Await terminal creation in the shell startup test
yannelli Oct 9, 2026
4d4b377
Add the Runtime page to the iOS app
yannelli Oct 9, 2026
976ef9f
Test the Runtime page and one-tap on web, and fix its actions
yannelli Oct 9, 2026
e0ca4f8
Test the iOS Runtime page, discovery, and one-tap in the harness
yannelli Oct 9, 2026
eb828e7
Document the Runtime page, runtime settings, and the random port
yannelli Oct 9, 2026
8dbf4e6
Regenerate the theme coverage inventory for the Runtime page styles
yannelli Oct 9, 2026
e919e1d
Expect the Runtime page from the workspace dialog's connect action
yannelli Oct 9, 2026
7c67dca
Test the SSH runtime keep-alive lease live
yannelli Oct 9, 2026
de80cca
Install managed language servers on linux-arm64
yannelli Oct 9, 2026
5c10206
Pin tar 7.5.22 and reject unsafe managed archive entries without an u…
yannelli Oct 9, 2026
a9b0c48
Upgrade markdown-it to 14.3.2 and DOMPurify to 3.4.16
yannelli Oct 9, 2026
06c09ef
Override fast-uri to 3.1.8
yannelli Oct 9, 2026
489f8fc
Upgrade vitest to 4.1.11 and patch dev-tool transitive dependencies
yannelli Oct 9, 2026
83313e0
Update desktop rustls to 0.23.45
yannelli Oct 9, 2026
68c279c
Upgrade managed bash-language-server to 5.8.1 and override vulnerable…
yannelli Oct 9, 2026
214dcea
Document dependency audit commands, fixes, and accepted advisories
yannelli Oct 9, 2026
e7ff091
Regenerate the iOS Info.plist with the Bonjour service and local netw…
yannelli Oct 9, 2026
6fa2f68
Merge p1/linux-arm64-builds
yannelli Oct 9, 2026
62b22f8
Merge sec/dependency-audit
yannelli Oct 9, 2026
0585456
Drop diagnostics that arrive after a file's language server is turned…
yannelli Oct 9, 2026
4a8ff8b
Merge p1/runtime-page
yannelli Oct 9, 2026
405a9b7
Add TestFlight notes for 0.5.0
yannelli Oct 9, 2026
c159d7a
Build test archives synchronously and format the lease test
yannelli Oct 9, 2026
ab18608
Check SSH owner rejection with a different workspace key
yannelli Oct 9, 2026
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
8 changes: 8 additions & 0 deletions .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ jobs:
platform: darwin-arm64
- runner: ubuntu-24.04
platform: linux-x64
ssh-platform: linux/amd64
- runner: ubuntu-24.04-arm
platform: linux-arm64
ssh-platform: linux/arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
Expand All @@ -38,6 +42,8 @@ jobs:
if-no-files-found: error
- name: Real SSH acceptance on an offline host
if: runner.os == 'Linux'
env:
OXBIT_SSH_TEST_PLATFORM: ${{ matrix.ssh-platform }}
run: bun run remote:test
build:
needs: remote-runtime
Expand All @@ -51,6 +57,8 @@ jobs:
platform: darwin-arm64
- runner: ubuntu-24.04
platform: linux-x64
- runner: ubuntu-24.04-arm
platform: linux-arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/language-servers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
runner: [macos-26, ubuntu-24.04]
runner: [macos-26, ubuntu-24.04, ubuntu-24.04-arm]
runs-on: ${{ matrix.runner }}
env:
OXBIT_LSP_REPORT: evidence/language-milestone1/real-servers.json
Expand Down
63 changes: 62 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
platform: darwin-arm64
- runner: ubuntu-24.04
platform: linux-x64
- runner: ubuntu-24.04-arm
platform: linux-arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -103,6 +105,65 @@ jobs:
name: remote-manifest
path: release-files/remote-runtime-manifest.json
if-no-files-found: error
# Linux arm64 is published when it builds; its failure does not block the release.
linux:
needs: remote-runtime
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
platform: linux-x64
- runner: ubuntu-24.04-arm
platform: linux-arm64
runs-on: ${{ matrix.runner }}
continue-on-error: ${{ matrix.platform == 'linux-arm64' }}
timeout-minutes: 120
env:
OXBIT_REMOTE_PAYLOADS: ${{ github.workspace }}/.desktop-cache/remote-payloads
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "24.20.0"
- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.4.2"
- name: Linux native dependencies (Ubuntu 24.04 minimum)
run: |
sudo apt-get update
sudo apt-get install -y build-essential python3 pkg-config libssl-dev libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev patchelf libxdo-dev libfuse2t64 xdg-utils xvfb dbus-x11
- run: rustup toolchain install 1.97.1 --profile minimal
- run: bun install --frozen-lockfile
- run: bun run build
- uses: actions/download-artifact@v4
with:
pattern: remote-runtime-*
path: .desktop-cache/remote-payloads
- name: Build and sign the updater AppImage and .deb
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
OXBIT_UPDATER_PUBLIC_KEY: ${{ vars.OXBIT_UPDATER_PUBLIC_KEY }}
run: bun run desktop:release
- name: Installed package smoke checks
run: |
bundle=apps/desktop/src-tauri/target/release/bundle
sudo apt-get install -y ./"$bundle"/deb/*.deb
xvfb-run -a dbus-run-session -- bun run desktop:test:installed -- /usr/bin/oxbit-desktop
sudo apt-get remove -y "$(dpkg-deb --field "$bundle"/deb/*.deb Package)"
APPIMAGE_EXTRACT_AND_RUN=1 xvfb-run -a dbus-run-session -- node scripts/desktop/installed-smoke.mjs "$(realpath "$bundle"/appimage/*.AppImage)"
- name: Collect release files
run: |
bundle=apps/desktop/src-tauri/target/release/bundle
mkdir -p release-files
cp "$bundle"/deb/*.deb "$bundle"/appimage/*.AppImage "$bundle"/appimage/*.AppImage.sig release-files/
ls -l release-files
- uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.platform }}
path: release-files/
if-no-files-found: error
# The pinned manifest records the darwin payload after the macos job signs and repacks it.
ios:
needs: [remote-runtime, macos]
Expand Down Expand Up @@ -181,7 +242,7 @@ jobs:
path: release-files/
if-no-files-found: error
publish:
needs: [macos, ios]
needs: [macos, ios, linux]
if: github.ref_type == 'tag' && github.repository == 'yannelli/oxbit'
runs-on: ubuntu-24.04
permissions:
Expand Down
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,17 @@ See [npm packages](docs/npm.md).
| `oxbit -f` | Keep the runtime attached to the terminal |
| `oxbit --no-open` | Start without opening a browser |
| `oxbit --port 9300` | Choose a port for a new runtime; stop an existing one first |
| `oxbit --lan` | Serve on your network and advertise the runtime to the iOS app |
| `oxbit --keep-alive 1h` | Stop the runtime after an hour with no connected client |
| `oxbit --help` | Show all options |

The first runtime uses port 9277. Later runtimes choose a free port and record it
in `~/.oxbit/workspaces/<id>/daemon.json`. The printed URL includes a pairing code
in its fragment, which the editor consumes and removes from the address bar.
Opening `http://127.0.0.1:9277` without that fragment loads the browser sample
workspace; use **Runtime connection** to pair it with your project.
Each runtime binds a port the operating system assigns, unless `--port` or `PORT`
sets one, and records it in `~/.oxbit/workspaces/<id>/daemon.json`. The printed URL
includes a pairing code in its fragment, which the editor consumes and removes from
the address bar. Opening the runtime URL without that fragment loads the browser
sample workspace; the cloud button in the title bar opens the **Runtime** page,
where you pair the runtime with its printed code. Later, one tap on the cloud button
reconnects to the last runtime.

Without a global install, run `OXBIT_WORKSPACE=/absolute/path bun run start` after
building. See [runtime configuration](docs/runtime.md) for network hosting,
Expand All @@ -62,11 +66,11 @@ allowed origins, and storage.
### Desktop

The Tauri desktop app bundles Node, ripgrep, the terminal addon, and managed
language services. It targets Apple Silicon with macOS 26+ and Ubuntu 24.04+ x64.
language services. It targets Apple Silicon with macOS 26+ and Ubuntu 24.04+ x64 and arm64.
Run `bun run desktop:dev` for development or `bun run desktop:build` for local installers.
Use `oxbit --desktop [path]` to open an installed app.

**Connect over SSH…** opens a remote folder on Linux x64 or macOS Apple Silicon.
**Connect over SSH…** opens a remote folder on Linux x64, Linux arm64, or macOS Apple Silicon.
Oxbit installs its headless runtime through SSH; the remote host does not need
Node or npm for the bundled runtime.

Expand All @@ -82,7 +86,7 @@ GitHub tokens and runtime pairing credentials are stored in Keychain.

Run `bun run ios:dev "Oxbit iPhone"` or `bun run ios:simulator` on macOS with Xcode.
See [iOS setup and runtime connections](docs/ios.md).
The [documentation index](docs/INDEX.md) links native source control, SSH and SFTP, and language-server guides with official API references.
The [documentation index](docs/INDEX.md) links native source control, SSH and SFTP, language-server, runtime discovery and keep-alive guides with official API references.
The [iOS release artwork guide](docs/ios-release-assets.md) covers icon exports,
App Store screenshots, and promo exports with Apple's design and size references.

Expand Down Expand Up @@ -155,7 +159,8 @@ watchers.
| `examples/` | Extension and icon-pack examples |

See [architecture](docs/architecture.md), [feature status](docs/feature-status.md),
[dependencies](docs/dependencies.md), and [design assets](design/README.md).
[dependencies](docs/dependencies.md), [dependency audits](docs/security.md#dependency-audit),
and [design assets](design/README.md).

### Checks

Expand Down
3 changes: 2 additions & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"react": "19.1.0",
"react-dom": "19.1.0",
"@tauri-apps/api": "2.11.1",
"@oxbit/themes": "workspace:*"
"@oxbit/themes": "workspace:*",
"@oxbit/protocol": "workspace:*"
},
"devDependencies": {
"@tauri-apps/cli": "2.11.4",
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src-tauri/Cargo.lock

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

5 changes: 3 additions & 2 deletions apps/desktop/src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ pub async fn desktop_connection(
window: WebviewWindow,
key: String,
restart: Option<bool>,
keep_alive: Option<u64>,
) -> Result<Value, String> {
let project = authorized(&app, &window, &key)?;
tauri::async_runtime::spawn_blocking(move || {
Expand All @@ -313,8 +314,8 @@ pub async fn desktop_connection(
let progress_app = app.clone(); let progress_key = key.clone();
let process = OwnedRuntime::launch(&resource.join("bin/node"), &resource.join("desktop.js"), Launch {
version: 1, r#type: "launch", root: &project.path, data_dir: &data.to_string_lossy(), workspace_key: &key, token: &token,
rg_path: &resource.join("bin/rg").to_string_lossy(), git_path: git.as_deref(), development: cfg!(debug_assertions) && !cfg!(feature = "custom-protocol"),
}, &desktop.environment, move || { let _ = event_app.emit("desktop-runtime-failed", json!({"key":event_key})); }, move |message| { let _ = progress_app.emit("desktop-remote-progress", json!({"key":progress_key,"message":message})); })?;
rg_path: &resource.join("bin/rg").to_string_lossy(), git_path: git.as_deref(), development: cfg!(debug_assertions) && !cfg!(feature = "custom-protocol"), keep_alive,
}, &desktop.environment, move |detail| { let _ = event_app.emit("desktop-runtime-failed", json!({"key":event_key,"detail":detail})); }, move |message| { let _ = progress_app.emit("desktop-remote-progress", json!({"key":progress_key,"message":message})); })?;
// Ownership can change while the runtime starts. Never return credentials to a former owner.
desktop.model.lock().unwrap().authorize(window.label(), &key)?;
let result = json!({"url":format!("http://127.0.0.1:{}", process.port), "token":token, "key":key, "openFile":process.open_file});
Expand Down
Loading
Loading