diff --git a/package.json b/package.json
index b5893a0ad..86f84a3db 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"dev": "vite",
"dev:web": "vite",
"build": "tsc && vite build",
+ "build:app": "yarn skills:build && tsc && vite build",
"compile": "tsc --noEmit",
"preview": "vite preview",
"tauri": "tauri",
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index b1f5bfd80..2c9d94105 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -311,6 +311,12 @@ pub fn run() {
match runtime::v8_engine::RuntimeEngine::new(skills_data_dir) {
Ok(engine) => {
engine.set_app_handle(app.handle().clone());
+
+ // Set resource directory for bundled skills (production builds)
+ if let Ok(resource_dir) = app.path().resource_dir() {
+ engine.set_resource_dir(resource_dir);
+ }
+
let engine = std::sync::Arc::new(engine);
// Wire the SkillRegistry into the SocketManager for MCP
diff --git a/src-tauri/src/runtime/v8_engine.rs b/src-tauri/src/runtime/v8_engine.rs
index 16110c347..d54d5f8b9 100644
--- a/src-tauri/src/runtime/v8_engine.rs
+++ b/src-tauri/src/runtime/v8_engine.rs
@@ -29,6 +29,8 @@ pub struct RuntimeEngine {
skills_data_dir: PathBuf,
/// Directory containing skill source files.
skills_source_dir: RwLock