asopi tech
asopi techIndie Developer
nimino-pack でサイトをデスクトップアプリにする:ビルドから配布まで

【2026年8月版】

nimino-pack でサイトをデスクトップアプリにする:ビルドから配布まで

公開日: 2026/08/18
読了時間: 約 17分

Nimino は、Nim で Web UI のデスクトップアプリを作るための基盤です。以前の記事で開発開始をお知らせしました。この記事では、最新のリリースである v0.2.9 の手順を扱います。

今回はその中の nimino-pack を使います。URL を渡すと、そのサイトを独立したウィンドウで開くアプリにするツールです。ブラウザのタブもアドレスバーもない、専用のアプリになります。

まず手元で動かし、そのあとで配布用のインストーラを作ります。

環境と前提

次の環境で確認しました。

項目バージョン
Niminov0.2.9
Nim / Nimble2.2.10 / 0.22.2
nimino-pack の実行環境Debian 13
WebView(Linux)GTK 4.18.6 / WebKitGTK 2.52.5
WebView(Windows)WebView2 Evergreen Runtime 151.0.4129.86

Nimino のアプリは OS の WebView を使うため、動かす環境には WebView が必ず要ります。用意の仕方は OS ごとに違います。

Linux では GTK 4 と WebKitGTK 6.0 を入れます。Debian 13 と Ubuntu では次の二つです。

sudo apt install libgtk-4-1 libwebkitgtk-6.0-4

Fedora なら gtk4webkitgtk6.0、CentOS Stream 10 や RHEL 10 では webkitgtk6.0 が EPEL にあるため、先に EPEL を有効にします。WebKitGTK 6.0 を持たない EL9 は対象外です。

Windows の WebView2 Evergreen Runtime は Windows 11 に標準で入っています。未導入の環境でも、生成したインストーラが実行時に確認して取得します。

macOS は Cocoa と WKWebView を使い、.app.dmg の生成も実装されています。ただし署名と公証には Apple の開発者資格情報が必要で、署名なしのビルドでは Gatekeeper に阻まれます。この記事では扱いません。手元の環境が macOS だけの場合、以降の手順はそのままでは進められません。

配布物を作る段には、これに加えて形式ごとの生成ツールが要ります。dpkg-debdesktop-file-validatemakensis といったもので、揃っていなければ何が足りないかを言って止まります。

nimino package-linux: Linux package generation requires desktop-file-validate in the Docker image

これらを個別に入れる代わりに、公開されているコンテナイメージを使えます。nimino と生成ツールが同梱されています。配布の節で実際に使います。

まず出来合いのアプリを試す

自分で URL からアプリを作る前に、出来上がったものを見ておきます。Releases に YouTube、Gmail、Google Analytics のインストーラを置いてあります。それぞれ Linux 向けの .deb.rpm、Windows 向けの -setup.exe.msi があります。

Debian や Ubuntu なら .deb を落として入れます。配布物には SHA256SUMS が付いているので、一緒に落とせば中身を検証できます。

依存は宣言されているので、GTK と WebKitGTK は apt が入れます。

配布物を落として検証する
宣言された依存は GTK と WebKitGTK の二つで、チェックサムも一致する

落とした .debapt で入れます。

sudo apt install ./youtube-com.nimino.youtube-com_0.2.9_amd64.deb

インストールするとアプリケーションメニューに YouTube が並びます。起動すると、タブもアドレスバーもないウィンドウで YouTube が開きます。中身は /opt/nimino/com.nimino.youtube-com/ に入っていて、これから作るバンドルと同じ構成です。

Windows 向けの -setup.exe は管理者権限なしで入り、スタートメニューに登録されます。

ここから先は、これと同じものを自分の好きな URL で作ります。

インストールする

パッケージ名でインストールします。Nim の公式パッケージ索引に登録されています。

nimble でインストールする
~/.nimble/bin に nimino と nimino-host の二つが入る

nimino コマンドと一緒に nimino-host が入ります。あとで作るアプリは、これを実行本体として同梱します。

nimino~/.nimble/bin に入ります。このディレクトリが PATH にあれば、そのまま呼べます。

export PATH="$HOME/.nimble/bin:$PATH"

Nim を入れたくない場合は、コンテナイメージが公開されています。nimino コマンドと、配布物を作るときに要る生成ツールが入っています。

docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/work" \
  ghcr.io/asopitech-labs/nimino:latest \
  pack https://asopi.tech --name AsopiTech --out /work/dist/app

