This plugin allows you to execute code snippets in code blocks in your notes. The plugin adds a 'run' button for code blocks in supported languages. Clicking them results in the code of the block being executed locally. After the execution the result of the execution is shown. An interactive input element is created when your code snippets reads expects user input.
The result is shown only after the execution is finished. It is not possible to enter text on the command line into the executed program now.

The following languages are supported: C, C++, CSharp, Dart, F#, Golang, Groovy, Haskell, Java, JavaScript, Kotlin, Lean, Lua, Maxima, OCaml, Octave, Prolog, Python, R, Racket, Ruby, Rust, Scala, Shell (including Batch & Powershell), SQL, TypeScript, Wolfram Mathematica, Zig.
If you are new to MarkDown or Obsidian.md, you can go to the Quickstart Guide or take a look in to some blogs and videos that feature this plugin
Python, R, and Octave support embedded plots. All languages support "magic" commands that help you to access paths in obsidian or show images in your notes.
You can create code blocks that are executed before or after each code block of the same language and define global code injections.
New: You can enable persistent output to store the output of a code block in the note and export it to PDF.
Take a look at the changelog to see what has changed in recent versions.
Here you can find some other tools and plugins that are compatible with this plugin and might be useful for you.
If you like this plugin and use it a lot, please consider supporting me in continuing the development of this plugin. You can also sponsor a new feature or language integration directly, if you want to speed up the development for a specific feature you need.
In blogs:
Are you featuring this plugin in your content? Let me know and I will add it here.
function hello(name) {
console.log(`Hello ${name}!`);
}
hello("Bob")
npm install typescript -g and npm install ts-node -g. (-g means global installation)ts-node path in the settings to npx ts-node instead of ts-node.let message: string = 'Hello, World!';
console.log(message);
def hello(name):
print("Hello", name)
if __name__ == "__main__":
hello("Eve")
plt.show() is called.import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style("darkgrid")
iris = sns.load_dataset('iris')
sns.FacetGrid(iris, hue ="species", height = 5)
.map(plt.scatter, 'sepal_length', 'petal_length')
.add_legend()
plt.show()

