- Install dependencies:
npm install
- Type-check:
npm run check
- Build the plugin:
npm run build
- Run tests:
npm test - Watch for plugin changes:
npm run dev
Galdur's host runtime is still Windows-only, but the plugin can optionally resolve and launch supported CLI tools through wsl.exe.
This is useful when:
- Obsidian is running on Windows
- The managed Galdur runtime is installed on Windows
- Your preferred AI CLI is installed inside a WSL distro instead of on native Windows
Behavior summary:
WSL modeis configured inSettings -> Galdur -> Runtime- The optional
WSL distrosetting maps towsl.exe --distribution <name> - The runtime process still runs on Windows
- The vault working directory and generated plugin file paths are translated to
/mnt/<drive>/...paths before launch - Context guard policy paths are also translated for Claude and Gemini when WSL mode is on
- Command resolution prefers native Linux paths inside WSL and intentionally ignores
/mnt/...mounted Windows shims
Use bumpp plus a small TypeScript post-step to keep plugin release metadata in sync:
npm run version:bump -- patch
npm run version:bump -- minor
npm run version:bump -- 0.6.0This updates:
package.jsonmanifest.jsonversions.jsonpackage-lock.json
bumpp handles package.json, manifest.json, and package-lock.json. A small TypeScript post-step then syncs the matching versions.json entry from the bumped plugin version and manifest.json's minAppVersion.
Galdur uses a managed local runtime process for PTY-backed terminal sessions.
In simple terms: the runtime is a small helper app that exists only to provide real terminal support. It is not an AI model, and it does not bundle Claude, Codex, or OpenCode.
- The Obsidian plugin handles UI, settings, install and update flows, and runtime lifecycle.
- PTY execution is delegated to a separate Windows runtime binary installed under the vault plugin folder at
bin/. - The plugin starts the runtime with a named pipe path and protocol version arguments, then sends an auth token through an environment variable.
- The plugin and runtime communicate over a newline-delimited JSON IPC protocol for commands such as
ping,spawn,write,resize, andkill. - The runtime owns
node-ptyand emits async session events back to the plugin over the same pipe.
When WSL mode is enabled, the runtime still hosts the PTY on Windows, but the spawned tool command is wrapped with wsl.exe. In practice, that means Galdur keeps one Windows-side runtime architecture while allowing the AI CLI itself to execute in a Linux userspace.
This split exists because Obsidian plugins run inside an Electron renderer process, while node-pty requires a real Node.js environment with native addon support.
Galdur includes a global tag-based context guard for Markdown notes.
In simple terms: the plugin reads Obsidian metadata for configured note tags, computes the set of matching vault-relative note paths at launch time, writes plugin-owned guard artifacts under vault/.obsidian/plugins/galdur/context-guard/, and appends any tool-specific guard arguments after the normal tool args.
Current behavior:
- The setting lives in
GaldurSettings.excludedNoteTags - Tags are normalized by trimming whitespace, stripping leading
#, and lowercasing - Only Markdown notes are evaluated
- Tag extraction uses Obsidian
metadataCache - If a note has no metadata cache entry yet, it is treated as included for that launch
Generated artifacts:
excluded-notes.json: Debugging and inspection artifact with normalized tags plus matched note pathsclaude-settings.json: Temporary Claude settings payload withpermissions.denyrules forRead(...)andEdit(...)gemini-policy.toml: Temporary Gemini policy rules for file-tool denies
Per-tool support:
- Claude: tool-enforced. Galdur appends
--settings <path>and writes deny rules for each matched note path. This does not fully block shell-based access. - Gemini: partial. Galdur appends
--policy <path>and writes deny rules for supported file tools. This does not fully block shell-based access. - Codex: advisory. No documented native path-deny surface is wired today, so Galdur surfaces the match count and warning in the startup banner only.
- OpenCode: advisory for the same reason.
Mitigation guidance:
- If a user depends on the context guard for sensitive content, they should verify which tool they are launching before starting a session.
- Claude is the only currently supported tool with enforced deny rules for tagged notes.
- Gemini should be treated as a partial guard only, because shell-capable workflows can still reach tagged files outside the blocked file-tool surface.
- Codex and OpenCode should be treated as visibility warnings, not privacy boundaries.
Launch plumbing:
TerminalViewresolves the guard state before orchestrationtoolSessionOrchestratorappendscontextGuard.toolArgsaftertool.buildArgs(...)- Guard args intentionally win over per-tool extra args
terminalMessages.writeStartupBanner()prints support level, excluded tag count, excluded note count, and a one-line support messageContextGuardStalenessMonitorwatches vault and metadata events during a live session, recomputes the excluded note set with a short debounce, and marks the session stale if that set changesterminalMessages.writeContextGuardStaleWarning()prints a restart-required warning, andTerminalViewdecorates the live status text withrestart required
This feature does not mutate vault-root project files such as .geminiignore, .claude/, or similar. All generated files stay inside the plugin folder. It also does not attempt filtered mirror workspaces in this iteration, because that approach complicates writes, new-file propagation, and shell behavior.
Important: The context guard is launch-time policy generation, not a replacement for a true sandbox.
Known limitation:
- The guard is metadata-driven. Newly created notes, retagged notes, or stale metadata may not be reflected until Obsidian updates
metadataCache. - Galdur can detect that the excluded note set changed after session start, but it cannot hot-reload Claude or Gemini policy into an already running CLI process.
- The reliable enforcement boundary is still session start. If guard-relevant tags change, restart the Galdur session.
The runtime build has two stages:
- Bundle
runtime/src/intoruntime/galdur-runtime.jswith esbuild. - Package that bundle into Windows executables with
@yao-pkg/pkg.
What ends up inside the runtime bundle:
- A packaged Node.js executable
- Galdur's runtime server code
- The staged
node-ptydependency and its native support files
What does not end up inside the runtime bundle:
- Claude Code CLI
- Codex CLI
- Gemini CLI
- OpenCode CLI
- Any model weights or remote AI service
Build commands:
npm run runtime:build:js
npm run runtime:build:exeArchitecture-specific builds:
npm run runtime:build:exe:x64
npm run runtime:build:exe:arm64WSL mode does not change runtime packaging. The managed runtime artifacts are still Windows executables because wsl.exe bridging happens at tool launch time, not in the runtime build.
Release artifacts expected by the plugin:
galdur-runtime-windows-x64.zipgaldur-runtime-windows-arm64.zipgaldur-runtime-checksums.txt
Plugin release artifacts:
main.jsmanifest.jsonversions.jsonstyles.cssgaldur-<version>.zip
Release tag contract:
- Git tags must match
manifest.jsonexactly, such as1.0.1 - The managed runtime installer downloads from the matching GitHub release tag
- BRAT-compatible release assets are
main.js,manifest.json,styles.css, andversions.json
If you want to test a locally built runtime inside a vault:
- Build the runtime zip artifacts in this repo:
npm run runtime:build:exe
- Copy the full
runtime/dist/folder into:YOUR_VAULT/.obsidian/plugins/galdur/runtime/dist/ - Open
Settings -> Galdur. - Use
Install local runtime (dev).
That copies the local runtime bundle into the managed install location and sets the runtime path override to the local build.
- The plugin bundle and the runtime are separate artifacts.
- The runtime still uses
node-pty, but it runs outside the main plugin process. - Runtime installation and updates are handled from inside the plugin settings UI.
- On Windows, Galdur currently forces
node-ptytowinptymode withuseConpty: falsefor compatibility with Obsidian's runtime environment. - WSL mode is an execution option for the AI CLI, not a native Linux host mode for the plugin runtime.
- The context guard is launch-time policy generation, not a replacement for a true sandbox.