Get AI summaries of any video or article — Sign up free
Excalidraw Scripting - How to Automate On-File-Open Actions in Obsidian thumbnail

Excalidraw Scripting - How to Automate On-File-Open Actions in Obsidian

5 min read

Based on Zsolt's Visual Personal Knowledge Management's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Use EA.getExcalidrawAPI to access Excalidraw’s published functions, then locate setActiveTool to control the active tool.

Briefing

Excalidraw Automate can trigger Excalidraw actions automatically when a drawing opens in Obsidian—such as switching to the hand tool on mobile or running an “autodraw for pen” style script—by wiring Excalidraw’s API hooks into Obsidian startup automation. The key move is using Excalidraw Automate’s on-file-open hook, then installing that hook at Obsidian launch so it’s ready before any drawing is opened.

The walkthrough starts with Obsidian’s developer console (Ctrl+Shift+I / Cmd+Option+I) and Excalidraw Automate’s shorthand variable (EA = ExcalidrawAutomate). Once the script attaches to the active drawing via EA.setView, the Excalidraw API becomes the control panel. From there, the process becomes a repeatable pattern: fetch the API (EA.getExcalidrawAPI), list available functions, and locate the one needed—such as setActiveTool. Because the API doesn’t make argument values obvious, the method relies on two “find it yourself” tricks: search the Excalidraw GitHub repository for setActiveTool usage to see the expected object shape, and query the current application state (API.getAppState) to confirm tool types (type: hand vs type: rectangle).

With the hand-tool behavior confirmed, the guide shifts to making it run automatically. In Excalidraw’s markdown front matter, an unload script can call EA.getExcalidrawAPI and then setActiveTool with {type: 'hand'}. To target mobile only, the script checks Obsidian’s app.mobile flag: if app.isMobile (or app.mobile in the transcript’s naming) is true, it switches tools; otherwise it can run a desktop alternative. Testing is done by opening the drawing from markdown view and verifying that the active tool changes immediately.

To avoid repeating this per drawing, the same logic is inserted into an Excalidraw template configured in Excalidraw’s plugin settings. New drawings inherit the front matter and therefore the unload script automatically. The transcript also warns about a common template pitfall: the template field can look filled due to a faint placeholder hint, so users should verify they can actually select the text before assuming the template file is truly applied.

For pen automation, the guide expands beyond unload scripts. It shows two ways to run Excalidraw scripts: (1) call them through Obsidian’s command system using app.commands.executeCommandById with the script’s command ID, and (2) use Excalidraw Automate’s on-file-open hook, which receives a data object and can execute logic whenever a file opens. A quick console.log test confirms the hook fires and provides file metadata.

The final step is making the hook persistent across restarts. Instead of relying on per-file front matter, the guide uses Templator to install the on-file-open hook at Obsidian startup. A startup template creates a script that waits for Excalidraw Automate to become available (a watchdog loop with up to 50 retries and short delays) to prevent race conditions. After restart, the developer console message confirms installation, and opening a drawing triggers the desired automation automatically—without manual setup each time.

Cornell Notes

Automation for Excalidraw in Obsidian hinges on two layers: Excalidraw Automate’s API/hook system and Obsidian/Templator startup wiring. First, tool switching is validated by calling Excalidraw’s setActiveTool via EA.getExcalidrawAPI, using API.getAppState to confirm tool types like {type: 'hand'}. Next, mobile-only behavior is implemented by checking app.mobile inside Excalidraw front matter scripts (unload scripts) or by embedding the logic into an Excalidraw template so new drawings inherit it. For broader automation—like running “autodraw for pen” scripts—the on-file-open hook is installed via Templator at startup, with a watchdog loop to avoid timing issues when plugins load. The result: actions fire automatically whenever drawings open.

How does someone discover which Excalidraw API function to call and what arguments it expects (e.g., for switching tools)?

