이 페이지의 번역은 오류가 있을 수 있습니다. 영어 원문 보기

Native Shell

한 번 만들면, 어디서나 네이티브

앱은 가운데에 있습니다. 주변의 각 아치는 하나의 플랫폼입니다.

TSX만 작성하면 Rust 못지않게 빠른 네이티브 클라이언트를 배포할 수 있습니다. 하나의 코드베이스가 8개 플랫폼에서 실행되며, 각 플랫폼은 시스템 고유의 UI와 인터랙션을 갖춥니다.

FPS
120
첫 프레임
~1 ms
플랫폼
8

Rust 바로 옆에서 작성하는 TSX 클라이언트

NSH에서 JS인 것은 앱 코드뿐입니다. 반응형 그래프, 렌더러, 레이아웃, 그리고 모든 모듈은 Rust입니다. TSX 앱과 Rust 앱은 동일한 네이티브 실행 파이프라인을 공유합니다.

120 FPS
22개의 실시간 스파크라인, 호가창, 체결 내역이 함께 갱신되며 프레임 p95는 4 ms 미만
~0.1 ms
엔진 시작 (75–155 µs)
~1 ms
카운터 앱의 첫 프레임
~0.12 ms
탭 한 번, 이벤트부터 커밋까지
< 1 KB
hello world의 앱 코드
~1.1 MB
웹에서 TSX 앱의 다운로드 크기 (Wasm 런타임)
측정한 작은 앱: 기본 시스템 창보다 몇 MB 더 사용
TSXRust기본 시스템 창
메모리 사용량, macOS~20 MB~19 MB~17 MB
Private dirty 메모리, Linux (GTK, GL)~48 MB~44 MB~38 MB
시스템 창 대비, macOS / Linux+3 / +9 MB+2 / +5 MB
Private working set, Windows~15 MB~14 MB
플랫폼별 크기: nsh init의 hello world
TSX 실행 파일TSX 패키지Rust 실행 파일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 다운로드——

릴리스 빌드 기준입니다. 유휴 상태의 메모리: macOS footprint는 Apple M3에서 측정했으며(카운터 앱과 Rust 템플릿은 1200 × 800, 시스템 창은 480 × 640에 레이블 하나), Linux private dirty 메모리는 NVIDIA RTX 3060 Ti에서 측정했고(nsh init의 TSX 및 Rust 템플릿과 레이블 하나가 있는 GTK 창, 모두 480 × 640), Windows는 private working set입니다. RSS와 USS를 포함한 각 플랫폼의 측정값은 보고서에 있습니다. 크기: nsh package의 릴리스 빌드이며 링크 타임 최적화와 strip을 적용했습니다. TSX 실행 파일에는 QuickJS 런타임이 포함되고 앱 코드는 1 KB 미만입니다. 패키지는 macOS에서는 zip으로 압축한 .app, Linux에서는 .tar.gz, Windows에서는 .zip이며, 웹에서는 브라우저가 내려받는 런타임과 앱의 크기입니다. 전체 성능 보고서

의존성 0개의 TSX

앱은 아래 파일들로 이루어집니다. nsh 명령줄이 자체 번들러와 툴체인을 제공하며, import하는 모듈은 네이티브입니다.

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

my-app/
  App.tsx
  nsh.json
  tsconfig.json
  • nsh 실행 파일 하나로 생성, 실행, 테스트, 패키징
  • 파일을 저장한 뒤 새 버전이 실행되기까지 약 120 ms
  • nsh check는 TypeScript 7의 네이티브 tsc로 타입을 검사합니다
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개 플랫폼, 각각 시스템 고유의 컨트롤

NSH는 각 플랫폼이 이미 가진 요소로 UI를 구성합니다. 텍스트 입력, 선택, 입력기, 접근성은 시스템이 제공하므로, 새 OS 릴리스가 이들에 가져오는 개선이 앱에도 그대로 반영됩니다.

플랫폼뷰텍스트텍스트 입력요구 사항
macOSAppKitCoreTextNSTextViewmacOS 14+
LinuxGTK 4PangoGtkTextViewGTK 4.14+
WindowsWin32, Direct2DDirectWriteNSH의 에디터, IMM32Windows 10 1809+
WebHTML, CSS브라우저 제공<input>, <textarea>최신 브라우저
iOSUIKitCoreTextUITextViewiOS 15+
AndroidAndroid 뷰StaticLayoutEditTextAPI 28+
TUIratatui터미널의 글꼴Readline 키, 입력기macOS, Windows, Linux
GPUIGPUIGPUI의 텍스트 시스템NSH의 에디터GPUI Kit 앱에 임베드

지도, 웹 뷰, 비디오, 그리고 호스트가 등록한 모든 네이티브 뷰는 같은 계층 구조 안의 또 하나의 하위 뷰입니다. 앱의 나머지 부분과 함께 레이아웃, 클리핑, 스크롤, 터치 처리가 이루어집니다. 플랫폼별 백엔드

앱 하나, 기기마다 고유한 형태로

