Runbook

pending

by rudkodm

Execute code blocks directly from your notes using a persistent terminal session.

2 starsUpdated 1mo agoApache-2.0Discovered via Obsidian Unofficial Plugins
View on GitHub

Obsidian Runbook

Obsidian License Version

Turn Obsidian into an executable runbook for DevOps, SREs, and developers. Run code blocks, execute commands line by line, and debug scripts directly from your notes — with a real, stateful terminal session.

Features

  • 🖥️ Real terminal — Full xterm.js terminal with ANSI colors, interactive programs (vim, top, less), and tab management
  • 🐍 Multi-language — Shell (bash/zsh/sh), Python, JavaScript, and TypeScript
  • 🔄 Persistent state — Native interpreter sessions preserve variables across code blocks
  • 📓 Session isolation — Each note gets its own shell and interpreter sessions
  • ▶️ Run All — Execute an entire runbook sequentially with one command
  • 🏷️ Runme compatible — Portable code block annotations work in both Obsidian Runbook and Runme (VS Code)
  • ⚙️ Configurable — Custom interpreter paths, font sizes, and editor behavior

Table of Contents

Installation

Manual Install

  1. Download main.js, manifest.json, and styles.css from the latest release
  2. Create a folder: <your-vault>/.obsidian/plugins/runbook/
  3. Copy the three files into that folder
  4. Open Obsidian → SettingsCommunity Plugins → Enable Runbook

Build from Source

git clone https://github.com/rudkodm/obsidian-runbook.git
cd obsidian-runbook
npm install
npm run build

Then copy main.js, manifest.json, and styles.css to your vault's plugin directory, or set OBSIDIAN_PLUGINS_HOME and run:

npm run install-plugin

Quick Start

  1. Open any note in Obsidian
  2. Create a fenced code block with a supported language:
```bash
echo "Hello from Runbook!"
ls -la
```
  1. Place your cursor on a line and press Shift + Cmd + Enter (macOS) or Shift + Ctrl + Enter (Windows/Linux) to execute that line
  2. Or click the button on the code block to execute the entire block
  3. Output appears in the terminal panel at the bottom

Supported Languages

LanguageTagsExecution
Shellbash, sh, zsh, shellReal PTY session (default)
Pythonpython, pyPersistent REPL or one-shot
JavaScriptjavascript, jsPersistent Node.js REPL or one-shot
TypeScripttypescript, tsPersistent ts-node REPL or one-shot

Shell

```bash
echo "Current directory: $(pwd)"
for i in 1 2 3; do echo "Item $i"; done
```

Shell blocks run in a real PTY with full ANSI color support, interactive programs, and persistent state.

Python

```python
import pandas as pd
df = pd.DataFrame({"name": ["Alice", "Bob"], "score": [95, 87]})
print(df)
```

By default, Python blocks run in a persistent REPL — variables are preserved across blocks in the same note.

JavaScript

```javascript
const data = [1, 2, 3, 4, 5];
const sum = data.reduce((a, b) => a + b, 0);
console.log(`Sum: ${sum}`);
```

TypeScript

```typescript
interface User { name: string; age: number; }
const user: User = { name: "Dima", age: 30 };
console.log(user);
```

Code Block Annotations

Runbook supports Runme-compatible JSON annotations after the language tag:

```bash {"name": "setup", "cwd": "/tmp"}
echo "Running setup in /tmp"
```
AttributeTypeDefaultDescription
namestringCell identifier
cwdstringWorking directory for this block
excludeFromRunAllbooleanfalseSkip this block during Run All
interactivebooleantrueUse persistent REPL (false = one-shot execution)
interpreterstringOverride interpreter path for this block

Examples

Skip a block during Run All:

```bash {"excludeFromRunAll": true}
# This is for manual debugging only
kubectl port-forward svc/my-service 8080:80
```

Use a specific Python version:

```python {"interpreter": "python3.11"}
import sys
print(sys.version)
```

One-shot execution (no state preserved):

```python {"interactive": false}
print("This runs via python3 -c, no REPL state")
```

Frontmatter Configuration

Set document-level defaults using YAML frontmatter:

---
shell: /bin/zsh
cwd: ~/projects/my-app
---
KeyDescription
shellDefault shell for this document
cwdDefault working directory for all blocks

