English | 简体中文
Building an OctoSense app? You do not need this repository: it renders OctoScript to OpenHarmony ArkUI for native OpenHarmony apps, a separate path from OctoSense script apps and the App Hub. Start from the OctoSense organization profile's reading order: OctoScript-App-Design-Flow
AGENTS.md→flows/README.md→docs/QUICKSTART.md.
native-runtime.lock.json selects one
Octoscript-Makepad
release. Its runtime.json owns the exact Makepad and Octoscript revisions,
shared with the OctoSense shells, the App Hub's card-host, Mail and the other
OctoSense applications.
Before building, run python3 tools/setup-native.py (Python 3.9+). The framework
repositories are siblings of this app: ../octoscript-makepad, ../makepad
and ../octoscript. Local changes are preserved; --update only updates clean
checkouts. CI verifies the selected release and rejects duplicate Makepad sources.
Use python3 tools/setup-native.py --check --cargo-manifest Cargo.toml
to check the local dependency graph. Existing platform rendering backends remain
part of their applications; the framework controls the shared VM and UI sources.
Runtime lock (fixed #67, 2026-09-26): the lock and the matching
Cargo revs now select Octoscript-Makepad 6cf2d90a, a commit on its main
(makepad d653bc44, Octoscript 2e37d9e6: the same framework sources as the
other OctoSense consumers). The previous pin, b1596d9c, was the pre-history-rewrite
hash of main's f4acc6c; nothing was lost in the move.
Build a HarmonyOS app with a web frontend and Rust for everything else.
A page calls octoscript.invoke('device.info') and gets an answer from Rust. Around
that page, real native ArkUI widgets — built from Rust too, not from ArkTS. The
shape is Tauri's; the widget layer is something Tauri does not have.
const info = await octoscript.invoke('device.info')
// { productModel: "SUP-AL90", osFullName: "OpenHarmony-6.1.1.120", ... }The octoscript-oh command is built from this repository. In an Octoscript-OH
checkout, after python3 tools/setup-native.py has placed the sibling framework
repositories (Cargo needs them to resolve the workspace):
cargo install --path tools/octoscript-oh-cli # rust-toolchain.toml selects nightlyThen:
octoscript-oh new my-app
cd my-app
npm install && npm run build
./build.sh # builds, installs and launches on a connected phone./build.sh needs an Octoscript-OH checkout to build against — clone one beside your
project or set OCTOSCRIPT_OH. See docs/building-an-app.md.
While developing, skip the rebuild entirely:
octoscript-oh dev # tunnels the phone to your machine over USB
npm run dev
OCTOSCRIPT_DEV_SERVER=http://127.0.0.1:5173 ./build.shFrontend edits now reload on the device in about a second. Rust edits still need a rebuild.
| Building an app | the template, the dev loop, octoscript.toml, the build |
| Plugins | your own native tools, sync and async |
| Capabilities | what a page may do, and how that is enforced |
| Releasing | signing, AGC, and what is not done yet |
Every page is also in Chinese: each docs/*.md has a docs/*.zh-CN.md beside it.
49 built-in tools, a few of them internal: device, display, battery, sensors, haptics, location, radio, Wi-Fi, network, filesystem, picker, clipboard, HUKS keystore, SQLite, Bluetooth, camera, audio, video, crypto, and the Octoscript VM. Your own tools go beside them — see docs/plugins.md.
A page gets only what its surface was granted. Trust is not one bit: each surface declares which tools, which directories and which hosts it may reach. See docs/capabilities.md.
crates/octoscript-oh-arkui/ the renderer rlib
crates/octoscript-oh-core/ registry, Args, Responder rlib
crates/octoscript-oh-webview/ the bridge and the capabilities cdylib -> liboctoscript_oh.so
crates/octoscript-oh-plugin-demo/ an example plugin rlib
examples/<app>/ one sample app per folder
tools/octoscript-oh-cli/ host-side tooling bin: octoscript-oh
deveco/ the ArkTS shell
The dependencies run one way, and that is what makes plugins possible.
octoscript-oh-arkui does not know webviews exist. octoscript-oh-core does not know
the bridge exists — which is why a plugin can depend on it without depending on
the app. octoscript-oh is a cdylib, a final artifact nothing links against, so it
is the crate that decides which plugins are in a build.
One .so comes out, because ArkTS loads exactly one.
Renders a UI tree to native ArkUI widgets from Rust. ArkTS hands over one
NodeContent at startup; after that every widget is created, configured, laid
out and event-wired by native code, with no per-widget and no per-frame ArkTS
call.
Contains the ArkUI NDK binding, the Octoscript DSL walker, the widget builders, four ported reference apps (WeChat, Taobao, TikTok, Wonderous) and the Rust-vs-ArkTS benchmark they exist to run.
assets/catalog.octoscript is a Material component catalog written in the DSL and
rendered to native ArkUI — an index plus 28 screens, no makepad, no ArkTS
widgets. All 28 are photographed in catalog-screens.png, and every one has been
looked at on a device rather than merely being reachable.
Two were wrong when that check was first run, and both are fixed: Badges drew
unlabelled pills under a caption promising numbers, and Text picker drew empty
rows because nothing set its range. CATALOG_WALK_MS in Index.ets re-runs the
sweep that found them.
| free of it | the widget tree, all the capabilities, the XComponent surface carrying camera and video |
| structurally cannot be | the Web component — there is no ARKUI_NODE_WEB |
| only for want of an NDK | file picker, clipboard, runtime permissions, BLE scan |
OH_NativeArkWeb_RunJavaScript resolves on device but the controller's web tag
never binds, so bridge traffic still relays through ArkTS. Measured, not
assumed — see crates/octoscript-oh-webview/src/arkweb.rs.
This runs on real hardware, and everything documented here was verified on a HarmonyOS 6.1 device rather than inferred. What is not done:
- Signing for release is not wired.
sign-hap.shhas a headless AGC path andoctoscript.tomlhas a[signing]section; nothing connects them yet. See docs/releasing.md. - The shell is a checkout, not a dependency. A project builds against an Octoscript-OH clone, and linking your own plugin is two manual edits in it.
- No multi-window, updater or tray. OHOS equivalents are unexplored rather than planned.
cargo testcannot run here. The crates build only foraarch64-unknown-linux-ohos, the host cannot exec that, and the device refuses under SELinux. The checks that matter run at startup instead and log their result — search hilog forselftest, and look immediately: hilog fills with Chromium output within about a minute and evicts them.