동일하게 컴파일된 코드가 여기서 두 번 실행되며, 달라지는 것은 기기뿐입니다. 포인터 환경에서는 대화 목록이 옆에 있는 창으로, 휴대폰에서는 버튼과 입력창이 Liquid Glass로 떠 있고 그 아래로 스레드가 스크롤됩니다. 터미널에서는 문자 격자 위에 표시됩니다. 앱은 한 번만 작성합니다.

데스크톱라이브: 메시지를 입력해 보세요
휴대폰라이브: 메시지를 입력해 보세요
터미널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                                                │
                     │ ╰───────────────────────────────────────────────────────────────╯

데스크톱과 휴대폰은 Native Shell의 웹 런타임으로 브라우저에서 실시간 실행됩니다. 터미널은 nsh run --target tui의 실제 출력입니다.

원한다면 같은 엔진을 Rust로

Rust는 앱 전체를 작성할 수 있는 일급 언어입니다. UI, 로직, 컴포넌트가 네이티브 코드로 컴파일되어 까다로운 비즈니스 로직에도 적합합니다. 둘 다 같은 엘리먼트와 시그널을 사용하며, TSX 화면에서 Rust 컴포넌트를 import할 수 있습니다.

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

변경된 뷰만 건드립니다

모든 엘리먼트는 플랫폼이 유지하는 뷰입니다. 변경이 발생하면 바뀐 시그널을 읽는 표현식만 프레임당 한 번의 배치로 실행됩니다. 메인 스레드는 JS를 기다리지 않고 네이티브 애니메이션도 JS 없이 실행되므로, 스크롤과 애니메이션은 120 FPS를 유지하고 앱은 유휴 상태에서 거의 아무 일도 하지 않습니다.

빠르게 유지되는 방법

시그널을 읽는 두 텍스트가 바뀌고 기록에 한 행이 추가되며, 다른 뷰는 건드리지 않습니다.

$ 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

릴리스 후에도 앱은 새로운 UI를 받을 수 있습니다

팀이 직접 작성할 수도 있고, 모델이 요청마다 생성할 수도 있습니다. UI는 서명된 모듈로 기기에 전달되어, 호스트가 설정한 샌드박스에서 실행되고 네이티브로 표시됩니다.

  1. 작성

    팀 또는 모델이 TSX 모듈을 작성합니다.

    App.tsx
  2. 검사

    타입을 검사한 뒤 헤드리스로 테스트를 실행합니다.

    nsh check nsh test
  3. 서명

    Ed25519로 서명된 .nshpkg이며, 릴리스 키는 오프라인 루트가 인증합니다.

    nsh publish
  4. 신뢰 경계

    실행

    기기가 서명, 인증서, 폐기 목록을 검증합니다. 각 뷰는 메모리, 호출 시간, 노드 수 제한이 있는 VM을 받으며, 호스트가 허용한 기능만 사용할 수 있습니다.

    NshAppView NshView AppView

배포 방식 세 가지, 엔진 하나

독립 실행형 앱

Rust, TSX 또는 둘 다로 작성하고, 설치 가능한 iOS, Android, macOS, Windows, Linux 앱이나 정적 웹사이트로 패키징합니다.

$ 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
시작하기

동적 UI와 플러그인

어떤 화면에든 뷰를 임베드하고, 호스트 자체의 네이티브 컴포넌트와 나란히 서명된 TSX 모듈을 런타임에 로드합니다.

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
플랫폼별 임베딩

AI 생성 UI

모델이 요청마다 모듈을 작성해, 앱이 인터페이스로 응답합니다. 서버가 이를 검사하고 서명합니다.

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

function Answer() {
  const range = signal("1W");
  return <View class="gap-3 p-4">…</View>;
}
mount(Answer);
서명과 샌드박싱

동작은 NSH에서, 룩은 당신이

nsh/base에는 상태, 포커스, 키보드, 접근성을 담당하는 스타일 없는 기본 컴포넌트가 들어 있으며, 각 부분의 스타일은 앱이 지정합니다. 나머지는 nsh 명령줄 하나로 처리합니다.

스타일 없는 기본 컴포넌트

내비게이션, 다이얼로그, 메뉴, 팝오버, 탭, 셀렉트, 데이터 테이블, 코드 에디터, 리치 텍스트 커널을 제공합니다. 각 부분은 Tailwind 클래스나 타입이 지정된 스타일로 꾸밉니다.

nsh/base

사람과 에이전트를 위한 하나의 툴체인

nsh 실행 파일 하나로 생성, 빌드, 타입 검사, 핫 리로드, 테스트, 패키징, 서명을 처리합니다. 선언은 Rust 소스에서 생성되고 문서는 llms.txt로 제공되므로, 에이전트도 같은 명령으로 전체 루프를 실행할 수 있습니다.

nsh run, nsh test, nsh package

모든 타깃에서 검증

동일한 테스트를 헤드리스로 실행하고, 실제 창, iOS 시뮬레이터, Android 기기, 브라우저에서도 각 플랫폼 고유의 입력으로 실행합니다.

nsh test --target ios

네이티브 뷰와 인터랙션,
당신의 비주얼 디자인

nsh를 설치하고 1분 안에 첫 TSX 앱을 실행해 보세요.