Murasaki
ビルド & 配布

設定

murasaki.config.ts の完全なリファレンス。

プロジェクトルートの murasaki.config.ts(または .js / .mjs)は、アプリの識別情報、ウィンドウ、ビルド設定を記述します。

murasaki.config.ts
import { defineConfig } from 'murasaki'

export default defineConfig({
  appId: 'app.murasaki.example',
  productName: 'Murasaki App',
  version: '0.1.0',
  icon: 'assets/icon.png',
  window: {
    title: 'Murasaki App',
    width: 1000,
    height: 700,
    backendCapabilities: ['api:POST:/api/documents'],
  },
  capabilities: ['dialog:openFile', 'clipboard:writeText'],
})

defineConfig は型推論のために受け取ったオブジェクトをそのまま返し、宣言されたウィンドウのラベルとルートを同期的に検証します。await は不要です。

トップレベルのフィールド

フィールド説明
appIdstring必須。 ポータブルな逆 DNS 形式の識別子(例: com.example.my-app。英数字・ドット・ハイフンが使用可能)。macOS では CFBundleIdentifier として使われます。
productNamestring必須。 ポータブルな 1〜120 文字の表示名兼ファイル名で、.app のファイル名、Dock とメニューバーのラベル、DMG のボリューム名になります。パス区切り文字や Windows の予約デバイス名、前後の空白、末尾のドットは使用できません。
versionstring?厳密なセマンティックバージョン(例: 1.2.3 / 1.2.3-beta.1v プレフィックスは不可)。ネイティブの About パネルとアーティファクトのファイル名に使われます。デフォルトは 0.0.0
descriptionstring?ネイティブの「About <app>」パネルに表示される短い説明。
copyrightstring?About パネルに表示される著作権表示。
homepagestring?About パネルに表示されるホームページ URL。
authorsstring[]?About パネルに表示される作者名(Windows/Linux のみ)。
aboutAboutConfig?サイズ、段落、詳細行、外部リンクボタンをカスタマイズできる macOS の About パネルを有効にします — 下記を参照。
windowWindowConfig?ウィンドウの形 — 下記を参照。
windowsRecord<string, SecondaryWindowConfig>?安定したラベルをキーにしたセカンダリウィンドウの定義 — 下記を参照。
webviewWebviewConfig?アプリ全体の User-Agent、プライベートセッション、認証なしプロキシの設定 — 下記を参照。
capabilitiesNativeCapabilityGrant[]?プライマリウィンドウ向けのネイティブレンダラー許可。window.capabilities を省略した場合にのみ使用されます。デフォルトではすべて拒否。
backendCapabilitiesBackendCapability[]?プライマリウィンドウ向けの、レンダラーから Node / API への許可。window.backendCapabilities を省略した場合にのみ使用されます。デフォルトではすべて拒否。
systemPermissionsSystemPermissionsConfig?ホスト OS の同意宣言と、パッケージ化された macOS アプリの起動時プロンプト — 下記を参照。
mainfalse | object?長寿命な Node Main のエントリと、シャットダウンの上限 — 下記を参照。
bundleobject?Node の依存関係と、コード以外のリソースのパッケージング — 下記を参照。
pluginsMurasakiPlugin[]?Vite、CLI フック、依存関係、リソースを拡張する、信頼されたビルド時拡張機能 — 下記を参照。
buildobject?ビルド前コマンドと、クライアントに公開する環境変数のプレフィックス — 下記を参照。
securityobject?レンダラーの Content Security Policy — 下記を参照。
updaterUpdaterConfig?自動更新のソース — 下記を参照。
localesstring[]?アプリが対応する BCP-47 の UI 言語(例: ['en', 'ja'])。macOS バンドルの CFBundleLocalizations に反映され、Murasaki のデフォルトのネイティブメニュー翻訳を制約します。デフォルトは Murasaki がメニュー翻訳を提供しているすべての言語: enjazh-Hanskoesfrde
devPortnumber?murasaki dev 実行時の Vite 開発サーバーのポート。デフォルトは 5178(使用中なら自動インクリメント)。
targetsTarget[]?ビルドターゲット。デフォルトはホストプラットフォーム。darwin-arm64darwin-x64win32-x64win32-arm64linux-x64linux-arm64 のうち1つ以上。
iconstring?正方形のソース PNG(1024px 推奨)へのパス。フル Xcode がある macOS では Assets.car をコンパイルして現在のマスクを OS に任せ、.icns をレガシーフォールバックとして残します。Windows / Linux 向けのリソースも同じソースから生成されます。
protocolsProtocolConfig[]?パッケージ化された macOS アプリや Windows インストーラーが登録するカスタム URL スキーム — 下記を参照。
fileAssociationsFileAssociationConfig[]?パッケージ化された macOS アプリや Windows インストーラーが登録するドキュメントの拡張子 — 下記を参照。
installerobject?macOS の DMG と Windows インストーラーのオプション — 下記を参照。
signobject?macOS Developer ID / Windows Authenticode 署名 — 下記を参照。

about