--user は自分のユーザーIDを渡しています。コンテナが書いたファイルの所有者がこれで決まるため、指定しないと自分のディレクトリに消せないファイルが残ります。

このイメージは197MBで、Nim のコンパイラもクロスコンパイル用のツールチェインも入っていません。nimino の実行に要るものだけが入っています。

リポジトリを clone して開発用コンテナに入る方法もあります。Nim のコンパイラごと揃うため、Nimino 自体を改造する場合はこちらです。

git clone https://github.com/asopitech-labs/nimino.git
cd nimino
make shell

このコンテナは、リポジトリを /workspace にマウントして、あなたと同じユーザーで動きます。コンテナの中でビルドしたファイルは、ホスト側でもあなたの所有物になるため、消すのに sudo は要りません。

どのサブコマンドがあるかは --help で確認できます。

nimino --help
usage: nimino pack <manifest.toml> [--out <directory>] [--host <executable>]
       nimino pack --config <manifest.toml|config.json> [--out <directory>] ...
       nimino pack <url-or-local-path> [--use-local-file] [--name <name>] ...
       nimino package-linux <bundle> --format <deb|rpm|appimage|flatpak|zst> ...
       nimino package-windows <bundle> --format <nsis|msi> --out <directory> ...
       nimino package-macos <bundle> [--format <app|dmg>] --out <directory> ...

pack がアプリを作り、package-linux などがそこから配布物を作ります。pack の行が長いのは、ウィンドウサイズ、ユーザーエージェント、プロキシ、ダークモード、システムトレイなどをすべてコマンドラインから指定できるためです。

手元で動かす

ここでは asopi.tech をアプリにします。URL と名前と出力先を渡すだけで、出力先には12個のファイルができます。

URL からアプリを作る
URL から名前・識別子・アイコン・起動スクリプトがすべて導出される

指定したのは URL と名前と出力先の三つだけです。それ以外はすべて URL から導出されています。実行本体の nimino-host も、インストール時に置かれたものが自動で同梱されます。

run-nimino.sh を実行すると、asopi.tech が独立したウィンドウで開きます。

./dist/app/run-nimino.sh

起動スクリプトの中身は三行で、ホストにマニフェストのパスを渡しているだけです。サイト固有のロジックはどこにもありません。

#!/bin/sh
# Generated by nimino-pack.
exec "$(dirname "$0")/nimino-host" --manifest "$(dirname "$0")/nimino-manifest.json" "$@"

アプリの挙動はすべて nimino-manifest.json に書かれています。包み直さなくても、このファイルを編集すれば設定を変えられます。

何が生成されたのか

マニフェストの先頭を見ると、URL から何が導かれたか分かります。