The workflow is: (1) get the Excalidraw API object with EA.getExcalidrawAPI, (2) list available functions by inspecting the API object, and (3) locate the target function such as setActiveTool. To learn the argument format, search the Excalidraw GitHub repository for “setActiveTool” and look for how it’s called in code. Then test by passing an object like {type: 'hand'}. To verify the current tool, call API.getAppState and inspect app state for the active tool’s type (type: hand vs type: rectangle).

Why does the guide use API.getAppState, and what does it help confirm?

API.getAppState reveals the live application state, including the active tool. After switching tools manually (e.g., to rectangle), running getAppState shows type: rectangle; switching back to hand and running it again shows type: hand. That confirmation removes guesswork when setting setActiveTool and ensures the correct tool identifier is used.

How can the hand-tool switch be limited to mobile openings only?

The unload script in Excalidraw front matter includes a conditional on Obsidian’s mobile flag. The transcript uses app.mobile (accessed through app.* in the Obsidian API). The logic is: if app.mobile is true, call EA.getExcalidrawAPI and then setActiveTool with {type: 'hand'}. On desktop, the condition fails, so the hand-tool switch doesn’t run unless an alternate branch is provided.

What’s the difference between running a script via command execution and using the on-file-open hook?

Command execution uses Obsidian’s command system: app.commands.executeCommandById(scriptId) runs a named script (like set grid or autodraw for pen) when the command ID is provided. The on-file-open hook is event-driven: Excalidraw Automate exposes a hook such as on file open, and when installed, it runs whenever a drawing file opens. The hook can receive a data object (the transcript demonstrates console.log(data) to confirm it fires and to inspect metadata).

How does Templator make the on-file-open automation survive restarts?

A Templator startup template installs the hook at Obsidian launch. The startup script waits for Excalidraw Automate to exist (a watchdog loop that retries up to 50 times with short delays) to avoid race conditions where the hook would be set before EA is ready. Once EA is available, the script assigns the on-file-open hook to the desired function (e.g., executing set grid or other automation). After restarting and reloading Obsidian, opening a drawing triggers the hook automatically.

Review Questions

  1. When setActiveTool is called, how can you verify the correct tool identifier without relying on assumptions?
  2. What problem does the watchdog loop solve when installing the on-file-open hook at startup?
  3. How would you choose between app.commands.executeCommandById and the on-file-open hook for a new automation workflow?

Key Points

  1. 1

    Use EA.getExcalidrawAPI to access Excalidraw’s published functions, then locate setActiveTool to control the active tool.

  2. 2

    Confirm tool identifiers by inspecting API.getAppState, which exposes the active tool type (e.g., type: hand).

  3. 3

    Implement mobile-only behavior by checking Obsidian’s app.mobile flag inside Excalidraw front matter scripts.

  4. 4

    Avoid per-drawing repetition by placing the unload logic into an Excalidraw template configured in the plugin settings.

  5. 5

    Run Excalidraw scripts either via Obsidian command execution (app.commands.executeCommandById) or by installing Excalidraw Automate’s on-file-open hook.

  6. 6

    Install the on-file-open hook at startup using Templator, and use a retry/watchdog loop to handle plugin load order.

  7. 7

    Test hook installation by restarting Obsidian, checking the developer console for confirmation, then opening a drawing to confirm the automation fires.

Highlights

Switching to the hand tool is done by calling setActiveTool with an object like {type: 'hand'} through EA.getExcalidrawAPI.
API.getAppState provides the authoritative active tool type, making tool selection verifiable rather than guesswork.
Mobile-only automation can be gated with Obsidian’s app.mobile flag inside Excalidraw front matter scripts.
The on-file-open hook turns “run once” scripts into “run whenever a drawing opens” behavior.
Templator startup templates plus a watchdog loop make the hook reliable across restarts despite plugin load timing.

Topics

  • Excalidraw Automate
  • Obsidian Scripting
  • Mobile Tool Switching
  • On-File-Open Hooks
  • Templator Startup Automation