about を省略すると、OS 標準のコンパクトな About ダイアログがそのまま使われます。macOS では、これを宣言した場合だけカスタマイズ可能なネイティブ AppKit パネルに切り替わります。Windows / Linux では、現時点では標準のメタデータダイアログを使い続けます。

murasaki.config.ts
about: {
  name: 'My App',
  width: 520,
  height: 680,
  paragraphs: [
    '作業に集中できるデスクトップワークスペース。',
    'Murasakiで構築されています。',
  ],
  paragraphSpacing: 16,
  details: [
    { label: 'Build', value: '15212' },
    {
      label: 'Commit',
      value: '332b2aefc',
      href: 'https://github.com/example/app/commit/332b2aefc',
    },
  ],
  buttons: [
    { label: 'Docs', href: 'https://docs.example.com' },
    { label: 'GitHub', href: 'https://github.com/example/app' },
  ],
},
フィールド説明
namestring?パネルの見出し。デフォルトは productName
widthnumber?論理ピクセル単位の幅。360〜900、デフォルトは 480。
heightnumber?論理ピクセル単位の高さ。320〜1000。省略した場合は内容に応じて自動調整されます。
paragraphsstring[]?中央揃えの本文段落。最大 8 件。省略した場合は description を使用します。
paragraphSpacingnumber?段落間の余白。0〜48。デフォルトは 12。
details{ label, value, href? }[]?ラベルと値の詳細行。最大 12 件。Version 行を指定しなければ自動的に追加されます。
buttons{ label, href }[]?下端に並べるネイティブボタン。最大 6 件。

外部リンク先は、認証情報を含まない絶対 httphttpsmailto の URL に限定されます。アプリアイコンは macOS がインストール済みのバンドルから解決するため、About パネルは Finder や Dock と同じマスク済みのアイコン表示になります。

window

フィールド説明
titlestring?ウィンドウのタイトルバーのテキスト。起動時に一度だけ設定されます。
width / heightnumber?初期ウィンドウサイズ。
minWidth / minHeightnumber?最小ウィンドウサイズ。
resizableboolean?ウィンドウをリサイズ可能にするかどうか。
transparentboolean?透明なウィンドウ背景。
vibrancy'hud' | 'sidebar' | 'popover' | nullmacOS の半透明なウィンドウビブランシー。
consoleboolean?Windows のみ: バックエンドの Node コンソールウィンドウを表示します。デフォルトは false
routestring?このウィンドウに読み込む同一オリジンのパス。デフォルトは /。完全 URL やプロトコル相対 URL は拒否されます。
visibleboolean?初期表示状態。main はデフォルト true、セカンダリウィンドウはデフォルト false
capabilitiesNativeCapabilityGrant[]?ウィンドウごとのネイティブ許可。セカンダリウィンドウはデフォルトではすべて拒否。
backendCapabilitiesBackendCapability[]?ウィンドウごとの Node Main、Server Action、API Route、アップデーター、イベント、診断機能に対する許可。セカンダリウィンドウはデフォルトではすべて拒否。

macOS では、vibrancy に対応するセマンティックな NSVisualEffectView マテリアルを適用し、ネイティブウィンドウと WebView を自動的に透明化します。マテリアルを見せたい領域では、レンダラーの背景も透明にしてください。他のプラットフォームでは、この macOS 専用のオプションは無視されます。

windows

window は、予約ラベル main を持つプライマリウィンドウです。セカンダリウィンドウは windows に宣言します。各エントリはプライマリ専用の console を除いて同じ形式を受け付け、ルート、初期表示、コマンドの許可リストをそれぞれ個別に設定できます。

window: {
  route: '/',
  capabilities: ['window:open', 'window:list', 'window:manage'],
  backendCapabilities: ['api:POST:/api/settings'],
},
windows: {
  settings: {
    route: '/settings',
    width: 720,
    height: 560,
    createOnLaunch: false,
    capabilities: [],
    backendCapabilities: ['api:GET:/api/settings'],
  },
},

ラベルは安全な 1〜64 文字で、main は予約済みです。セカンダリウィンドウはデフォルトで createOnLaunch: true を使い、非表示の状態で作成されます。false にすると、Node Main が windows.create(label) を呼び出すまで宣言を休止状態にできます。プライマリウィンドウは常に起動時に作成されます。セカンダリウィンドウはトップレベルの権限を一切継承しません。console フィールドはアプリケーション全体の Windows バックエンドコンソールを制御するオプションのため、セカンダリで指定すると拒否されます。ライフサイクルとレンダラー API については、ウィンドウと権限を参照してください。

セカンダリ専用フィールド説明
createOnLaunchboolean?起動時に、宣言されたセカンダリウィンドウを作成します。デフォルトは truefalse にすると、信頼された Node Main のテンプレートとして保持されます。

webview

これらの設定は、開発時およびパッケージ化された macOS / Windows アプリのすべてのネイティブ WebView に適用されます。ウィンドウ単位のオーバーライドはサポートされていません。

