Esta página se tradujo automáticamente y puede contener errores. Leer el original en inglés

Native Shell

Crea una vez, nativo en todas partes

Tu app está en el centro. Cada arco a su alrededor es una plataforma.

Escribe solo TSX y distribuye clientes nativos que van al ritmo de Rust. Una sola base de código se ejecuta en 8 plataformas, cada una con la UI y la interacción propias del sistema.

FPS
120
primer fotograma
~1 ms
plataformas
8

Un cliente escrito en TSX, justo al lado de Rust

En NSH solo el código de tu app es JS. El grafo reactivo, el renderizador, el layout y todos los módulos son Rust. Las apps en TSX y en Rust comparten el mismo pipeline de ejecución nativo.

120 FPS
22 sparklines en vivo, un libro de órdenes y una cinta actualizándose a la vez, frame p95 por debajo de 4 ms
~0.1 ms
Arranque del motor (75–155 µs)
~1 ms
Primer fotograma de una app contador
~0.12 ms
Un toque, del evento al commit
< 1 KB
El código de app de un hello world
~1.1 MB
Descarga de una app TSX en la web (runtime de Wasm)
Apps pequeñas medidas: unos pocos MB por encima de la ventana básica del sistema
TSXRustVentana básica del sistema
Huella de memoria, macOS~20 MB~19 MB~17 MB
Memoria privada sucia, Linux (GTK, GL)~48 MB~44 MB~38 MB
Por encima de la ventana del sistema, macOS / Linux+3 / +9 MB+2 / +5 MB
Conjunto de trabajo privado, Windows~15 MB~14 MB
Tamaño en cada plataforma: el hello world de nsh init
Ejecutable TSXPaquete TSXEjecutable RustPaquete 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—~1.1 MB de descarga——

Compilaciones release. Memoria en reposo: huella en macOS en un Apple M3 (la app contador y la plantilla de Rust a 1200 × 800; la ventana del sistema contiene una etiqueta a 480 × 640); memoria privada sucia en Linux en una NVIDIA RTX 3060 Ti (las plantillas TSX y Rust de nsh init y una ventana GTK con una etiqueta, todas a 480 × 640); conjunto de trabajo privado en Windows. La medición de cada plataforma, con RSS y USS, está en el informe. Tamaños: compilaciones release de nsh package, con optimización en tiempo de enlace y símbolos eliminados; el ejecutable TSX incluye el runtime QuickJS y el código de la app ocupa menos de 1 KB; el paquete es el .app comprimido en zip en macOS, el .tar.gz en Linux y el .zip en Windows; en la web, lo que descarga el navegador, runtime y app. El informe completo de rendimiento

TSX con 0 dependencias

Una app son los archivos de abajo. La línea de comandos nsh trae su propio bundler y toolchain, y los módulos que importas son nativos.

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

my-app/
  App.tsx
  nsh.json
  tsconfig.json
  • Un solo ejecutable nsh crea, ejecuta, prueba y empaqueta
  • ~120 ms desde que guardas un archivo hasta que la nueva versión se ejecuta
  • nsh check comprueba los tipos con el tsc nativo de 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 plataformas, cada una con los controles propios del sistema

NSH construye cada UI con lo que su plataforma ya tiene. La entrada de texto, la selección, los métodos de entrada y la accesibilidad vienen del sistema, y lo que una nueva versión del SO aporta a todo ello llega a la app con ella.

PlataformaVistasTextoEntrada de textoRequiere
macOSAppKitCoreTextNSTextViewmacOS 14+
LinuxGTK 4PangoGtkTextViewGTK 4.14+
WindowsWin32, Direct2DDirectWriteEl editor de NSH, IMM32Windows 10 1809+
WebHTML, CSSEl del navegador<input>, <textarea>Navegadores modernos
iOSUIKitCoreTextUITextViewiOS 15+
AndroidAndroid viewsStaticLayoutEditTextAPI 28+
TUIratatuiLa fuente de la terminalTeclas Readline, métodos de entradamacOS, Windows, Linux
GPUIGPUIEl sistema de texto de GPUIEl editor de NSHIntegrado en apps de GPUI Kit

Los mapas, las web views, el vídeo y cualquier vista nativa que registre el host son una subvista más en la misma jerarquía: se disponen, se recortan, se desplazan y reciben toques junto con el resto de la app. El backend de cada plataforma

