Org mode is an Emacs major mode with a laundry-list of powerful features, one of which is Org Babel, the literate programming engine that is embedded within Org mode. Think of it as the polyglot jupyter notebook of Emacs, if you will.
I use Org mode for a significant proportion of everything that I do, both for work and for personal use. From simple notes in org-roam and README files in git repos, to workbooks and authoring blog posts, Org mode has my back. For me, it's Org Babel that brings unique value to Org mode. Like a Jupyter notebook, everything happens inline so there is no copying and pasting between editor and shell.
This blog post is written in Org mode and makes extensive use of inline code that gets evaluated using Org Babel. Let's take a tour of the things we can do from the comfort of our favourite text editor.
Shell commands
We define source blocks in org-mode using #+begin_src <language> and #+end_src markers.
Source blocks are executable inline, with the results added into the same org buffer. Here's an
example that uses the default shell.
Note: I'm showing the code fence markers in all the examples, but normally they don't get rendered.
#+begin_src sh
ls -lh
#+end_src| total | 504 | |||||||
| -rw-r–r– | 1 | donaldh | staff | 12K | 19 | Nov | 12:48 | index.org |
| -rw-r–r– | 1 | donaldh | staff | 13K | 15 | Sep | 14:32 | llm-routing.png |
| -rw-r–r– | 1 | donaldh | staff | 146K | 19 | Nov | 12:46 | ob-backends.png |
| -rw-r–r– | 1 | donaldh | staff | 4.6K | 13 | Sep | 00:10 | plantuml-net.png |
| -rw-r–r– | 1 | donaldh | staff | 13K | 13 | Sep | 00:10 | plantuml-yaml.png |
| -rw-r–r–@ | 1 | donaldh | staff | 2.8K | 19 | Nov | 12:07 | things-rr.svg |
| -rw-r–r– | 1 | donaldh | staff | 27K | 15 | Sep | 17:03 | wind-chart.png |
| -rw-r–r– | 1 | donaldh | staff | 13K | 13 | Sep | 00:09 | yaml-example.png |
Note: Org babel detects tabular looking output and formats it as an org table.
Source blocks can be evaluated on a remote host, by specifying a remote directory in TRAMP syntax. I use this extensively to capture command output from other hosts.
#+begin_src sh :dir "/ssh:tosh:net-next"
./tools/net/ynl/pyynl/cli.py --family rt-addr \
--json '{"ifa-index" : 1, "ifa-family": 2 }' \
--dump getaddr
#+end_src
[{'address': '127.0.0.1',
'cacheinfo': {'cstamp': 282,
'ifa-prefered': 4294967295,
'ifa-valid': 4294967295,
'tstamp': 282},
'flags': {'permanent'},
'ifa-family': 2,
'ifa-flags': {'permanent'},
'ifa-index': 1,
'ifa-prefixlen': 8,
'ifa-scope': 254,
'label': 'lo',
'local': '127.0.0.1'}]
Compiled languages
Compiled languages are also fair game for inline source blocks, assuming you have the language's compiler toolchain installed.
C code
#+begin_src C :includes "<stdio.h> <string.h>"
printf("Hello world!\n");
#+end_srcHello world!
Rust code
#+begin_src rust
println!("Hello world");
#+end_srcHello world
HTTP requests
It's the 21st century and there's a whole web out there so naturally you might want some
json-rpc. The :wrap parameter tells Org Babel how to enclose the results block.
#+header: :var name="ob-http"
#+header: :var password="secret"
#+begin_src http :select .json :wrap src json
POST http://httpbin.org/post
Content-Type: application/json
{
"auth": {
"name": "${name}",
"password": "${password}"
}
}
#+end_src{
"auth": {
"name": "ob-http",
"password": "secret"
}
}GraphViz diagrams
One of the babel languages that I use a lot is the GraphViz dot language. With the dot
notation, I find that there's often a lot of boilerplate required to achieve the desired style.
It's possible to define boilerplate in a separate source block and then include it inline in
other source blocks using the <<noweb>> syntax.
Here's a source block named dot-preamble that contains the boilerplate for a left-to-right
diagram:
#+name: dot-preamble
#+begin_src dot
pad=0.2
rankdir="LR"
ranksep=0.75
nodesep=0.25
splines=curved
node [fontname="Arial" fontsize=12 height=0.4 penwidth=0.2]
edge [arrowhead="normal" fontname="Arial" fontsize=12 penwidth=0.5 color="#666"]
#+end_src
And here's a dot source block that includes the <<dot-preamble>> boilerplate using the noweb
syntax.
#+name: graphviz
#+begin_src dot :file llm-routing.png :exports results :noweb yes
digraph llm_routing {
<<dot-preamble>>
r, llm1, llm2, llm3 [shape="rect" style=filled fillcolor="#dfd" color="#060" fontcolor="#060"]
in, out [style=filled fillcolor="#fee" color="#a00" fontcolor="#a00"]
in [label="In"]
r [label="LLM Call\nRouter"]
llm1 [label="LLM Call A"]
llm2 [label="LLM Call B"]
llm3 [label="LLM Call C"]
out [label="Out"]
in -> r
r -> llm1
r -> llm2 [style="dashed"]
r -> llm3 [style="dashed"]
llm1 -> out
llm2 -> out [style="dashed"]
llm3 -> out [style="dashed"]
}
#+end_srcThe result block for a GraphViz dot code block is an inline image element:
#+RESULTS: graphviz
[[file:llm-routing.png]]
SQL queries
Org Babel has great support for SQL source blocks which can either be run standalone or used as a named function to provide input to another source block. Here is an example that runs a SQL query against a named SQLite database.
#+begin_src sqlite :db "~/git/weather/weather.db" :
select datetime(max(time), 'unixepoch') as date, temp from weather
#+end_src"2025-09-15 15:05:11",15.7
Here is an example of where Org Babel shines for me — the ability to integrate source blocks that are written in different languages so that the output from one gets used as input for another.
The following SQL source block is run as a function to produce tabular data for the gnuplot
program shown in the next example. The #+name: header is used to give the block a name so that
it can be referenced from the gnuplot source block.
#+name: wind-dir-data
#+header: :db "~/git/weather/weather.db"
#+begin_src sql
select datetime(max(time), 'unixepoch') as date,
round(avg(speed), 0) as speed,
round(avg(dir), 0) as dir
from weather
where time > unixepoch() - 86400
group by cast(time / 864 as integer)
#+end_srcA gnuplot chart
Here we use Gnuplot to create a wind chart diagram. This wind chart uses the output from the SQL query as the data source for the plot.
#+header: :term "png size 1024,300"
#+begin_src gnuplot :var data=wind-dir-data :file wind-chart.png :noweb yes
<<plot-preamble>>
plot \
data using 1:2:(2000):($3) with arrows as 1 title "Direction", \
data using 1:2 smooth csplines title "Speed"
#+end_src
PlantUML diagrams
When writing design documents or user guides, I often turn to PlantUML to use the many diagram formats that it supports.
Here is an example of a YAML structure diagram:
#+begin_src plantuml :file plantuml-yaml.png
@startyaml
!theme plain
cable.drivers:
ipip+ipsec:
inner: ipip
outer: ipsec-transport
vxlan : vxlan.NewDriver
libreswan : libreswan.NewDriver
wireguard : wireguard.NewDriver
@endyaml
#+end_src
Or how about a network diagram?
#+begin_src plantuml :file plantuml-net.png :exports results
@startuml
nwdiag {
network dmz {
address = "192.168.0.0/24"
web01 [address = "192.168.0.1"];
web02 [address = "192.168.0.2"];
}
}
@enduml
#+end_src
And the rest
Here's all the Org Babel backends that are included in the Emacs distribution:

This has been a quick tour of the many ways I use Org Babel but I have barely scratched the surface of what Org Babel can be used for.