murasaki.config.ts
webview: {
  userAgent: 'AcmeDesktop/1.4 Murasaki',
  incognito: true,
  proxy: {
    protocol: 'socks5',
    host: '127.0.0.1',
    port: 1080,
  },
},
フィールド説明
userAgentstring?完全なカスタム User-Agent の値。前後の空白を取り除き、制御文字を含まず、最大 512 UTF-8 バイトである必要があります。
incognitoboolean?アプリの永続プロファイルの代わりに、Wry の非永続/プライベートなデータストアを使用します。デフォルトは false
proxy.protocol'http' | 'socks5'http は HTTP CONNECT プロキシ、socks5 は SOCKSv5 を表します。
proxy.hoststringASCII の DNS ホスト名、IPv4 アドレス、または角括弧付き IPv6 リテラルで、最大 253 バイト。URL ではありません。
proxy.portnumber1〜65535 の整数。

プロキシの URL や認証用フィールドは意図的にサポートしていません。スキーム、パス、user@host、ユーザー名、パスワード、未知のプロキシフィールドは設定の検証で拒否されます。認証が必要なプロキシを使う場合は、Murasaki の外側で設定するか、認証なしのローカル転送プロキシを使用してください。設定は Wry のネイティブ WebKit / WebView2 ビルダーへ渡され、Rust ホスト側でも再検証されます。

プラットフォームごとの制約は次のとおりです。

  • macOS のプロキシ機能は Wry の mac-proxy 機能を使用し、macOS 14 以降が必要です。古い macOS でプロキシを設定すると、WebView の起動が明示的に失敗します。プライベートセッションには WebKit の非永続データストアを使用します。
  • Windows のプロキシ機能は WebView2 のブラウザ引数を使用します。カスタム User-Agent には WebView2 86.0.616.0 以降、プライベートモードには 101.0.1210.39 以降が必要で、古いランタイムでは WebView2 がこれらの設定を無視します。
  • Linux では、開発時と AppDir / AppImage / .deb の配布ビルドのどちらでも、これらの設定を Wry / WebKitGTK へ渡します。実際の挙動は、対象ディストリビューションに含まれる WebKitGTK のバージョンでも確認してください。

incognito が制御するのは、ローカルの WebView の永続化だけです。ネットワークの匿名化、プロキシ/サーバーからのクライアントの秘匿、アプリレベルの Node データのプライベート化は行いません。Murasaki はネイティブウィンドウごとにブラウザプロファイルを分離するため、cookie、ストレージ、ワーカーがウィンドウ別のバックエンド権限をまたぐことはありません。プライマリウィンドウは従来どおりのアプリプロファイルを維持し、セカンダリウィンドウのプロファイルは Windows / Linux と macOS 14 以降では永続化されます。macOS 11〜13 では分離された非永続ストアを使用します。そのため、ウィンドウ間でのセッション共有は意図的にサポートされていません。状態を共有したい場合は、Main / API を使って明示的に同期してください。セキュリティも参照してください。

capabilities

レンダラー向けのネイティブ API は、デフォルトですべて拒否されます。アプリが実際に使うコマンドだけを追加してください。未知の権限は何も許可しません。

capabilities: [
  'app:quit',
  'autostart:read',
  'autostart:write',
  'dialog:openFile',
  'clipboard:readText',
  'clipboard:writeText',
  'notification:show',
  'shell:openExternal',
  'window:setTitle',
]

完全な型付き一覧は NativeCapability です。プライマリウィンドウは window.capabilities ?? capabilities ?? [] を使い、各セカンダリウィンドウは自身のリストまたは [] を使います。許可は呼び出し元のレンダラーごとに評価され、別オリジンのページはネイティブブリッジを利用できません。ウィンドウ管理には window:getLabelwindow:openwindow:listwindow:manage を使います。アプリケーションのプログラムによるシャットダウンには app:quit が必要です。組み込みのアップデーターを有効にすると、検証済みの再起動ハンドシェイク用としてプライマリウィンドウへ自動的に付与されます。ログイン時の自動起動は、読み取りと書き込みの権限が分離されています。status() だけを呼ぶウィンドウには autostart:read を、enable()disable() を呼ぶ設定画面には autostart:write を付与してください。

