Features
A
Markdown
Tzara reads a directory of markdown files and serves it as a wiki in your browser. Any [[wiki links]] resolve to other pages, pages can be embedded, there is support for Obsdian .canvas files, https://jsoncanvas.org/. An entire vault of markdown files can be viewed, edited, created, and managed from within the browser.
Tzara works seamlessly with Obsidian vaults. Your Obsidian notes are markdown files, so no conversion is needed.
Vaults are isolated collections of markdown files. Each vault has its own index, history, and graph. Searching for content in one vault only returns results from that vault. Tzara does have single vault that it designates as the system vault. This vault holds help pages, agent definitions, and editor definitions. These are all privileged markdown pages that you control, so by virtue of being the system vault, they are only ever human editable. See Agents and Editors below.
Inline Jupyter
Code blocks in your markdown can be made executable via a Jupyter server. The difference here is that interactive code is ephemeral. When inline code is run, a jupyter kernel is created on a page by page basis, and the kernel is killed after inactivity. Any executed code cells on a page can interact with one another as they share state. Output is rendered directly in the browser page.
There is partial support for ipywidgets. Custom ipywdiget styling is not supported. There is some support for anywidget, and this opens up interesting oportunities, though the learning curve is steeper than ipywidgets. There is support for Plotly, mpld3, and Matplotlib. Tqdm works.
All your plots, tables and computed values sit inline with the prose that explains them. Mathmatical notation is typeset with KaTeX wherever it appears in static markdown.
Git versioning
Each vault gets its own git history, kept separately from the vault itself so it does not interfere with whatever else you do with those files. Edits are committed as you make them, every page has a history view, and anything can be rolled back.
The utility of this is when something other than you makes changes to a page, such as agents running in the background. When an agent modifies a page they commit a pre-change version first, so any automated change is always a diff you can read and revert.
Convertzation with your notes
Your vault is indexed into PostgreSQL with pgvector, and a local model can answer questions by sourcing your own pages. Chat operates per vault, so it only answers with knowledge about that specific vault you're on. Your isolated notes stay isolated even when chatting about them.
Everything runs through a local inference server: Ollama by default, Lemonade, or any other server that supports OpenAI `v1/` calling convention. Only Ollama and Lemonade have been tested though. And all my development these days are with Lemonade.
The defaults are small enough to be work on CPU (llama3.2:3b
and embeddinggemma:300m), and you can point at something larger
whenever you have the hardware for it. I make no claims about the usability
of really small models. However, Tzara was built with them in mind, so a
lof stuff internally is there to work around small model limitations, such
as mangled function calls, and an inability to follow explict instructions.
They're doing the best that they can.
Agents
Background agents are markdown files in the system vault
(vaults/dada/agents/*.md). In Tzara, an agent is a prompt,
a set of granted capabilities, and optional human-authored Python tools. They can
run manually, on a schedule: - daily @ 4:30 pm,
2nd saturday, or a cron expression like 0 */4 * * *.
Alternatively, agents can run on an on: event trigger such as \
any agent failed or uploads in inbox/.
Schedules and triggers compose as OR, which means an agent can be triggerd
in multiple ways.
Writes are governed by a per-agent mode:. In propose mode
changes are staged for review at /agents, this is human in the loop. In
act-with-checkpoint they are applied with a pre-change commit as a checkpoint.
Event triggers carry loop guards: self-exclusion, a chain depth cap, per-agent cooldown and hourly
budget with deferred events waiting in a pool, and cycle detection at load time.
The agent scheduler and event triggers ship disabled. Set
AGENT_SCHEDULER_ENABLED=true and/or
EVENT_TRIGGERS_ENABLED=true in .env to turn them on once
you have read the authoring guide. Activity, staged proposals and recent events are
at /agents.
The system vault ships a few small example agents, all manual-run, so nothing fires until you ask it to: a vault-health reporter that finds orphaned pages and weak links, a daily NASA picture-of-the-day fetcher, a physics librarian and its companion citation finder, and a pair of RPG worldbuilding agents that demonstrate scheduled and event-driven runs chaining together.
Editors
Editors are custom /-menu commands that transform text while you write.
Like agents, each one is a markdown file in the system vault, so adding a command means
writing a page rather than patching the application. These are not "skills". An editor
is custom function that transforms some input text into something else where you
write your function with natural langange and also optionally python.
The shipped examples show a variety of different options: a cipher that encodes and decodes selected text, a research-notes command that finds related material in your vault and saves the references to a note, an Americanisms-to-British spelling pass, a TL;DR block generated from the whole document, and an equation-to-LaTeX converter for typesetting a selected expression.
The editing experience has a bunch of built-in /-menu commands. The
Editors feature allows you to easily extend these editing commands. Some of the built-in
commands allow you to take selected text and rewrite it to be longer or shorter,
convert prose into a table or a Mermaid diagram and vice versa. There is even a built-in
"prompt" command that allows you easily describe a transformation for any selected text.
For example, you could select some text and call /prompt, then say something
like "Change this to pirate speak! Arg!."
Themes
The whole interface recolors from four seed values - accent, background,
foreground and link colour. A theme is one theme.css file that overrides
those; every shade the wiki uses is derived from them at use time, including dark mode,
so a theme never drifts when the application changes.
Two worked examples ship alongside the default: ocean and sage.
Select one with TZARA_TEMPLATE in .env.
Any theme you create incorporates whatever is in the "default" theme if that file is missing from your customized version.
The services
What comes up when you start the stack:
| Service | Role |
|---|---|
tzaraserver | Starlette web app - the wiki UI and API |
tzaraworker | Taskiq background worker: indexing, git, agents, editors |
redisserver | Redis, backing Taskiq |
pgserver | PostgreSQL with pgvector, holding the RAG index |
ollamaserver | Local LLM server for chat and embeddings - or bring your own |
ollama-init | One-shot: pulls the default models on first up, then exits |
jupyterserver | Per-page Jupyter kernels for inline code execution |
jupyterserver-agent | Isolated kernel for agent and editor custom-tool code, with no vault mount |