Una app, en la forma propia de cada dispositivo

El mismo código compilado se ejecuta aquí dos veces, y solo cambia el dispositivo. Con un puntero es una ventana con sus conversaciones a un lado; en un teléfono los botones y el compositor flotan en Liquid Glass con el hilo desplazándose por debajo; en una terminal se asienta sobre la cuadrícula de caracteres. La app se escribe una sola vez.

EscritorioEn vivo: escribe un mensaje
TeléfonoEn vivo: escribe un mensaje
TerminalExplorar 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                                                │
                     │ ╰───────────────────────────────────────────────────────────────╯

Escritorio y teléfono se ejecutan en vivo en tu navegador sobre el runtime web de Native Shell. La terminal es salida real de nsh run --target tui.

El mismo motor en Rust, cuando lo quieras

Rust es un lenguaje de primera clase para apps completas: la UI, la lógica y los componentes se compilan a código nativo, listo para lógica de negocio exigente. Ambos usan los mismos elementos y signals, y las pantallas TSX importan tus componentes Rust.

Crear 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())),
        )
}

Solo se tocan las vistas que cambiaron

Cada elemento es una vista que la plataforma mantiene. Un cambio ejecuta solo las expresiones que leen el signal modificado, en un único lote por fotograma. El hilo principal nunca espera a JS y las animaciones nativas se ejecutan sin él, así que el desplazamiento y la animación mantienen 120 FPS y la app queda casi inactiva en reposo.

Cómo se mantiene rápida

Cambian los dos textos que leen los signals y el historial gana una fila; ninguna otra vista se toca.

$ 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

Tras el lanzamiento, tu app aún puede recibir nueva UI

Tu equipo puede escribirla, o un modelo puede generarla para cada solicitud. Llega al dispositivo como un módulo firmado, se ejecuta en un sandbox que define el host y se muestra de forma nativa.

  1. Escribir

    Tu equipo o un modelo escribe un módulo TSX.

    App.tsx
  2. Comprobar

    Comprueba sus tipos y luego ejecuta sus pruebas en modo headless.

    nsh check nsh test
  3. Firmar

    Un .nshpkg firmado con Ed25519, con su clave de release certificada por una raíz sin conexión.

    nsh publish
  4. Límite de confianza

    Ejecutar

    El dispositivo verifica la firma, el certificado y las revocaciones. Cada vista obtiene una VM con límites de memoria, tiempo de llamada y nodos, y solo las capacidades que concede el host.

    NshAppView NshView AppView

Tres formas de distribuir, un solo motor

Apps independientes

Escríbela en Rust, TSX o ambos, y empaqueta una app instalable para iOS, Android, macOS, Windows o Linux, o un sitio web estático.

$ 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
Primeros pasos

UI dinámica y plugins

Incrusta una vista en cualquier pantalla y carga en ella módulos TSX firmados en tiempo de ejecución, junto a los componentes nativos propios del 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
Incrustación, por plataforma

UI generada por IA

Un modelo escribe un módulo por solicitud, de modo que la app responde con una interfaz. Tu servidor la comprueba y la firma.

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

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

El comportamiento, de NSH; el aspecto, tuyo

nsh/base contiene componentes base sin estilo que gestionan el estado, el foco, el teclado y la accesibilidad, y la app da estilo a cada parte. Una sola línea de comandos nsh hace el resto.

Componentes base sin estilo

Navegación, diálogos, menús, popovers, pestañas, selects, tablas de datos, un editor de código y un núcleo de texto enriquecido. Da estilo a cada parte con clases de Tailwind o con estilos tipados.

nsh/base

Una sola toolchain, para personas y agentes

Un solo ejecutable nsh crea, compila, comprueba tipos, recarga en caliente, prueba, empaqueta y firma. Las declaraciones se generan a partir de las fuentes de Rust y la documentación se sirve como llms.txt, de modo que un agente ejecuta todo el ciclo con los mismos comandos.

nsh run, nsh test, nsh package

Verificado en cada destino

Las mismas pruebas se ejecutan en modo headless, y en ventanas reales, un simulador de iOS, un dispositivo Android o un navegador, con la entrada propia de la plataforma.

nsh test --target ios

Vistas e interacción nativas,
tu diseño visual

Instala nsh y ten tu primera app TSX en marcha en un minuto.