🛡️ Be aware: Foundation will NEVER ask for your seed words, device PIN, or call you unexpectedly. If anyone does, it's a scam.



🚧 The Passport Prime SDK is in public beta. Got an idea, or want a dev unit to play with? We'd love to hear from you, hello@foundation.xyz .

What is an app on KeyOS?

An app is a Rust binary crate that runs as an isolated process under the Xous microkernel. Each app gets its own address space, its own storage scope, and its own declared permissions, all enforced by the kernel. There is no runtime escalation path.

Apps compile to the armv7a-unknown-xous-elf target, are signed with cosign2, and are installed under apps/<app-name>/ on the device.

Project layout

my-app/
├── app-config.toml              # app identity, publisher, permissions, signing
├── Cargo.toml
├── build.rs                     # Slint code generation (router, exports, i18n)
├── src/
│   └── main.rs                  # entry point
├── ui/
│   ├── app.slint                # top-level UI component
│   └── pages/                   # per-page components (multi-page-app template)
├── resources/
│   └── icon.svg                 # launcher icon
└── i18n/
    └── en.json                  # translation strings

foundation new my-app scaffolds this layout for you. Two templates ship with the SDK:

  • default-app, single-page starter
  • multi-page-app, router-based multi-screen starter

app-config.toml

This is the source of truth for your app's identity, publisher metadata, required permissions, and signing configuration. Every field maps one-to-one onto an internal AppConfig struct, no hidden defaults.

app-name = "my-app"
friendly-app-name = "My App"
launcher-app-name = "My App"
description = "Example application"
icon = "resources/icon.svg"
app-id = "0x00112233445566778899aabbccddeeff"
version = "0.1.0"
min-keyos-version = "1.0.0"
signing-identity = "Example Company"
cosign2-config = "~/.foundation/signing/my-app/cosign2.toml"

[publisher]
name = "Example Company"
contact-email = "support@example.com"
support-url = "https://example.com/support"

[permissions]
"os/settings" = ["GetDeviceName"]

Field reference

FieldRequiredNotes
app-nameCargo package name and build output directory name
friendly-app-nameDisplay name
launcher-app-name,Falls back to friendly-app-name
descriptionOne-line description
iconPath relative to the project root; validated at build time
app-id0x-prefixed even-length hex; must be unique on the device
versionSemver
min-keyos-versionMinimum KeyOS version your app requires
signing-identity,Selects an identity under ~/.foundation/signing/<name>/
cosign2-config,Explicit path to a cosign2.toml; overrides identity resolution
[publisher]name, contact-email, support-url
[permissions]Per-service entries: "os/<service>" = ["MethodA", "MethodB"]

The UI: Slint with a curated component library

KeyOS apps use Slint for UI. The SDK exposes a stable @ui/... import surface, a curated library of Foundation-designed components, theme tokens, fonts, and icons. Your app imports from @ui and inherits a polished, on-brand starting point that you're free to fully restyle.

A minimal ui/app.slint:

import { BaseWindow } from "@ui/widgets.slint";
import { Button } from "@ui/widgets.slint";

export component AppWindow inherits BaseWindow {
    Button {
        text: "Hello, Passport Prime";
        clicked => { debug("button pressed"); }
    }
}

Components available from @ui/...:

  • Form controls, Input, Checkbox, RadioButton, Slider, Dropdown, Switch, Pagination, SegmentedSelector
  • Navigation, Drawer, Dialog, ModalWindow, PopupMenu
  • Display, Card, Chip, Badge, Button, IconButton, Progress, QR code renderer
  • Specialized, AuthWidget, CryptoFiatField, SeedWords, PinEntry, SlideToButton, FileList
  • Theming, ColorPicker, CircularProgress, Shimmer, full design tokens

Live-preview any .slint file with foundation preview ui/app.slint.

A minimal src/main.rs

The app! macro from slint_keyos_platform wires your top-level AppWindow into the KeyOS runtime:

// SPDX-License-Identifier: Apache-2.0

use slint_keyos_platform::app;

app!("My App");

fn app_main(_cx: AppContext, ui: AppWindow) {
    log_server::init_wait(env!("CARGO_CRATE_NAME")).unwrap();
    log::set_max_level(log::LevelFilter::Info);
    log::info!("My App starting");

    // The Slint event loop runs automatically inside app!()
    // Wire up UI callbacks, spawn tasks, subscribe to IPC events here.
}

Build, simulate, preview

From inside an SDK shell (foundation develop):

foundation new my-app              # scaffold from template
cd my-app
foundation sim                     # hosted simulator (debug)
foundation preview ui/app.slint    # live Slint preview
foundation build                   # release-quality signed hardware build
foundation sideload                # build + upload to Passport Prime + launch

See the CLI Reference for every flag.

Signing

Every app on Passport Prime is signed. foundation build signs app.elf in place with cosign2 using a secp256k1 key.

One-time identity setup:

foundation cert gen "My Company"

This writes four files to ~/.foundation/signing/My Company/:

  • private.pem, secp256k1 private key (keep secret)
  • public.pub, compressed public key hex
  • certificate.crt, self-signed X.509 code-signing certificate
  • cosign2.toml, the config foundation build consumes

Identity resolution order at build time:

  1. cosign2-config in app-config.toml (explicit path)
  2. signing-identity in app-config.toml (name under ~/.foundation/signing/)
  3. An identity whose name matches [publisher].name
  4. The only configured identity, if exactly one exists
  5. Interactive prompt (errors in non-interactive contexts)

Passport Prime's app launcher verifies the signature against the embedded certificate chain before starting your app. Tampered or unsigned binaries are refused.

Registering your developer certificate on Passport Prime

🚧 Coming soon. The flow for installing a developer's public key / X.509 certificate onto Passport Prime (so sideloaded apps built under your identity are trusted) is still being designed. Expected to live under the Apps section in Settings. Watch this space, or email hello@foundation.xyz if you're an early-access partner and need the current interim flow.

Toolchain

ComponentDetail
Rust toolchainNightly, pinned by the SDK
Target triplearmv7a-unknown-xous-elf
Build flagsRUSTFLAGS="--cfg keyos -C relocation-model=pic -C link-arg=-pie" for hardware, --cfg keyos for simulator
Signingcosign2 (secp256k1 + X.509)
Build orchestrationcargo + foundation CLI (cargo xtask for SDK maintainers)
EnvironmentNix flake (foundation develop enters it)

You don't install Rust or manage the cross-compiler manually, foundation develop hands you a shell with everything already in place.

Next