hello <- function(name){
print(paste("Hello", name, sep = " "))
}
hello("Bob")
y = c(12, 15, 28, 17, 18)
x = 1:length(y)
plot(x, y, type="l")
#include <iostream>
#include <string>
using namespace std;
void hello(string name) {
cout << "Hello " << name << "!\n";
}
hello("Alice);
#include <iostream>
void main() {
std::cout << "Hello, World!" << std::endl;
}
#include <stdio.h>
printf("Hello, World!");
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Requirements: LaTeX distribution like MiKTeX or TeX Live is installed and the correct paths are set in the settings.
Injects default document class. Consider setting Crop to content.
\begin{document}
Hello World!
\end{document}
Set filename with \title{…}. Adds prefix figure to avoid file name collisions, group all generated files, and for appearance CSS selectors. Click run again will overwrite the file, and refresh its embeddings in the active view.
![[figure time of day.svg]]
\documentclass[border=2pt]{standalone} \title{time of day}
\usepackage{datetime2}
\begin{document}
The time is \DTMcurrenttime.
\end{document}
Include files relative to the vault's attachment folder. Consider listings for source code listings, markdown for inputting markdown files as LaTeX code, and \input{…} to paste plaintext or LaTeX source files.
Layout with graphbox for vertical alignment, or tabularray for more complex alignment.
\documentclass{standalone} \title{include_attachments}
\usepackage{graphicx}
\begin{document}
\includegraphics{figure time of day.pdf} \quad
\includegraphics{figure time of day.pdf}
\end{document}
For instance reference a label that appears later in the document. The plugin detects LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. during compilation and reruns until resolved.
\documentclass{article} \title{sum of two poisson distribution}
\usepackage{mathtools,amsfonts}
\begin{document}
As seen in \eqref{eq:poisson}, we use convolutions of probability distributions for two independent poisson distributed random variables.
\begin{align*} \MoveEqLeft
\mathbb{P}(X + Y = k) = \sum_{m = 0}^\infty \mathbb{P}(X = m)\, \mathbb{P}(X = m - k) \tag{1}\label{eq:poisson} \\&
= \sum_{m = 0}^k \frac{\lambda^m\, e^{-\lambda}}{m!} \cdot \frac{\mu^{k - m}\, e^{-\mu}}{(k - m)!} = \ldots
\end{align*}
\end{document}
Not all rerun requirements are easy to detect. Consider adding the package lastpage to force a rerun, by creating an unresolved reference.
\documentclass{article} \title{rerun sidenotes table}
\usepackage{sidenotes,tabularray,lipsum,lastpage}
\begin{document} \SetTblrInner{hlines}
\sidenotetext{This is a marginal note.} \lipsum[1][1-3]
\begin{table*}
\begin{tblr}[tall, caption={Expand table into page margins}]{X}
\lipsum[3][1-4]
\end{tblr}
\end{table*}
\end{document}
Explore more LaTeX examples, consult package documentations, or learn about LuaLaTeX.
dotnet tool install -g dotnet-script, then config dotnet-script fullpath.Console.WriteLine("Hello, World!");
void main() {
print("Hello World");
}
print('Hello, World!')
def main : IO Unit :=
IO.println s!"Hello, World!"
#eval main
echo "Hello World!"
ls -la
powershell to pwsh in the plugin settings. Make sure you set the right path.echo "Hello World!"

ECHO Hello World!
% query" in the code block like in the followinglikes(john, pizza).
likes(john, cheese).
likes(jane, beer).
% query
likes(john, X).
def hello(name){
println "Hello ${name}!"
}
def helloClosure = {
println "Hello ${it}!"
}
hello("Bob")
helloClosure "Bob"
go binary is available).package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
cargo binary is available).cargo-eval is installed. Install using cargo install cargo-eval.cargo-eval. Read
their documentation.fn main() {
println!("Hello World");
}
hello(name: String) {
println("Hello $name!")
}
hello("Bob")
-cloud as argument in the settings to use the Wolfram Cloud instead of the local installation.mySum:: Num a => a -> a -> a
mySum a b = a+b
println("Hello, World!")
"Hello, world!"
puts "Hello, World!"
<?php
echo "Hello, World!";
?>
exp(i*pi)
x = -10:0.1:10;
plot (x, sin(x));
(Thanks to Michael M. Tung for the code example.)
integrate(x,x);
plot2d(sin(x), [x,0,%pi]);
(Thanks to Michael M. Tung for the code example.)
print_endline "Hello, OCaml!"
print("Hello, world!")
Squiggle: For Squiggle support take a look at the Obsidian Squiggle plugin by @jqhoogland.
Magic commands are some meta commands that can be used in the code block. They are processed by the plugin before the source code is executed.
The following magic commands are supported:
@vault_path: Inserts the vault path as string (e.g. "/User/path/to/vault")@vault_url: Inserts the vault url as string. (e.g. "app://local/path/to/vault")@note_path: Inserts the note path as string (e.g. "/User/path/to/vault/Note.md")@note_url: Inserts the note url as string. (e.g. "app://local/path/to/vault/Note.md")@title: Inserts the note title as string.@show(ImagePath): Displays an image at the given path in the note.@show(ImagePath, Width, Height): Displays an image at the given path in the note.@show(ImagePath, Width, Height, Alignment[center|left|right]): Displays an image at the given path in the note.@html(HtmlSource): Displays HTML in the note@content: Inserts the html content of the note in the code block. (Here you find a nice example for the usage of this command.)(@show(...) and @html(...) are only supported for JavaScript and Python yet.)
(The old commands @note and @vault are still supported, but may be removed in the future.)
Examples for the magic commands with Python:
print("Vault path:", @vault_path)
print("Vault url:", @vault_url)
print("Note path:", @note_path)
print("Note url:", @note_url)
print("Note title:", @title)
@show("image.png")
@show("image.png", 100, 100)
@show("https://upload.wikimedia.org/wikipedia/commons/d/de/TestScreen_square.svg", 10%, 10%, "center")
@html("<h1>HTML Caption</h1>")
@html('''
<svg width="100%" height="100%" viewBox="0 0 600 600" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="300" cy="300" r="250" style="fill:peru;" />
<circle cx="200" cy="250" r="50" style="fill:black;" />
<circle cx="400" cy="250" r="50" style="fill:black;" />
<circle cx="190" cy="230" r="20" style="fill:white;" />
<circle cx="390" cy="230" r="20" style="fill:white;" />
<circle cx="250" cy="400" r="85" style="fill:saddlebrown;" />
<circle cx="350" cy="400" r="85" style="fill:saddlebrown;" />
<ellipse cx="300" cy="380" rx="50" ry="35" style="fill:black;" />
<ellipse cx="130" cy="100" rx="110" ry="70" style="fill:saddlebrown;"/>
<ellipse cx="470" cy="100" rx="110" ry="70" style="fill:saddlebrown;" />
</svg>
''')
Try it out yourself!