ターゲットを持つコマンドを制限したい場合は、構造化された NativeCapabilityGrant を使います。denyallow より優先され、ワイルドカードとして使えるのは末尾の /** だけです。

capabilities: [
  { permission: 'shell:openExternal', allow: { urls: ['https://example.com/help/**'] } },
  { permission: 'shell:showItemInFolder', allow: { paths: ['/Users/me/Documents/**'] } },
  { permission: 'window:manage', allow: { windows: ['settings', 'preview'] } },
  { permission: 'systemPermission:request', allow: { permissions: ['camera'] } },
  { permission: 'secureStorage:get', allow: { keys: ['account:*'] } },
  { permission: 'webview:writeCookies', allow: { urls: ['https://app.example.com/**'] } },
]

互換性のため、文字列形式の許可はターゲットに制限がありません。URL、パス、キー、ウィンドウ、OS 権限のスコープは、設定の読み込み時に検証され、Rust ホスト側でも再度強制されます。

backendCapabilities

レンダラーからローカルの Node リソースへのアクセスも、別途デフォルトですべて拒否されます。プライマリウィンドウは window.backendCapabilities ?? backendCapabilities ?? [] を使い、セカンダリウィンドウは何も継承せず、自身のリストまたは [] を使います。

backendCapabilities: [
  'main:src/backend/account.ts#loadAccount',
  'action:src/actions/save.ts#saveDocument',
  'api:POST:/api/documents/*',
  'updater:check',
  'events:sync.*',
  'diagnostics:renderer-error',
]

末尾に 1 つだけ * が付いた許可はプレフィックスワイルドカードとして扱われ、それ以外は完全一致になります。API リソースには大文字のメソッドを含めます。main:*action:*api:*updater:*events:* のような広い許可も有効ですが、本番環境では厳密なリソース指定の方が安全です。ネイティブのシャットダウン、アクティベーション、ウィンドウ制御のエンドポイントはレンダラーへ許可できません。セキュリティも参照してください。

systemPermissions

この設定が表すのは、信頼するレンダラーコマンドではなく、ホスト OS の同意です。パッケージ化された macOS アプリでは、用途説明を Info.plist に書き込み、ほとんどの権限を起動時に要求できます。

systemPermissions: {
  macOS: {
    camera: {
      usageDescription: 'ビデオ通話でカメラを使用します。',
      requestOnLaunch: true,
    },
    microphone: {
      usageDescription: '音声通話でマイクを使用します。',
    },
    screenRecording: { requestOnLaunch: false },
    accessibility: { requestOnLaunch: false },
    inputMonitoring: { requestOnLaunch: false },
    location: {
      usageDescription: '近くのスポットを表示します。',
      mode: 'whenInUse',
    },
    fullDiskAccess: { requestOnLaunch: false },
    photos: { usageDescription: '投稿に写真を添付します。' },
    contacts: { usageDescription: '友達を見つけます。' },
    calendar: { usageDescription: '予定を確認します。' },
    reminders: { usageDescription: 'リマインダーを確認します。' },
    speechRecognition: { usageDescription: 'ボイスメモを文字起こしします。' },
    bluetooth: { usageDescription: '近くのデバイスを見つけます。' },
    appleEvents: { usageDescription: '他のappを代わりに自動操作します。' },
    localNetwork: { usageDescription: 'このネットワーク上のデバイスを探します。' },
  },
},
フィールド説明
macOS.camera{ usageDescription: string; requestOnLaunch?: boolean }NSCameraUsageDescription を書き込みます。任意で、パッケージ化されたアプリの起動時にプロンプトを表示します。
macOS.microphone{ usageDescription: string; requestOnLaunch?: boolean }NSMicrophoneUsageDescription を書き込みます。任意で、パッケージ化されたアプリの起動時にプロンプトを表示します。
macOS.screenRecording{ requestOnLaunch?: boolean }任意で、パッケージ化されたアプリの起動時に画面収録の同意を要求します。
macOS.accessibility{ requestOnLaunch?: boolean }任意で、パッケージ化されたアプリの起動時に macOS のアクセシビリティ信頼プロンプトを開きます。
macOS.inputMonitoring{ requestOnLaunch?: boolean }任意で、パッケージ化されたアプリの起動時に入力監視(HID リッスンイベント)の同意を要求します。
macOS.location{ usageDescription: string; mode?: 'whenInUse' | 'always'; requestOnLaunch?: boolean }NSLocationWhenInUseUsageDescription を書き込みます(mode: 'always' の場合は NSLocationAlwaysAndWhenInUseUsageDescription も追加)。任意で、パッケージ化されたアプリの起動時にプロンプトを表示します。
macOS.fullDiskAccess{ requestOnLaunch?: boolean }ガイダンスのみです。TCC のリクエスト API が存在しないため、ステータスがすでに granted でない限り、requestOnLaunch はアプリ内プロンプトの代わりにシステム設定の「フルディスクアクセス」ペインを開きます。
macOS.photos{ usageDescription: string; requestOnLaunch?: boolean }NSPhotoLibraryUsageDescription を書き込みます(読み書き両方のライブラリアクセス)。
macOS.contacts{ usageDescription: string; requestOnLaunch?: boolean }NSContactsUsageDescription を書き込みます。
macOS.calendar{ usageDescription: string; requestOnLaunch?: boolean }NSCalendarsUsageDescriptionNSCalendarsFullAccessUsageDescription を書き込みます(常に両方を書き込むことで、1 つのビルドが macOS 11 から 14 以降まで正しく動作します)。
macOS.reminders{ usageDescription: string; requestOnLaunch?: boolean }NSRemindersUsageDescriptionNSRemindersFullAccessUsageDescription を書き込みます(calendar と同じ理由です)。
macOS.speechRecognition{ usageDescription: string; requestOnLaunch?: boolean }NSSpeechRecognitionUsageDescription を書き込みます。
macOS.bluetooth{ usageDescription: string; requestOnLaunch?: boolean }NSBluetoothAlwaysUsageDescription を書き込みます。CoreBluetooth には明示的なリクエスト呼び出しがなく、central manager が最初に作成された時点で暗黙的に同意が確定します。
macOS.appleEvents{ usageDescription: string }NSAppleEventsUsageDescription を書き込みます。宣言のみで、requestOnLaunch はありません。オートメーションの同意は対象アプリごとに付与されるため、status() は常に unknown を返し、request() はガイダンスとしてシステム設定の「オートメーション」ペインを開くだけです。
macOS.localNetwork{ usageDescription: string }NSLocalNetworkUsageDescription を書き込みます。宣言のみで、照会・リクエスト用の API は一切存在せず、macOS は最初のローカルネットワークアクセス時に自動的にプロンプトを表示します。

ユーザーが先に機能の必要性を理解できる場合は、起動時プロンプトよりも文脈に沿った systemPermission.request() を優先してください。実行時の呼び出しには、そのレンダラーのケイパビリティリストに systemPermission:status / systemPermission:request も必要です。Windows のアンパッケージ版デスクトップでの同意は利用時に発生するため、汎用的な起動時プロンプトはありません。上記の 15 種類はすべて macOS 専用です — Windows と Linux には、これらの TCC 管理下プロンプトに相当する OS レベルの機能がありません。macOS の TCC の実際の挙動は、murasaki dev のターミナルや Node のアイデンティティではなく、パッケージ化されたアプリで確認してください。

Entitlements と App Sandbox

Murasaki が現在対応しているのは Hardened Runtime による署名であり、macOS の App Sandbox ではありません。sign.appSandbox をデフォルトの false のままにした場合、Murasaki は camera、microphone、location、photos、contacts、calendar/reminders、Apple Events に必要な Hardened Runtime のリソースアクセス用エンタイトルメントを systemPermissions.macOS から生成します。署名済みビルドには、これらのホストエンタイトルメントと、対応する Info.plist の用途説明の両方が必要です。この非サンドボックス構成では、Bluetooth と音声認識は用途説明だけを使用します。同梱の Node ヘルパーのみが JIT 用の Hardened Runtime 権限を受け取り、ネイティブアドオンには実行可能エンタイトルメントは付与されません。sign.appSandbox: true は、Apple のヘルパー継承規則と現在の組み込み Node / JIT アーキテクチャが両立しないため、fail-closed で拒否されます。カスタムの sign.entitlements / sign.helperEntitlements はそのまま使用され、指定したパスが存在しないか plutil の検証に失敗した場合はビルドが停止します。種類ごとの完全な対応表は、Native APIs → Entitlements と App Sandboxを参照してください。

main

src/main.ts が存在すると、Murasaki が自動的に読み込みます。main を使うと、別のエントリを指定したり、グレースフルシャットダウンの期限を変更したり、Main の自動検出を無効化したりできます。

main: {
  entry: 'src/backend/main.ts',
  shutdownTimeoutMs: 15_000,
}
// main: false
フィールド説明
entrystring?プロジェクトルートからの相対パス。デフォルトは src/main.ts
shutdownTimeoutMsnumber?ホストが終了する前の beforeQuit()shutdown() を合わせた全体の上限。デフォルトは 10_000

ライフサイクルフックと 'use main' については、Node Mainを参照してください。

protocols

カスタム URL スキームを登録すると、一致する URL を Node Main の openRequested() フックで受け取れます。

protocols: [
  { scheme: 'violet', name: 'Violet Link' },
]
フィールド説明
schemestring必須。 violet://open/42violet のような RFC 3986 形式のスキーム。前後の空白を除去し、小文字に正規化されます。有効なスキーム文字を 1〜63 文字含める必要があります。blobfilehttphttpsjavascriptmailtoms-settingstelmurasaki などのブラウザ/OS スキームは予約済みです。
namestring?パッケージメタデータに使われる、人が読めるハンドラー名。デフォルトは `${productName} URL`

重複したスキームや不正なスキームがあると、ビルドは失敗します。macOS では .appInfo.plist に、Windows では NSIS / MSI インストーラーに登録情報を書き込みます。Linux では .desktop ファイルへ対応する MimeType を記録し、.deb のインストール時にデスクトップデータベースへ登録します。展開しただけの AppDir / AppImage と、ポータブルな Windows アーカイブは、OS への登録処理を行いません。

fileAssociations

1 つ以上の拡張子をドキュメントタイプとして登録します。

fileAssociations: [
  {
    extensions: ['vnote', 'violet-note'],
    name: 'Violet Note',
    description: 'Violet で作成したノート',
    role: 'editor',
    mimeType: 'application/x-violet-note',
  },
]
フィールド説明
extensionsstring[]必須。 1 つ以上の拡張子。先頭にドットを付けても削除され、小文字に正規化されます。各値は英数字・アンダースコア・ハイフンからなる 1〜32 文字で、先頭は英数字である必要があります。
namestring?ドキュメントタイプ名。デフォルトは `${productName} document`
descriptionstring?パッケージ/Windows の登録メタデータに保存する説明。デフォルトは name
role'viewer' | 'editor' | 'shell' | 'none'macOS のドキュメントロール。デフォルトは viewer
mimeTypestring?ドキュメントメタデータに保存する任意の MIME タイプ。

拡張子はすべてのエントリ間で一意である必要があり、不正な拡張子や MIME タイプはビルドエラーになります。一致したファイルは Node Main の openRequested() フックに届きます。配布形式ごとの制約は protocols と同じです。パッケージ化された macOS の .app、インストール済みの Windows NSIS / MSI、インストール済みの Linux の .deb は関連付けを登録します。ポータブルな Windows アーカイブ、展開しただけの AppDir / AppImage、murasaki dev は OS への関連付けを登録しません。

配信の仕様、テスト方法、信頼できない入力の扱いについては、Deep Link と File Associationを参照してください。

bundle

サーバー/Main のコードは本番向けにコンパイルされます。静的な bare npm import は自動的に検出・ステージングされます。実行時の挙動を静的に検出できない依存関係やアセットには、次のオプションを使用してください。

bundle: {
  external: ['computed-plugin'],
  noExternal: ['small-js-only-package'],
  resources: [
    'prisma/schema.prisma',
    { from: 'prisma/migrations', to: 'database/migrations' },
    { from: 'bin/indexer', to: 'sidecars/indexer', executable: true },
  ],
}
フィールド説明
externalstring[]?アプリの node_modules にパッケージをステージングします。動的に算出されるパッケージの読み込みをここに追加します。ネイティブアドオンや実行時データを持つパッケージには、こちらを優先してください。
noExternalstring[]?コンパイル済みのサーバーバンドルへ強制的に含めます。実行時アセットを持たない JS のみのパッケージ向けです。
resourcesArray<string | { from: string; to?: string; executable?: boolean }>?ファイルやディレクトリをパッケージ化されたリソースへコピーします。文字列で指定した場合はソースのベース名を使用し、オブジェクトで指定した場合は相対的な配置先を指定できます。アプリが所有する実行可能なサイドカーには必ず executable: true を付けてください。これにより、macOS / Windows の署名で外側のアーティファクトより先に封印されます。実行可能なディレクトリは拒否されます。

resources に秘密情報を置かないでください。アプリバンドル内のものはユーザーが読み取れます。ネイティブアドオンは、対象となるすべてのアーキテクチャでテストしてください。

plugins

defineMurasakiPlugin を使うと、信頼されたビルド時拡張機能を宣言できます。プラグインは murasaki.config.ts と同じ Node.js 権限で実行されるため、信頼できるコードだけをインストールしてください。

murasaki.config.ts
import { defineConfig, defineMurasakiPlugin } from 'murasaki'
import inspect from 'vite-plugin-inspect'

const assetsPlugin = defineMurasakiPlugin({
  name: 'acme.assets',
  vite: inspect(),
  bundle: {
    external: ['native-addon'],
    resources: [{ from: 'models', to: 'models' }],
  },
  hooks: {
    async before({ command, target, projectRoot, config }) {
      // dev / build / bundle の前にfileを生成・検査する。
    },
    async after(context) {
      // command成功後に宣言順で実行する。
    },
  },
})

export default defineConfig({
  appId: 'app.murasaki.example',
  productName: 'Murasaki App',
  plugins: [assetsPlugin],
})
フィールド説明
namestring安定した小文字の識別子(必須)。名前が重複すると設定の検証エラーになります。
vitePluginOption?Murasaki のコアプラグインの後に追加される Vite の拡張。ネストした配列や非同期のオプションは、Vite のセマンティクスに従います。
bundleBundleConfig?externalnoExternalresources をプラグインの宣言順に追加します。完全に重複するものは除去され、同じパッケージが両方にある場合は noExternal が優先されます。
hooks.before / hooks.after(context) => void | Promise<void>直列に実行される CLI フック。throw または reject するとコマンドが停止し、プラグイン名が表示されます。after はコマンド成功後にのみ実行されます。

フックのコンテキストには、プラグインオブジェクトを除いた深く凍結された設定のスナップショット、絶対パスの projectRootcommanddev / build / bundle)、そして bundle コマンド時の具体的な target が含まれます。プラグインオブジェクトや関数は murasaki-meta.json へシリアライズされません。

この SDK が拡張するのは ビルドパイプラインだけ です。ネイティブの Rust ABI、動的ライブラリローダー、レンダラー/ランタイムのプラグインサンドボックスではありません。ネイティブ機能は、引き続き Murasaki のネイティブホストとケイパビリティモデルに実装してください。

build

build: {
  before: 'pnpm --filter @acme/database build && pnpm prisma generate',
  envPrefix: ['MURASAKI_PUBLIC_', 'ACME_PUBLIC_'],
}
フィールド説明
beforestring?クライアントと Node のビルドの前に一度だけ実行されるシェルコマンド。終了コードが 0 以外だとパッケージングが停止します。ワークスペースの前提条件やコード生成に使用します。
envPrefixstring[]?レンダラーのコードに公開できる環境変数のプレフィックス。デフォルトは MURASAKI_PUBLIC_。プレフィックスを追加・置換したい場合にのみ指定します。

プレフィックスが付いた変数だけがクライアントに公開されますが、そこに秘密情報を置かないでください。Vite がその値を配布用の JavaScript に埋め込みます。

環境変数と.env

Murasaki CLI は、プロジェクトルートから次のファイルを自動的に読み込みます。後にあるファイルほど優先度が高く、ターミナルや CI からすでに渡されている環境変数は、すべての .env ファイルより優先されます。

.env
.env.local
.env.development          # murasaki dev
.env.development.local
.env.production           # build / bundle / installer
.env.production.local

レンダラーへ渡す値には、Murasaki 固有の MURASAKI_PUBLIC_ という名前空間を付け、import.meta.env から参照します。

.env.local
MURASAKI_PUBLIC_API_ORIGIN=https://api.example.com
ACCOUNT_API_TOKEN=keep-this-private
src/app/page.tsx
const apiOrigin = import.meta.env.MURASAKI_PUBLIC_API_ORIGIN

プレフィックスのない値は、レンダラーのバンドルには一切含まれません。murasaki.config.*、プラグインフック、Node Main、Server Actions、API Routes では、通常の Node の環境変数として参照できます。

src/main.ts
const token = process.env.ACCOUNT_API_TOKEN

MURASAKI_PUBLIC_ の値はビルド時に配布用の JavaScript へ埋め込まれるため、このプレフィックスを秘密情報には使用しないでください。パッケージ化された Node Main はランチャーの環境を継承しますが、Murasaki は .env ファイルをアプリへコピーしません。インストール済みアプリの秘密情報やエンドユーザー向けの実行時設定には、デプロイ環境、OS の認証情報ストア、secureStorage、または context.paths.data を使用してください。

security

Murasaki は、フレームワークのシェルとユーザー所有の index.html の両方に、環境ごとの Content Security Policy を 1 つ注入します。完全な置き換えを設定することも、明示的にオプトアウトすることもできます。

security: {
  csp: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: wss:; object-src 'none'; base-uri 'none'; frame-src 'none'",
},

// 別layerがpolicyを管理する場合のescape hatch:
// security: { csp: false },
動作
省略Murasaki の本番/開発それぞれのデフォルト値を使用します。
stringデフォルト値を完全に置き換えます。ディレクティブはマージされません。
falseフレームワークによる注入を無効化します。ユーザーが記述した CSP は削除されません。

index.html にすでに CSP の <meta http-equiv> タグがある場合、Murasaki はそのユーザー所有のポリシーを維持しつつ、スクリプトやリソースより先に適用されるよう <head> の先頭へ移動します。ポリシーは必ず 1 か所で管理してください。既存のタグと security.csp の文字列を併用すると、ビルドエラーになります。設定する値は、空でない 1 行の文字列に限られ、制御文字、二重引用符、<> は使用できません。デフォルト値、移行方法、meta 配信 CSP の制約については、セキュリティを参照してください。

updater

true は、通常の OSS アプリにとって完全に動作する設定です — GitHub リポジトリは package.jsonrepository フィールドから、公開鍵は .murasaki/update-key.pub から推論され、チャンネルはデフォルトで 'stable'、起動時に一度だけチェックします。オブジェクト形式では、これらのデフォルトに合わない部分だけを上書きすればよいです。

type UpdaterConfig =
  | boolean
  | {
      repo?: string                    // "owner/repo" — デフォルトは package.json#repository
      endpoint?: string                // セルフホストのマニフェスト URL — repo とは排他、https必須(loopback httpはローカルテスト用に許可)
      channel?: string                 // リリースチャンネル、デフォルト 'stable'
      checkOnStart?: boolean           // 起動時に一度チェック、デフォルト true
      checkInterval?: string | false   // 例 '6h' — タイマーで再チェック、デフォルト '6h'
      publicKey?: string               // base64 の Ed25519 公開鍵 — デフォルトは .murasaki/update-key.pub
      publicKeys?: string[]            // ローテーション用の追加pinned key(publicKeyと合わせて最大4つ)
      maxManifestAgeDays?: number      // この日数より古いmanifestを拒否、デフォルト90
      allowLegacyManifestsWithoutGeneratedAt?: boolean // migration用escape hatch、default false
    }

意図的に provider フィールドはありません — GitHub かセルフホストかは、repoendpoint のどちらが設定されているかから推論されるため、設定の他の部分とずれることがありません。また、署名検証を無効化する方法もありません。セルフホストの endpoint は、認証情報を含まない https: である必要があります(http: はループバックホスト — 127.0.0.1localhost[::1] — に対してのみ、ローカルテスト用に許可されます)。この制約は設定の読み込み時と、フェッチ時の両方で強制されます。リプレイ保護のため、generatedAt はデフォルトで必須です。レガシー向けの回避策は、古い署名済みマニフェストを移行する期間だけ有効にしてください。

checkOnStartcheckInterval は更新エンジン自身が処理するため、UI 側で check() を呼ばなくても機能します。useUpdate().check() を手動で呼ぶこともできます — チェックが実行中のときに二重に走ることはありません。

useUpdate()<UpdateButton />(どちらも murasaki からエクスポートされます)から利用されます。マニフェストの形式、署名、リリースの公開方法については、完全な自動更新ガイドを参照してください。

installer

macOS の DMG のスタイリングと、Windows NSIS / MSI インストーラーのオプションです。省略した場合は Murasaki のデフォルト値が使われます。

フィールド説明
backgroundstring?カスタム DMG 背景 PNG への(プロジェクトルートからの相対)パス。Murasaki のデフォルトを上書きします。
window{ width: number; height: number }?DMG ウィンドウのコンテンツサイズ(ポイント単位)。デフォルトは { width: 640, height: 420 }(デフォルトの背景に合わせています)。
iconSizenumber?DMG ウィンドウ内のアイコンサイズ。デフォルトは 128

installer.windows

フィールド説明
installMode'perUser' | 'perMachine'NSIS のインストールスコープ。デフォルトは perUser。MSI は常にマシン単位です。
publisherstring?インストーラーや「プログラムの追加と削除」の発行元。authorscopyrightproductName の順にフォールバックします。
upgradeCodestring?安定した MSI の GUID。デフォルトは appId に由来する決定的な値。リリース後は変更しないでください。
iconstring?インストーラー、アンインストーラー、「プログラムの追加と削除」用の .ico。デフォルトは生成済みのアプリアイコン。
bannerstring?ウィザードヘッダーの BMP。NSIS は 150×57、MSI は 493×58 を想定しています。
sidebarstring?ウェルカム/完了画面の BMP。NSIS は 164×314、MSI は 493×312 を想定しています。
licensestring?NSIS の .txt / .rtf、または MSI の .rtf 形式のライセンスファイル。

組み込みのアップデーターを有効にした Windows 配布では、意図的にユーザー単位の NSIS のみを使用します。MSI の生成はスキップされ、installMode: 'perMachine' は設定の読み込み時に拒否されます。MSI は updater を無効化し、MSI のメジャーアップグレードで管理する配布であれば引き続き利用できます。必要なプラットフォームのパッケージングツールからインストーラーが 1 つも生成されない場合、murasaki installer コマンドは失敗します。ポータブルな ZIP だけが必要な場合は murasaki bundle を使用してください。

sign

Murasaki はあなた自身の証明書または署名プロバイダーで署名し、独自の証明書は一切同梱しません。公証の認証情報と PFX のパスワードは、この設定ではなく常に環境変数から読み取ります — 詳しくはDistribution → Signingを参照してください。

macOS のフィールド

フィールド説明
identitystring?署名アイデンティティ、例: "Developer ID Application: Name (TEAMID)"。デフォルトは $MURASAKI_SIGN_IDENTITY、その次にキーチェーン内で最初に見つかった "Developer ID Application" のアイデンティティ。
entitlementsstring?メインのアプリ実行ファイル用のカスタム .plist。デフォルトでは systemPermissions から必要最小限のホスト権限を生成します。ファイルが存在しない、または無効な場合はビルドを停止します。
helperEntitlementsstring?同梱の Node ヘルパー用のカスタム .plist。デフォルトでは Node の JIT/ライブラリ読み込み権限を生成します。ファイルが存在しない、または無効な場合はビルドを停止します。
appSandboxboolean?予約済みです。現在の同梱 Node 構成では、true を fail-closed で拒否します。デフォルトの Hardened Runtime による署名を使用してください。デフォルトは false

sign.windows

murasaki bundle --sign --target win32-x64 は、ポータブル ZIP を作成する前にアプリの実行ファイルへ署名します。murasaki installer --sign --target win32-x64 は、生成された各インストーラー(NSIS と、アップデーターが無効な場合の MSI)にも署名し、すべての署名を Authenticode ポリシーで検証します。この処理には Windows と SignTool が必要です。

フィールド説明
certificateFilestring?PFX / P12 のパス。パスワードは $MURASAKI_WINDOWS_CERTIFICATE_PASSWORD からのみ読み取ります。
certificateSubjectNamestring?Windows の My ストアにインポート済みの証明書を、サブジェクト名で選択します。
certificateSha1string?My ストア内にある証明書の 40 文字のサムプリント。ファイル/サブジェクトによる選択とは排他的です。
certificateStore'currentUser' | 'localMachine'サブジェクト/サムプリント/自動選択の対象となるストア。デフォルトは currentUser
timestampUrlstring | falseRFC 3161 タイムスタンプ URL。false で無効化します。通常は DigiCert、Artifact Signing の場合は Microsoft のサービスがデフォルトです。
signToolPathstring?明示的な signtool.exe。未指定なら PATH と Windows SDK から探索します。
artifactSigning{ dlib: string; metadata: string }?Microsoft Artifact Signing のプロバイダーパス(Azure.CodeSigning.Dlib.dll と、秘密情報を含まないアカウント/プロファイルのメタデータ JSON)。証明書の選択方法とは排他的です。

すべての選択方法には CI 用の環境変数によるオーバーライドも用意されています。詳しくはWindows インストーラーと署名を参照してください。

次へ

GitHub でこのページを改善

On this page