ショートカットの表記を Mac だけ「⌘」にする、バグ報告に OS と CPU の種類を添える、CPU に合った追加ファイルを落とす、といった場面では実行環境の情報が要ります。Tauri では OS Info プラグイン(os プラグイン)で、OS の種類・バージョン・CPU アーキテクチャ・ホスト名を JS からも Rust からも取得できます。つまずきやすいのは、hostname() だけが非同期で既定の権限に含まれない点と、arch() が CPU そのものではなく実行ファイルの種類を返す点です。
前提条件
npm run tauri add os
tauri add はパッケージの追加、lib.rs へのプラグインの登録、capabilities への os:default の追加をまとめて行います。os:default にはホスト名以外(platform / version / arch / family / type / exeExtension / locale)の権限が入っています。端末名には利用者の名前が入っていることも多いので、hostname() 用の os:allow-hostname は必要なときだけ自分で足します。
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"os:default",
"os:allow-hostname"
]
}
主な関数です。type() は platform() とほぼ同じ値なので省き、ロケールを返す locale() は システムの言語設定(ロケール)を取得する で扱います。
| 関数 | 戻り値の例 | 呼び方 | 必要な権限 |
|---|---|---|---|
platform() | "windows" / "macos" / "linux" / "ios" / "android" | 同期 | os:default |
version() | "10.0.26100"(形式は OS ごとに違う) | 同期 | os:default |
arch() | "x86_64" / "aarch64" | 同期 | os:default |
family() | "windows" / "unix" | 同期 | os:default |
exeExtension() / eol() | "exe" か "" / "\r\n" か "\n" | 同期 | os:default |
hostname() | "DESKTOP-AB12CD3" | 非同期 | os:allow-hostname |
1. フロントエンドから実装する (TypeScript)
同期の関数は最初の描画から使える
platform() などは、起動時にプラグインがページへ埋め込んだ値を読むだけなので、await も Rust との通信も要りません。モジュールの先頭で <html> 要素に印を付ければ、最初の描画から OS に合った見た目にできます。
import { platform } from '@tauri-apps/plugin-os';
const os = platform();
document.documentElement.dataset.os = os; // CSS で [data-os="macos"] のように出し分ける
// ショートカットの表記を OS に合わせる
export function shortcutLabel(key: string): string {
return os === 'macos' ? `⌘${key.toUpperCase()}` : `Ctrl+${key.toUpperCase()}`;
}
バグ報告用に環境情報をまとめる
hostname() だけは Rust 側へ問い合わせるので Promise を返します。拒否されても他の情報は送れるように、失敗を個別に受け止めます。アプリ自身と Tauri のバージョンは アプリと Tauri のバージョン番号を取得する と組み合わせます。
import { arch, hostname, platform, version } from '@tauri-apps/plugin-os';
export type EnvInfo = { os: string; osVersion: string; arch: string; host: string | null };
export async function collectEnvInfo(withHost: boolean): Promise<EnvInfo> {
let host: string | null = null;
if (withHost) {
try {
host = await hostname(); // os:allow-hostname が必要
} catch (e) {
console.warn('hostname を取得できません:', e);
}
}
return { os: platform(), osVersion: version(), arch: arch(), host };
}
CPU に合ったファイルを選ぶ
import { arch, platform } from '@tauri-apps/plugin-os';
const CPU_NAMES: Partial<Record<string, string>> = { x86_64: 'x64', aarch64: 'arm64' };
// 追加ツールの配布ファイルのうち、アプリと同じ OS・CPU 向けのものの名前を返す
export function toolAssetName(): string | null {
const cpu = CPU_NAMES[arch()];
if (!cpu) return null; // 32bit など配布していない組み合わせ
return `tool-${platform()}-${cpu}.zip`;
}
arch() が返すのは、アプリの実行ファイルがどの CPU 向けにビルドされたかです。Intel Mac 向けのビルドを Apple Silicon の Mac で動かすと(Rosetta 2 経由)x86_64 になり、x64 版を Windows on ARM で動かしても同じです。同じ種類の実行ファイルを選ぶ用途には正しく、CPU の本当の種類を表示する用途には向きません。
2. バックエンドから実装する (Rust)
Rust からは同じ関数を tauri_plugin_os::platform() のように直接呼べます。IPC を通らないので capabilities は関係なく、platform() と arch() は std::env::consts::OS / ARCH と同じ値です。自作コマンドでホスト名を返すと、os:allow-hostname による制限を経由しなくなる点には注意します。
OS によって存在しない API は、実行時の if ではなく #[cfg(target_os = "...")] で分けます。Dock のアイコンを隠す set_dock_visibility() は macOS 版の Tauri にしか無いので、if の中に書いても Windows ではコンパイルできません。
use serde::Serialize;
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct EnvReport {
os: &'static str,
os_version: String,
arch: &'static str,
hostname: String,
}
/// バグ報告用の環境情報を返す
#[tauri::command]
fn env_report() -> EnvReport {
EnvReport {
os: tauri_plugin_os::platform(),
os_version: tauri_plugin_os::version().to_string(),
arch: tauri_plugin_os::arch(),
hostname: tauri_plugin_os::hostname(),
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_os::init()) // JS の platform() などはこの登録で使えるようになる
.setup(|app| {
// 実行時の値はログや表示に使う
println!(
"{} {} ({})",
tauri_plugin_os::platform(),
tauri_plugin_os::version(),
tauri_plugin_os::arch()
);
// その OS にしか無い API はコンパイル時に分ける
#[cfg(target_os = "macos")]
app.set_dock_visibility(false);
Ok(())
})
.invoke_handler(tauri::generate_handler![env_report])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
import { invoke } from '@tauri-apps/api/core';
type EnvReport = { os: string; osVersion: string; arch: string; hostname: string };
const report = await invoke<EnvReport>('env_report');
console.log(report);
動作確認
npm run tauri dev で起動し、ボタンなどから collectEnvInfo(true) を呼んで結果を console.log すると、Windows 11(x64)では次のように出ます。
{ os: "windows", osVersion: "10.0.26100", arch: "x86_64", host: "DESKTOP-AB12CD3" }
capabilities から os:allow-hostname を外して再起動すると、host が null になり権限エラーの警告が出ます。
よくあるエラーと対処法
- 「os.hostname not allowed. Permissions associated with this command: os:allow-hostname」:
os:allow-hostnameを追加してtauri devを再起動します。リリースビルドでは「Command plugin:os|hostname not allowed by ACL」になります。 platform()でTypeErrorになる: プラグインが登録されておらず、埋め込まれるはずの値(window.__TAURI_OS_PLUGIN_INTERNALS__)がありません。lib.rsの.plugin(tauri_plugin_os::init())を確かめます(この状態でhostname()を呼ぶと「plugin os not found」)。開発サーバーの URL を普通のブラウザで開いたときも同じなので、Web と共用するコードでは@tauri-apps/api/coreのisTauri()で分岐します。- 「This comparison appears to be unintentional because the types 'OsType' and '"Darwin"' have no overlap.」: Tauri v1 の記事にある
type() === 'Darwin'です。v2 の値は'macos'のような小文字の名前です。 - Apple Silicon の Mac なのに
x86_64になる: Intel 向けのビルドが Rosetta 2 で動いています。Apple Silicon 向けか Universal のビルドを配布します。
OS ごとの違いと注意点
- Windows:
version()は"10.0.ビルド番号"です。Windows 11 も10.0のままなので、ビルド番号が 22000 以上かどうかで 10 と 11 を見分けます。 - macOS:
version()は製品バージョンを 3 つの数字で返します(15.6なら"15.6.0")。 - Linux:
version()はカーネルではなくディストリビューションの版で、Ubuntu 24.04 なら"24.4.0"になります。更新型のディストリビューションでは"Rolling Release"や"Unknown"もあり得るので、数値として扱うなら失敗時の分岐を用意します。 - 共通:
platform()とarch()はビルド時、version()は起動時に決まり、実行中に OS を更新しても変わりません。ホスト名は変更も重複もあり得るので、端末の識別には ハードウェア固有ID (UUID) を取得する を使います。 - 刻々と変わるメモリの量や CPU の使用率は os プラグインでは取れません。メモリ使用量を取得する と CPU 使用率を常時監視する を参照してください。