head -12 dist/app/nimino-manifest.json
{
  "name": "AsopiTech",
  "id": "com.nimino.asopi-tech.asopitech",
  "url": "https://asopi.tech",
  "localEntry": "",
  "icon": "favicon.ico",
  "profile": "default",
  "package": {
    "version": "0.1.0",
    "description": "AsopiTech web application",
    "publisher": "Nimino",
    "homepage": "https://asopi.tech",

ホスト名から逆DNS形式のアプリID、説明文、ウィンドウ既定値、パッケージメタデータが作られます。サイトごとの定義ファイルを書く必要はありません。

favicon.ico--icon を省略したときに https://<host>/favicon.ico から取得したものです。取得できない場合は警告を出して先へ進み、アイコンなしのアプリができます。

ウィンドウの設定を変える

ウィンドウサイズやトレイ常駐は、コマンドラインから指定できます。

nimino pack https://asopi.tech --name AsopiTech --out dist/app \
  --width 1280 --height 900 --hide-on-close --show-system-tray

指定が増えてきたら TOML に移せます。ここまでのオプションを書き出すと次のようになります。

app.toml
name = "AsopiTech"
id = "com.nimino.asopi-tech"
url = "https://asopi.tech"

[window]
width = 1280
height = 900

[runtime]
show-system-tray = true
hide-on-close = true

このファイルを --config で渡すと、先ほどのコマンドラインと同じアプリができます。

nimino pack --config app.toml --out dist/app

値はそれぞれ検証され、version は SemVer、homepage は HTTP(S) URL、categories は Desktop Entry の許可値です。

Pake 形式の JSON もそのまま読めます。Pake から移行する場合、設定を書き直さずに済みます。

設定を間違えたときの挙動

nimino-pack は設定を黙って捨てず、誤りがあれば終了コードを返して止まります。CI に組み込むときの前提になるので、代表的な三つを見ておきます。

存在しないオプションを渡すと、usage を表示して終了コード2になります。

存在しないオプションを渡したとき
引数の誤りは usage の表示と終了コード2で知らせる

存在しないローカルパスを渡した場合も止まります。ここで https://./no-such-dir のように URL へ読み替えることはしません。

nimino pack: local source path does not exist
exit=1

--out を付けずに実行すると、アプリを作らずに検証済みマニフェストを標準出力へ返します。設定だけを確認したいときに使えます。さらに CI へ組み込む場合は --json を付けると、生成物のパスが一行の JSON で返ります。

nimino pack https://example.com --out dist/app --json
{"manifest":"dist/app/nimino-manifest.json","directory":"dist/app","localEntry":"","artifacts":[]}

マニフェストの全項目と各オプションの適用先は nimino-pack の API ドキュメントにまとまっています。

配布する

ここまでは手元で動かす話でしたが、他の人へ配るならインストーラを作ります。

ここからは形式ごとの生成ツールが要ります。個別に入れる代わりに、先ほどのコンテナイメージを使います。dpkg-debmakensis も入っています。

Linux 向けの .deb を作ります。--maintainer の指定は必須です。

docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/work" \
  ghcr.io/asopitech-labs/nimino:latest \
  package-linux /work/dist/app --format deb --out /work/dist/packages \
  --arch amd64 --maintainer "Asopi <dev@example.invalid>"

dpkg-debdesktop-file-validate をホストに入れてあるなら、コンテナを介さず nimino を直接呼べます。次の録画はコンテナの中で実行したものですが、ホストでも同じコマンドです。

nimino package-linux dist/app --format deb --out dist/packages \
  --arch amd64 --maintainer 'Asopi <dev@example.invalid>'

.deb には GTK と WebKitGTK への依存が宣言されます。

バンドルから .deb を作る
dpkg-deb で見ると GTK と WebKitGTK が依存として並ぶ

出来上がった .deb を自分の環境へ入れてみます。宣言された依存は apt が解決するため、GTK と WebKitGTK を自分で入れる必要はありません。

sudo apt install ./dist/packages/*.deb

これで、記事の最初に試した YouTube のアプリと同じものが、自分で指定した URL で手に入ります。

Windows 向けのインストーラも Linux 上で作れます。NSIS も wixl も Linux のツールだからです。

docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/work" \
  ghcr.io/asopitech-labs/nimino:latest \
  pack https://asopi.tech --name AsopiTech --out /work/dist/win --targets nsis

makensisunzip がホストにあるなら、これも直接呼べます。ただし --out には "$PWD/dist/win" のように絶対パスを渡します。NSIS はスクリプトに書かれたパスを自身の作業ディレクトリから解決するため、相対パスだとバンドルを見つけられません。

Linux 上で Windows 向けインストーラを作る
Windows 向けのランタイムを取得し、NSIS のインストーラを生成する

Windows 向けのランタイムは自動で取得されます。--targetsnsismsi を指定すると、必要なホストがどのプラットフォームのものか決まるためです。取得したものはキャッシュされ、二回目以降は再取得しません。

生成された .exe を Windows 機で実行すると、管理者権限なしで %LOCALAPPDATA%\Nimino\<id> に入ります。スタートメニューにショートカットが登録され、「アプリと機能」からアンインストールできます。

package-linuxpackage-windows には、バンドルと出力先を絶対パスで渡します。相対パスを渡すと、生成された .nsi の中でバンドルを解決できずに失敗します。

まとめ

ここまでで、URL ひとつからデスクトップアプリを作り、ウィンドウの挙動を変え、配布用のインストーラまで作りました。

手元で試すだけなら、公開されているコンテナイメージに URL を渡し、生成された run-nimino.sh を実行するだけです。Nim も生成ツールも入れる必要はありません。

包む対象はサービスのサイトに限りません。ブラウザで動くゲームや、よく開くツール、社内の管理画面を包めば、タブを探さずにアイコンから起動できます。ウィンドウサイズを決め打ちにすれば、毎回大きさを直す手間もなくなります。

私たちは、普段使っているサイトを軽いウィンドウで開けるようにするために Nimino を作っています。遊びでも仕事でも、好きなサイトを包んで使ってもらえたらうれしいです。

Nimino は2026年7月22日の v0.1.0 から1か月弱で v0.2.9 まで、19回リリースしています。手順が変わることがあるので、手元で試すときはタグを固定します。この記事の手順もすべて v0.2.9 で通しました。

参考リンク