Spiega documentation
- Knowledge sharing
- Portfolio
org files features
org-mode
org-mode from being a note taking tool has become a full featured project tool and turns text files into dynamic workflow systems. Org is so reach that we can run project management, create knowledge and presentations, compute, write technical documentation, reports and dashboards.
- portability
- ascii text files are lightweight and portable
- rich text
- much more expressive than markdown
- customizable
- you can define the execution and export of every single element
- sections
- are tasks, nodes, agenda points, work streams…
- data
you can define variable for every component of the file and pipe it to other blocks
- connected
- you can move sections between files, rename files and your nodes and agendas will stay connected
- schedule
- specify time (`SCHEDULED:`) and due dates (`DEADLINE:`)
- status and tags
- each section can have a current status and a tag for search
- code
- you can execute code with org-babel specifying output and permissions for any language
- links
- to files, nodes, tags, footnotes, commands
- export
- to blob posts, slides, images, animations
- minimal
- Can replace multiple tools (Note-taking, Calendar, Kanban board, Code editor, LaTeX writer, Blog).
It is the “Swiss Army Knife” of Emacs, but like any Swiss Army Knife, you must be willing to read the manual (often hundreds of pages of documentation) to unlock its potential. For a developer or researcher who wants a clean, text-based, code-integrated, and portable knowledge base, it is arguably the best tool available.
org files features
Org files are reach in metadata and can integrate with any tool making it’s function looks like more an operating system than anything else. Org files are reach in functions cheatsheet.
Few of the functions we can use for our projects:
org files allow a really expressive integration of information:
- agenda
- to schedule a task or to set an alert [C-c a] [C-c .]
- logbook
- the time spent on tasks
- tags
- to specify meta information for that section [C-c C-q]
- status
- whether an action is done or pending [Space - left/right arrow]
- trees
- explain hierarchical structures [::]
- nodes
- tag every element to create interconnections
- code
- define code to execute `#+begin_src bash` `#+end_src`
- graph
- interconnect elements
- plots
- plot data with gnuplot
- link
- link to anything: files, websites, buffers, images…
- webpage content
- show the text of a web page [eww]
- local org files
- open new buffers from shell
- roam
- organizes the org node information into graphs
- spreadsheet
- formulas on tables
And pipe all together as you like.
tags and status
For each section we can set tags and status, data and logbook. We can define at file level the tags we want to use in that file
#+TODO: active done crit milestone todo review knwoledge task #+TAGS: executive(e) present(p) hide(h) devops(o) dev(d) science(s) business(b) architecture(a) management(m)We can as well set some behavior for that specific file like how we want to visualize it, what variables should we run, what do we want to export
#+STARTUP: showall #+OPTIONS: tex:t #+PROPERTY: HEADER-ARGS+ :eval no-exportcode to graph
We run an example, we benchmark the speed of different local models. We run a model comparison script and use gnuplot to show the results.
We first call ollama endpoint to get the list of available models and extract the name of the model using commands like jq, grep and awk. code arguments
curl localhost:11434/api/tags | jq | grep \"model\" | awk -F " " '{print $2}'
| qwen3.6:latest | |
| dolphin-mistral:latest | |
| gemma4:latest | |
| deepseek-coder:6.7b | |
| llama3.2:latest | |
| qwen2.5-coder:3b | |
| qwen3.5:9b | |
| qwen2.5-coder:7b |
We then run a script to test the speed of each model and extract the token/s.
#echo $model_list
cd ~/lav/src/blender_twin/deploy/ollama/
#bash benchmark_models.sh
python3 benchmark_stats.py
plotting
Given the following table write a gnuplot function to be integrated in emacs org
| qwen3.6:latest | model | tokens_per_second | token_rate | time_rate |
| dolphin-mistral:latest | qwen3.5:9b | 20.711123 | 37.218987 | 18.767091 |
| gemma4:latest | qwen2.5-coder:3b | 86.646493 | 6.607947 | 0.975372 |
| deepseek-coder:6.7b | qwen3.6:latest | 9.434619 | 32.298511 | 37.218987 |
| llama3.2:latest | gemma4:latest | 31.166858 | 18.467557 | 11.391252 |
| qwen2.5-coder:3b | qwen2.5-coder:7b | 42.268118 | 9.068185 | 2.231556 |
| qwen3.5:9b | deepseek-coder:6.7b | 15.847756 | 8.54775 | 5.17094 |
| qwen2.5-coder:7b | dolphin-mistral:latest | 54.457944 | 10.850281 | 2.096758 |
Figure 1: gnuplot graph of model benchmark
I can subset a part of that table and sort it:
code piping
;;(setf sortedList (sort data #'< :key #'cadr))
;;(print sortedList)
(sort data)
| deepseek-coder:6.7b | 15.847756 |
| dolphin-mistral:latest | 54.457944 |
| gemma4:latest | 31.166858 |
| qwen2.5-coder:3b | 86.646493 |
| qwen2.5-coder:7b | 42.268118 |
| qwen3.5:9b | 20.711123 |
| qwen3.6:latest | 9.434619 |
reset
set boxwidth 0.9 relative
set xtics rotate by 15 offset -1.6,-1.2
plot data using 2:xtic(1) with boxes title 'token/s'
reset
set boxwidth 0.9 relative
set style data histograms
#set style histogram cluster
set style solid 2.0 border lt -1
set xtics rotate by 15 offset -1.6,-1.2
set tickslevel 0
plot data using 2:xtic(1) title 'token/s'
Or call the lisp version
(org-plot/gnuplot)
further graphs
reset session
$Data <<EOD
# viol0 viol1 viol2 viol3 viol4 viol5
0.24 -0.24 0.0 0.333 1.299 2.866
0.48 -0.16 1.0 0.599 0.849 0.600
0.28 -0.44 0.583 0.599 0.975 1.066
0.56 -0.28 0.500 0.666 0.799 0.933
0.52 -0.28 0.749 0.699 0.849 0.866
0.32 -0.56 0.083 0.566 0.774 0.733
EOD
set table $kdensity
plot for [i=0:5] $Data u i+1:(1) smooth kdensity bandwidth 0.15
unset table
set title 'violin plots'
set output "../../f/f_twin/violin.svg"
set border 3
unset key
set linetype 9 lc "#800072b2" ps 0.5 pt 5
set style boxplot nooutliers
set style fill solid border -1
set boxwidth 0.075
set errorbars lt black lw 1
set xrange [-0.5 :(6-0.5)]
set xtics nomirror
set yrange [-1:2]
set ytics nomirror
W = 0.025
plot for [i=0:5] $kdensity index i u (i + $2*W):1 w filledcurves x=i lt 9,\
for [i=0:5] '' index i u (i - $2*W):1 w filledcurves x=i lt 9,\
for [i=0:5] $Data u (i):i+1 w boxplot fc "white" lw 2
Figure 2: gnuplot graph of model benchmark
task tool integration math
Org files can integrate with many external programs and directly bind to their results.
gnuplot
We can use gnuplot to display functions
set title "Simple Plots" font "
set key left box
set samples 50
set style data points
plot [-10:10] sin(x),atan(x),cos(atan(x))
Figure 3: gnuplot graph
size(2cm);
draw(unitcircle);
music
We can create sheet music with lilypond
\version "2.24.4"
\relative c' {
g a b c
d e f g
g1
}
Figure 4: lilypond sheet music
links and nodes
We can define many types of links
- clickable command
- ‘elisp:‘ set key for gnuplot
- node
- ‘id:‘
- file
- ‘file:‘
- picture
- ‘file:‘
- node
- ‘id:‘
- search string within file
- code line
diagrams
Here we create a diagram using mermaid
---
title: implementation sketch
---
flowchart LR
KN["`
script
knowledge
agenda
links
tasks
`"]
DOC@{ shape: docs, label: "Knowledge"}
MC@{ shape: procs, label: "mcp server"}
DT@{ shape: lin-cyl, label: "storage" }
EL@{ shape: notch-pent, label: "ellama" }
GP@{ shape: notch-pent, label: "gptel" }
PI@{ shape: notch-pent, label: "pi-coding", pos: "c", w: 60, h: 60, constraint: "off" }
%%A@{ icon: "fa:user", form: "square", label: "User Icon", pos: "t", h: 60 }
E(emacs) --> GP
E --> EL
E -- ask --> EL
EL -- connect --> OL[\ollama\]
OL -- answer --> EL
EL -- insert --> E
GP -- connects --> MC
MC -- summarize --> DOC
GP -- decide --> JT[\vllm\]
JT -- elaborate --> GP
GP -- insert --> E
E -- debug --> PI
PI -- write --> DT
PI -- edit --> E
E -- edit --> OR[org-file]
OR -- contain --> KN
diagram results
Figure 5: diagram of the implementation
But we can use plantuml or graphviz
#+begin_src plantuml :exports both :file ../../f/f_twin/plantulm_dia.svg@startumlstart:initialize;repeat :do something;repeat while (finished?) is (no)->yes;stop@enduml#+end_src
todo agenda
Each section can be linked to a data by inserting an agenda entry [C-c .]. We can put:
- dates
- past dates
- date range
- effort
- C-c C-x e (org-set-effort)
- schedules
- SCHEDULED: - elisp:(org-schedule)
- deadlines
- DEADLINE: - elisp:(org-deadline)
- recurrent tasks
- pay the server DEADLINE:
- log activities
- elisp:(org-clock-in), elisp:(org-clock-out), elisp:(org-clock-in-last), elisp:(org-clock-report)
- timer
- elisp:(org-timer-start), elisp:(org-timer-set-timer), elisp:(org-timer-stop)
- todos
- elisp:(org-todo-list), elisp:(org-agenda-list-stuck-projects)
| Headline | Time |
|---|---|
| Total time | 0:00 |
Figure 6: org agenda
project management
From the agenda you can directly create a gantt
---
displayMode: compact
title: Ignored if specified in chart
config:
gantt:
useWidth: 800
rightPadding: 0
topAxis: true #false
numberSectionStyles: 2
---
gantt
dateFormat <YYYY-MM-DD>
title Knowledge base action plan
excludes weekends
review : vert, v1, <2026-06-22>, 1d
section local models
deploy LLMs :done, deploy, <2026-05-20>, 7d
coding agent :done, deploy, <2026-05-27>, 14d
section list & summarize
parse knowledge :done, dev, <2026-06-01>, 5d
create graphs :done, dev, <2026-06-07>, 7d
section hierarchy
hierarchy :done, distil, <2026-06-16>, 9d
visualization :crit, distil, <2026-06-20>, 4d
section video
sceencast :active, create, <2026-06-12>, 5d
animate text :active, create, <2026-06-17>, 9d
section publish
content :active, share, <2026-06-22>, 10d
publication :milestone, share, <2026-06-27>, 5d
Figure 7: Gantt representation of the project
Kanban
We can as well display the agenda items as a kanban
---
config:
kanban:
ticketBaseUrl: 'https://mermaidchart.atlassian.net/browse/#TICKET#'
---
kanban
Todo
[compare model serve]
docs[benchmark vllm, llama.cpp and ollama]
[In progress]
id6[blog posts about the local implementation ]
id9[Ready for deploy]
id8[cloud webdav]@{ assigned: 'bot1' }
id10[Ready for test]
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
id11[Done]
id5[agent confs, org files]
id2[local deployment]@{ ticket: MC-2036, priority: 'Very High'}
id3[graph integration]@{ ticket: MC-2037, assigned: bot1, priority: 'High' }
Figure 8: Kanban representation of the project
integral
We can solve math problems using the output of an LLM prompt: Solve the following integral ∫_0^1 x^2 dx
from sympy import symbols, integrate
x = symbols('x')
integral_value = integrate(x**2, (x, 0, 1))
print(integral_value)
None
1/3
The value of the integral \(\int_0^1 x^2 \, dx\) is \(\boxed{\frac{1}{3}}\).
\begin{equation} x=\sqrt{b} \end{equation}\[ \int_0^1 x^2 \, dx = \left[ \frac{x^3}{3} \right]_0^1 = \frac{1^3}{3} - \frac{0^3}{3} = \frac{1}{3} \]
Or \[\int_0^1 x dx \].
import sympy as sp
x = sp.symbols('x')
integral = sp.integrate(x, (x, 0, 1))
print(integral)
The output of this code is 1/2.
lisp
(*(/ 1920 4) 3)
1440
markup
We have multiple formatting options: [C-c C-x C-f] (org-emphasize)
- bold
- ‘*bold*’ bold
- italic
- ‘/italic/’ italic
- underline
- ‘_underlined_’ underlined
- verbatim
- ‘=verbatim=’
verbatim - code
- ‘~code~’
code - strike
- ‘+strike-through+’
strike - sup
- ‘x^2’ x^2 ( ‘#+OPTIONS: ^:{}’ to disable export)
- sub
- ‘x_2’ x_2
- symbols
- π Γ
- footnote
- ‘1’ first footnote1 elisp:(org-footnote-action)
- citations
- ‘[cite@spiega_tech]’ (??, ????) elisp:(org-cite-insert)
Here we have a verse
Here we have a quote
Here we center
Here is literal text
other example
exports and execution
We have few options for code blocks:
- :export
- [code,results,both,none,drawer]
- :results
- [output,replace,none]
- :var
- the name of the variable to be read by another code block
- :tangle
- the file where to write the source code
drawer is some information you can keep in the source without exporting or export it as <aside> speaker notes. It is important to include files with “#+INCLUDE: ” to add configuration to certain types of exports. :results output avoids the formatting of the output in tables.
(code, results, both, none, drawer)
macros
You can use macros to perform certain operations during export:
#+MACRO: gnustamp (eval (concat "GNU/" (capitalize $1))) {{{gnustamp(ciccia)}}}GNU/Ciccia
org has a set of predefined macros
{{{keyword(TITLE)}}} - {{{title}}} - {{{author}}} - {{{date}}} - {{{input-file}}} - {{{property(OPTIONS}}}Turn into: org files features - org files features - - - tmp.org - {{{property(OPTIONS}}}
variables
I can define variables env of code.
| 1 |
| 2 |
| 3 |
| 4 |
and read their content to another code block
(length table)
4
I can export this file as presentation and copy its result into the publishing folder:
;; (org-reveal-export-to-html)
(org-re-reveal-export-to-html)
agent_interview.html
echo $outF ${outF/.html/_slide.html}
| one | 1 | 2 | 3 | 4 | 5 |
| two | 6 | 7 | 8 | 9 | 10 |
return [[val + 10 for val in row] for row in tab]
| one | 11 | 12 | 13 | 14 | 15 |
| two | 16 | 17 | 18 | 19 | 20 |
- simple
- not
- nested
- list
(print x)
| simple | list |
argument
default value
setting1 1234
setting2 <<argsubst1()>>
spreadsheets
Within org files we can run formulas in tables. You can edit the formulas for that cell with `[C-c =]` or open the table in another buffer `[C-c ’]`. Debugger is `[C-c {]`
| file | tool | info | Mean |
|---|---|---|---|
| txt | 0 | 2 | 1 |
| md | 4 | 7 | 5 |
| org | 18 | 9 | 13 |
| Means | 7 | 6 | 6 |
piping software
I can define a data structure in the document
| source | quantity | link |
| code | 3k3 sources | src |
| tech | 120 blog posts | spiega |
| thoughts | 30 posts | scritti |
| science | 30 works | PhD |
| videos | 180 videos | viudi |
and read it from another code block.
return tab
| source | quantity | link |
| code | 3k3 sources | src |
| tech | 120 blog posts | spiega |
| thoughts | 30 posts | scritti |
| science | 30 works | PhD |
| videos | 180 videos | viudi |
return tab
| file | tool | info | Mean |
|---|---|---|---|
| txt | 0 | 2 | 1 |
| md | 4 | 7 | 5 |
| org | 18 | 9 | 13 |
import re
import pandas as pd
header = tab[0]
data = tab[1:]
df = pd.DataFrame(tab,columns=header)
return df
txt 0 2 1 0 txt 0 2 1 1 md 4 7 5 2 org 18 9 13
org-roam
Org-roam is a package which creates nodes out of files and sections and populates a database with all the knowledge information and create advanced representations with org-roam-ui and searchable information with elisp:org-roam-db-explore and run queries with
(org-roam-db-query [:select * :from nodes])
We can visualize and navigate the information
In 2d or 3d
markdown compatibility
We want to apply markdown compatibility for the org-roam by using the package md-roam which helps extending the knowledge base to old files but lacks some important features. Markdown are though a bit more universal.
\begin{tikzpicture}
\fill[yellow] (0,0) circle (3cm);
\end{tikzpicture}
Footnotes:
here is the footnote