Adding run- before the language name in the code blocks (as in the example below) renders the code block in the preview already.
This allows you to execute the code in the preview.
```run-python
def hello(name):
print("Hello", name)
if __name__ == "__main__":
hello("Eve")
Code blocks support specifying additional arguments in the form {key='value', otherkey=['val1', 'val2']}. Add them to code blocks like so:
```python {label='my label'}
print('my labelled code block')
```
Sometimes it is helpful to have code that is executed before or after each other block of the same language. This plugin supports this in a few ways:
All languages have a 'global inject' option in the settings that allows defining code to be added to the top of every single code block on a per-language basis. Code reuse fully works with all languages, and all existing magic commands, including showing images, and inline plot outputs. This can be used to define e.g. often used functions or import your favourite packages or libraries.
You can specify the pre argument to create a block that is executed before each following code block:
```python {pre}
import pandas as pd
```
This code block is added before each python block you define below in the note and import the pandas package.
post blocks work the same way, but the code in post blocks is executed after your other code blocks.
Pre-/post-blocks will only apply to code blocks defined below them, and will only apply to code blocks from the same language.
You can also have a pre- and post-block at the same time by specifying {pre, post}
Note, the pre/post arguments are special in that you don't need to explicitly state a key/value pair, however you can do so if you wish:
{pre} is equivalent to {export='pre'}, {pre, post} is equivalent to {export=['pre', 'post']}.
You can label specific code blocks with the label='string' argument, then import them explicitly in other blocks with the import='string' or import=['string1', 'string2', ...] argument so they aren't automatically imported as with pre-/post-blocks:
```python {label='block 1'}
print('running block 1')
```
```python {label='block 2'}
print('running block 2')
```
```python {import=['block 1', 'block 2']}
print('should run block 1 and 2')
```
Labelled code blocks will be executed before the code block being run, however after global injects and pre blocks.
In case you want to manually ignore specific exports in a code block like pre / post / global exports, you can do so with the ignore argument that accepts either pre, post, global, an array of any of these 3, or all to ignore all exports:
```python {ignore='all'}
print('should not run any global injects or pre / post blocks')
```
```python {ignore=['global', 'pre']}
print('should not run any pre blocks or global injects')
```
A few languages (currently JS and Python) support Notebook Mode. If a language is using Notebook Mode (configurable in Settings), then all code blocks in a given file will execute in the same environment.
Variables functions, etc. defined in one code block will be available in other code blocks. Code blocks are executed on demand; the order of code blocks in the file does not affect the order in which they are executed:
```js
console.log(f)
```
```js
var f = 3;
```
Running the first code block, then the second, then the first again will give:
Uncaught ReferenceError: f is not defined
undefined
3
To manage the open runtimes for Notebook Mode, you can use the Open Code Runtime Management command in the command palette. From this sidebar window, you can stop kernels. Note: force-stopping requires taskkill on Windows and pkill on Unix. 99% of systems should have these preinstalled: if yours doesn't, please file an issue
Since version 2.0.0, the plugin supports persistent output. This means that the output of a code block is stored in the note and will be displayed when you open the note again. This is useful for long-running code blocks or code blocks that produce a lot of output. The output is stored in the note as a comment and will be displayed in the preview mode.
To enable this feature, you have to enable the setting Persistent Output in the plugin settings.
We recommend reopening open notes that contain code blocks after enabling this feature.
⚠ This feature is still experimental and may not work as expected in all cases! We recommend that you disable this feature if you encounter any problems.
This plugin supports customising styles using the Style Settings plugin or the Obsidian Code Styler plugin.
Take a look at the Obsidian Tools python package to find some useful tools for interacting with your vault.
Start by checking if the plugin is installed and activated. Continue by creating a code block in your preferred language. Check above to see if the language is supported.
Now you can switch from the preview mode to the rendered mode (where you can't edit the text anymore). Now, when you hover over the code block, you should see a button labeled "run". Click it!
If it didn't work and a warning appears (that is not related to a bug in your code), you probably need to set the correct execution part for the language (e.g., "C://User/YourName/anaconda/python.exe" or something like that). You can find instructions about how to find the right path below.
Now it works, great! Feel free to read or skim through the text above to learn more features you might like, for example persistent output or embedding of plots.
In your vault go to Settings > Community plugins > Browse and search for "Execute Code". Select the plugin, install it and activate it.
or
Follow this link and click "Open in Obsidian".
To avoid or resolve errors from an incorrect path.
('where' for Mac and Windows) --- (for Linux Users, replace 'where' with 'which')


Do not execute code from sources you don't know or code you don't understand. Executing code can cause irreparable damage.
.deb version of Obsidian. If your distro isn't compatible with .deb files, you may see issues.run button after switching the theme: Try to close and reopen your notes and wait for a few minutes. It seems like obsidian doesn't call the postprocessors after the theme switch.All contributions are welcome. Just create a merge request or email me: contact(at)tim-wibiral.de
The open issues are a good starting point to find something to work on. Some are marked as "good first issue" and are easier to solve.
Made with contrib.rocks.