Questa pagina è stata tradotta automaticamente e può contenere errori. Leggi l'originale in inglese

Native Shell

Costruisci una volta, nativo ovunque

La tua app sta al centro. Ogni arco attorno è una piattaforma.

Scrivi solo TSX e distribuisci client nativi che tengono il passo con Rust. Un'unica codebase gira su 8 piattaforme, ciascuna con la UI e l'interazione native del sistema.

FPS
120
primo frame
~1 ms
piattaforme
8

Un client scritto in TSX, a fianco di Rust

In NSH solo il codice della tua app è JS. Il grafo reattivo, il renderer, il layout e ogni modulo sono Rust. Le app TSX e Rust condividono la stessa pipeline di esecuzione nativa.

120 FPS
22 sparkline live, un order book e un tape che si aggiornano insieme, frame p95 sotto i 4 ms
~0.1 ms
Avvio del motore (75–155 µs)
~1 ms
Primo frame di un'app contatore
~0.12 ms
Un tocco, dall'evento al commit
< 1 KB
Il codice app di un hello world
~1.1 MB
Download di un'app TSX sul web (runtime Wasm)
Piccole app misurate: pochi MB sopra la finestra di sistema nuda
TSXRustFinestra di sistema nuda
Impronta di memoria, macOS~20 MB~19 MB~17 MB
Memoria private dirty, Linux (GTK, GL)~48 MB~44 MB~38 MB
Sopra la finestra di sistema, macOS / Linux+3 / +9 MB+2 / +5 MB
Working set privato, Windows~15 MB~14 MB
Dimensioni su ogni piattaforma: l'hello world di nsh init
Eseguibile TSXPacchetto TSXEseguibile RustPacchetto Rust
macOS (Apple silicon)19.8 MB9.5 MB12.4 MB6.0 MB
Linux (x86_64)25.7 MB11.6 MB16.5 MB7.5 MB
Windows (x86_64)28.6 MB12.4 MB15.0 MB6.7 MB
Web—download di ~1.1 MB——

