一键导入
add-tauri-sidecar
How to bundle an external binary and its dylib dependencies with the Tauri app, patch rpaths, sign everything, and resolve the path at runtime
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
How to bundle an external binary and its dylib dependencies with the Tauri app, patch rpaths, sign everything, and resolve the path at runtime
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Experimental protocol for Deep Cuts research, prototypes, model evaluations, threshold tuning, ablations, metric comparisons, and claims about accuracy or quality. Use before running or interpreting experiments so bots preserve train/validation/test boundaries, avoid leakage, compare against baselines, and report results honestly.
Guidelines for creating, updating, reorganizing, and reviewing Deep Cuts documentation in the project wiki, including page taxonomy, lifecycle status, protected pages, proposal handling, and link verification.
Pattern for multi-agent collaboration sessions in the deep-cuts fam — forge-first coordination over the botfam substrate (Gitea issues/PRs as the coordination plane, the unified `botfam wait` wake loop, bare-actor worktrees), with IRC opt-in for design sprints, plus session-log conventions
Draft, structure, and finalize a Deep Cuts blog-series post so it conforms to the post template, house voice, and cross-post link rules. Use when writing, drafting, assembling, or editing a "Deep Cuts" blog post (the rlupi.com series), preparing a post for publishing, or adding front matter to one. Covers the template, front matter schema, voice, agent crediting, and the link linter.
Checklist and guide for adding a new analysis pass to the trait-based modular pipeline
Safe pattern for adding SQLite schema migrations in the deep-cuts Rust/rusqlite_migration stack
| name | add-tauri-sidecar |
| description | How to bundle an external binary and its dylib dependencies with the Tauri app, patch rpaths, sign everything, and resolve the path at runtime |
Sidecars are external executables bundled inside the .app and resolved at runtime. The project already uses this for llama-server and fpcalc. Follow the same pattern for any new binary.
Important: if the binary depends on dynamic libraries (
.dylib), there are extra macOS-specific steps around rpath patching and code signing. Read the full skill before starting.
Copy the binary to src-tauri/binaries/ with the target-triple suffix:
src-tauri/binaries/my-tool-aarch64-apple-darwin
chmod +x src-tauri/binaries/my-tool-aarch64-apple-darwin
If the binary links against .dylib files (check with otool -L my-tool), you must:
src-tauri/binaries/@rpath / @loader_path instead@loader_path/../Frameworks to the RPATH of every file so they find each other when Tauri bundles them into Contents/Frameworks/Use the helper script tools/bundle-llama-server.sh as a reference — it does all of this for llama-server. Create a similar script for your binary.
The key install_name_tool operations each file needs:
# Replace Homebrew lib rpath with @loader_path
install_name_tool -rpath "/opt/homebrew/opt/foo/lib" "@loader_path" "$file"
# Add Frameworks rpath so bundled app finds dylibs in Contents/Frameworks/
install_name_tool -add_rpath "@loader_path/../Frameworks" "$file"
# Patch any remaining absolute /opt/homebrew/... install names → @rpath
install_name_tool -change "/opt/homebrew/opt/foo/lib/libfoo.dylib" "@rpath/libfoo.dylib" "$file"
# Re-sign (required after any install_name_tool modification)
codesign --force --options runtime --sign "Developer ID Application: Roberto Lupi (83BHH8484C)" "$file"
tauri.conf.json"bundle": {
"externalBin": [
"binaries/my-tool"
],
"macOS": {
"frameworks": [
"binaries/libfoo.dylib",
"binaries/libbar.0.dylib"
]
}
}
Critical: dylib dependencies go in bundle.macOS.frameworks, not bundle.resources. The frameworks key places them in Contents/Frameworks/ inside the .app, which is the path that @loader_path/../Frameworks in the rpath resolves to. Using resources puts them in the wrong location and causes a crash at runtime.
The path in externalBin is without the target-triple suffix — Tauri appends it automatically at bundle time.
Do not use Tauri's Command::sidecar() API — this project resolves sidecar paths manually via AppHandle. Follow the pattern from src-tauri/src/llama.rs and src-tauri/src/acoustid.rs:
use tauri::{AppHandle, Manager};
use std::path::PathBuf;
fn get_my_tool_path(app: &AppHandle) -> Option<PathBuf> {
#[cfg(target_arch = "aarch64")]
const TARGET_ARCH: &str = "aarch64";
#[cfg(target_arch = "x86_64")]
const TARGET_ARCH: &str = "x86_64";
#[cfg(target_os = "macos")]
const TARGET_OS: &str = "apple-darwin";
#[cfg(target_os = "linux")]
const TARGET_OS: &str = "unknown-linux-gnu";
#[cfg(target_os = "windows")]
const TARGET_OS: &str = "pc-windows-msvc";
let triple = format!("{}-{}", TARGET_ARCH, TARGET_OS);
let filename = format!("my-tool-{}", triple);
// 1. Next to the executable — production .app where Tauri strips the triple suffix
if let Ok(exe_path) = std::env::current_exe() {
if let Some(exe_dir) = exe_path.parent() {
let p = exe_dir.join("my-tool"); // suffix-stripped name
if p.exists() { return Some(p); }
let p = exe_dir.join(&filename); // triple-suffixed name (fallback)
if p.exists() { return Some(p); }
}
}
// 2. Resource dir — alternate production layout
if let Ok(res_dir) = app.path().resource_dir() {
let p = res_dir.join("binaries").join(&filename);
if p.exists() { return Some(p); }
}
// 3. Dev paths relative to repo root (CARGO_MANIFEST_DIR points to src-tauri/)
let dev_paths = vec![
std::path::Path::new("src-tauri/binaries").join(&filename),
std::path::Path::new("binaries").join(&filename),
];
for p in dev_paths {
if p.exists() { return Some(p); }
}
None
}
Location 1 must come first. In a production
.app, the binary lives inContents/MacOS/next to the main executable. Checking the resource dir first causes a miss and the binary is never found.
Then spawn it:
let path = get_my_tool_path(app)
.ok_or_else(|| "my-tool binary not found".to_string())?;
let output = std::process::Command::new(&path)
.arg("--some-flag")
.output()
.map_err(|e| format!("Failed to run my-tool: {}", e))?;
If the binary comes from Homebrew, update tools/bundle-llama-server.sh (or create a sibling script) that:
install_name_toolRe-run the script after every brew upgrade of the relevant formula.
src-tauri/binaries/ with target-triple suffix, chmod +x.dylib dependencies in src-tauri/binaries/@loader_path/../Frameworks added to RPATH of binary and all dylibs/opt/homebrew/... install names patched to @rpath/...codesign --force --options runtimeexternalBin entry added to tauri.conf.jsonbundle.macOS.frameworks (NOT bundle.resources)cargo test --manifest-path src-tauri/Cargo.toml still passes