Per-block cwd annotations override the frontmatter value.

Interactive Interpreters

By default, non-shell code blocks run in persistent REPL sessions. This means variables, imports, and state are preserved across code blocks within the same note.

Block 1:

```python
x = 42
data = [1, 2, 3]
```

Block 2 (same note — x and data are still available):

```python
print(f"x = {x}, sum = {sum(data)}")
```

Each language gets its own interpreter session per note:

  • Shell blocks → PTY shell session
  • Python blocks → Python REPL
  • JS blocks → Node.js REPL
  • TS blocks → ts-node REPL

To disable persistent state for a specific block, use "interactive": false.

Session Isolation

Every note in your vault gets its own set of sessions. Commands in deploy-prod.md won't affect sessions in debug-api.md.

  • Sessions are created lazily on first execution
  • Terminal tabs show the note name for identification
  • Closing a note cleans up its sessions

Run All

Execute every code block in a note sequentially:

  1. Open Command Palette (Cmd/Ctrl + P)
  2. Run Runbook: Run all cells

Behavior:

  • Blocks execute in document order
  • Each block routes to the correct interpreter (shell, Python, JS, TS)
  • Blocks with excludeFromRunAll: true are skipped
  • Per-block cwd is respected
  • Execution stops on error

Terminal

The terminal panel uses xterm.js for a full-featured terminal experience:

  • ANSI 256-color supportls --color, syntax highlighting, etc.
  • Interactive programsvim, less, top, htop all work
  • Clickable URLs — Links in terminal output are clickable
  • Tab management — Multiple terminal tabs, rename, close
  • Resize — Terminal reflows on panel resize
  • Copy/paste — Standard OS shortcuts
  • Command history — Up/down arrows (per session)
  • Theme integration — Follows your Obsidian theme

Toggle the terminal: Cmd/Ctrl + PRunbook: Toggle terminal

Settings

SettingsCommunity PluginsRunbook

SettingDefaultDescription
Shell path$SHELL or /bin/bashDefault shell for terminal sessions
Python pathpython3Python interpreter path
Node.js pathnodeNode.js interpreter path
TypeScript pathnpx ts-nodeTypeScript interpreter path
Font size13Terminal font size
Auto-advance cursortrueMove cursor to next line after execution

Command Reference

CommandDefault HotkeyDescription
Execute line or selectionShift + Cmd/Ctrl + EnterRun current line or selected text
Run all cellsExecute all code blocks in the active note
Toggle terminalShow/hide the terminal panel
Start shell sessionStart a new shell session
Get session statusShow current session info
Restart shellRestart the active shell session

Runme Compatibility

Obsidian Runbook adopts the Runme code block annotation syntax. Runbooks authored in Obsidian Runbook can be opened and executed in Runme (VS Code) and vice versa.

Supported shared attributes: name, cwd, excludeFromRunAll, interactive, interpreter.

Security Considerations

This plugin executes code and commands in real terminal sessions on your system. This means:

  • File access is not limited to your vault. Commands can read, write, or delete any files your user account has access to.
  • Commands run with your permissions. The plugin does not sandbox execution — it runs as you.
  • Be careful with untrusted runbooks. Only execute code blocks from sources you trust.

This is by design — the plugin is meant for DevOps, SRE, and development workflows where full system access is necessary. If you need sandboxed execution, consider running Obsidian in a container or VM.

Known Limitations

  • Python compound statementsif/else, try/except, for/else blocks may not work correctly in the interactive REPL when split across indentation transitions. The REPL inserts blank lines between indent changes, which can prematurely terminate compound statements before else:, elif:, except:, or finally:. Wrap complex control flow in functions as a workaround.

  • JS/TS const redeclaration — Re-running a code block that declares const variables will fail because the REPL scope already has the binding. Use let or var for blocks you plan to re-run. This is a fundamental REPL limitation.

  • Desktop only — This plugin uses child_process and PTY sessions. It does not work on Obsidian Mobile.

Tech Stack

ComponentTechnology
LanguageTypeScript
Plugin APIObsidian API
EditorCodeMirror 6
Terminalxterm.js
PTYPython 3 pty module
Buildesbuild
TestingVitest

License

Apache-2.0

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.