Build release. Memoria a riposo: footprint di macOS su un Apple M3 (l'app contatore e il template Rust a 1200 × 800; la finestra di sistema contiene una label a 480 × 640); memoria private dirty di Linux su una NVIDIA RTX 3060 Ti (i template TSX e Rust di nsh init e una finestra GTK con una label, tutti a 480 × 640); working set privato di Windows. La misura di ogni piattaforma, con RSS e USS, è nel report. Dimensioni: build release di nsh package, con link-time optimization e simboli rimossi; l'eseguibile TSX contiene il runtime QuickJS, il codice dell'app è sotto 1 KB; il pacchetto è l'.app compresso in zip su macOS, il .tar.gz su Linux e lo .zip su Windows; sul web, ciò che il browser scarica, runtime e app. Il report completo sulle prestazioni

TSX con 0 dipendenze

Un'app è fatta dei file qui sotto. La riga di comando nsh porta con sé il proprio bundler e la propria toolchain, e i moduli che importi sono nativi.

$ nsh init my-app --template ts
$ nsh run my-app --target macos

my-app/
  App.tsx
  nsh.json
  tsconfig.json
  • Un solo eseguibile nsh crea, esegue, testa e impacchetta
  • ~120 ms dal salvataggio di un file alla nuova versione in esecuzione
  • nsh check controlla i tipi con il tsc nativo di TypeScript 7
TSXApp.tsx
import { mount, signal, Text, View } from "nsh";

function App() {
  const count = signal(0);
  return (
    <View class="items-center gap-4">
      <Text>Count: {count()}</Text>
      <View
        class="rounded-lg bg-blue-600 px-5 py-3"
        onPress={() => count.update((n) => n + 1)}
      >
        <Text class="text-white">Tap</Text>
      </View>
    </View>
  );
}
mount(App);

8 piattaforme, ciascuna con i controlli propri del sistema

NSH costruisce ogni UI con ciò che la sua piattaforma ha già. Input di testo, selezione, metodi di input e accessibilità vengono dal sistema, e ciò che una nuova versione dell'OS vi porta arriva all'app insieme.

PiattaformaVisteTestoInput di testoRequisiti
macOSAppKitCoreTextNSTextViewmacOS 14+
LinuxGTK 4PangoGtkTextViewGTK 4.14+
WindowsWin32, Direct2DDirectWriteL'editor di NSH, IMM32Windows 10 1809+
WebHTML, CSSQuello del browser<input>, <textarea>Browser moderni
iOSUIKitCoreTextUITextViewiOS 15+
AndroidViste AndroidStaticLayoutEditTextAPI 28+
TUIratatuiIl font del terminaleTasti Readline, metodi di inputmacOS, Windows, Linux
GPUIGPUIIl sistema di testo di GPUIL'editor di NSHIncorporato nelle app GPUI Kit

Mappe, web view, video e qualsiasi vista nativa registrata dall'host sono una sottovista in più nella stessa gerarchia: si dispongono, vengono ritagliate, scorrono e ricevono i tocchi insieme al resto dell'app. Il backend di ogni piattaforma

Un'app, nella forma propria di ogni dispositivo

Lo stesso codice compilato qui gira due volte, e cambia solo il dispositivo. Con un puntatore è una finestra con le conversazioni a lato; su un telefono i pulsanti e il composer fluttuano in Liquid Glass con la conversazione che scorre sotto; in un terminale si dispone sulla griglia di caratteri. L'app è scritta una sola volta.

DesktopDal vivo: scrivi un messaggio
TelefonoDal vivo: scrivi un messaggio
TerminaleEsplora TUI
+ New chat           │ What makes an NSH app native?
Today                │ A signal holds the count; only the Text that reads it updates   │
What makes an NSH…   │ when you press.                                                 ┃
Plot a week of NSH   │ import { mount, signal, Text, View } from "nsh";                ┃
Signed packages,…    │                                                                 ┃
A sheet with two…    │ const count = signal(0);                                        ┃
Taffy grid vs flex   │ mount(() => (                                                   ┃
                     │   <View onPress={() => count.set(count() + 1)}>                 ┃
                     │     <Text>{count()}</Text>                                      ┃
                     │   </View>                                                       ┃
                     │ ));                                                             ┃
                     │                                   What makes an NSH app native? ┃
                     │ Every element is the platform's own view: UIKit on iOS, Android ┃
                     │ views, AppKit on macOS and GTK 4 on Linux. Your TSX describes   ┃
                     │ them; layout, text and the reactive graph run in Rust.          ┃
                     │                                 And the glass around this chat? ┃
                     │ It's Liquid Glass, one glassEffect style. iOS 26 and macOS 26   ┃
                     │ draw the system's material; elsewhere it blurs what scrolls     ┃
                     │ beneath.                                                        ┃
                     │ • The buttons and the composer float over the thread            ┃
                     │ • Messages pass under them as you scroll                        ┃
                     │ • The same code at every idiom                                  ┃
                     │ ╭───────────────────────────────────────────────────────────────╮
                     │ │ › Ask anything                                                │
                     │ ╰───────────────────────────────────────────────────────────────╯

Desktop e telefono girano dal vivo nel tuo browser sul runtime web di Native Shell. Il terminale è output reale di nsh run --target tui.

Lo stesso motore in Rust, quando vuoi

Rust è un linguaggio di prima classe per app intere: UI, logica e componenti compilano in codice nativo, pronto per logica di business impegnativa. Entrambi usano gli stessi elementi e signal, e le schermate TSX importano i tuoi componenti Rust.

Sviluppare con Rust

Rustsrc/lib.rs
use nsh_core::element::prelude::*;

#[component]
pub fn App() -> impl IntoElement {
    let count = signal(0);
    view()
        .items_center()
        .gap_4()
        .child(text(move || format!("Count: {}", count.get())))
        .child(
            view()
                .rounded_lg().bg(rgb(0x2563eb)).px_5().py_3()
                .on_press(move || count.update(|n| *n += 1))
                .child(text("Tap").text_color(white())),
        )
}

Vengono toccate solo le viste che sono cambiate

Ogni elemento è una vista che la piattaforma mantiene. Una modifica esegue solo le espressioni che leggono il signal cambiato, in un unico batch per frame. Il thread principale non attende mai JS e le animazioni native girano senza, quindi scorrimento e animazione reggono 120 FPS e l'app resta quasi inattiva a riposo.

Come resta veloce

I due testi che leggono i signal cambiano e la cronologia guadagna una riga; nessun'altra vista viene toccata.

$ nsh test examples/counter/App.tsx --trace
perf commit: 56 ops, 50 mount items, 21 nodes
press(+1)
perf commit: 10 ops, 7 mount items, 24 nodes

Dopo il rilascio, la tua app può ancora ricevere nuova UI

Può scriverla il tuo team, oppure un modello può generarla a ogni richiesta. Arriva sul dispositivo come modulo firmato, gira in una sandbox definita dall'host e viene mostrata in modo nativo.

  1. Scrivi

    Il tuo team o un modello scrive un modulo TSX.

    App.tsx
  2. Verifica

    Controlla i tipi, poi esegui i suoi test in headless.

    nsh check nsh test
  3. Firma

    Un .nshpkg firmato con Ed25519, la cui chiave di rilascio è certificata da una root offline.

    nsh publish
  4. Confine di fiducia

    Esegui

    Il dispositivo verifica firma, certificato e revoche. Ogni vista ottiene una VM con limiti di memoria, tempo di chiamata e nodi, e solo le capability concesse dall'host.

    NshAppView NshView AppView

Tre modi di distribuire, un solo motore

App standalone

Scrivila in Rust, TSX o entrambi, e impacchetta un'app installabile per iOS, Android, macOS, Windows o Linux, o un sito web statico.

$ nsh init my-app --template rust
$ nsh run my-app --target macos
$ nsh package my-app --target windows
# --template ts for TSX
# ios · android · macos · windows · linux · gpui · web
Per iniziare

UI dinamica e plugin

Incorpora una vista in qualsiasi schermata e carica al suo interno moduli TSX firmati a runtime, accanto ai componenti nativi dell'host.

let app = NshAppView()
try app.grantCapabilities(grants)
let info = try await app
  .loadPackage(at: file, trust: trust)
// verified, sandboxed, running
// NshView on Android, AppView elsewhere
Incorporare, piattaforma per piattaforma

UI generata dall'AI

Un modello scrive un modulo per ogni richiesta, così l'app risponde con un'interfaccia. Il tuo server lo verifica e lo firma.

import { mount, signal, View } from "nsh";

function Answer() {
  const range = signal("1W");
  return <View class="gap-3 p-4">…</View>;
}
mount(Answer);
Firma e sandboxing

Il comportamento da NSH, l'aspetto da te

nsh/base contiene componenti base senza stile che gestiscono stato, focus, tastiera e accessibilità, e l'app dà stile a ogni parte. Una sola riga di comando nsh fa il resto.

Componenti base senza stile

Navigazione, dialog, menu, popover, tab, select, data table, un code editor e un kernel di rich text. Dai stile a ogni parte con classi Tailwind o stili tipizzati.

nsh/base

Una toolchain, per persone e agenti

Un solo eseguibile nsh crea, compila, controlla i tipi, fa hot reload, testa, impacchetta e firma. Le dichiarazioni sono generate dai sorgenti Rust e la documentazione è servita come llms.txt, così un agente esegue l'intero ciclo con gli stessi comandi.

nsh run, nsh test, nsh package

Verificato su ogni target

Gli stessi test girano in headless, e in finestre reali, in un simulatore iOS, su un dispositivo Android o in un browser, con l'input proprio della piattaforma.

nsh test --target ios

Viste e interazione native,
il tuo design visivo

Installa nsh e avvia la tua prima app TSX in un minuto.