Hamish2 downloadsRun a council of LLM value agents over your journal to surface decisions you have not made. Local-first via Ollama, OpenRouter, or any OpenAI-compatible endpoint.
Repository: https://github.com/Slaymish/Synod
A council of LLM "value agents" reads your journal, surfaces tensions you haven't resolved, and never suggests compromises. Runs entirely inside Obsidian; LLMs are reached via local Ollama, OpenRouter, or any OpenAI-compatible endpoint (e.g. llama-swap).
╭─────────────────────╮ ╭──────────────────╮ ╭────────────────╮
│ Import journal │────▶│ Per-value agent │────▶│ Compiler │
│ (Rosebud / vault │ │ (parallel, fully │ │ (3 passes) │
│ folder / journals) │ │ isolated) │ │ │
╰─────────────────────╯ ╰──────────────────╯ ╰────────┬───────╯
│
▼
╭──────────────────────╮
│ Bulletin (.md in │
│ vault) + side panel │
│ status │
╰──────────────────────╯
Pick from the Import journal entries command (or the Import entries button in the side panel). Each importer remembers its own folder / date-format settings between runs, and the modal opens on whichever importer you used last:
| Importer | Source | Use when… |
|---|---|---|
rosebud |
Rosebud .md or .zip export |
You're migrating off Rosebud. |
obsidian-folder |
Any folder of markdown notes | Your journal is free-form notes. |
obsidian-journal |
Obsidian Journals / Daily Notes | Filenames are dates (YYYY-MM-DD). |
The Rosebud picker also accepts drag-and-drop. Imports are deduped on SHA-256 of the normalised user text, so re-running an import never creates phantom duplicates.
On first load the plugin writes default prompt files into
<vault>/Synod/_prompts/ (path configurable):
value-agent.md — per-value agent system promptcompiler-finder.md — Pass 1 tension findercompiler-validator.md — Pass 2 tension validatorcompiler-report-validator.md — Pass 0 evidentiary gateschwartz-extractor.md — value-discovery promptEdit them like any markdown note. The next pipeline run reads the changes.
Use {value_name} / {value_definition} placeholder syntax.
Every knob is in Settings → Community plugins → Synod:
Open the side panel via the ribbon icon (or Synod: Open status view).
The view shows the live phase
(ingesting → extracting → agents → compiling → writing → done),
a progress bar, last-run timestamp, counts, and a tail of the log.
localhost. Nothing leaves your machine.data.json,npm install
npm run build # bundles to main.js
npm test # pure-function smoke tests (parsers, hashing, packing)
To install into a vault during development:
ln -s "$(pwd)" "/path/to/Vault/.obsidian/plugins/synod"
Then in Obsidian: Settings → Community plugins → enable Synod.
version in manifest.json (SemVer).versions.json mapping the new plugin version to the
minimum compatible Obsidian version.v):git tag -a 0.2.0 -m "0.2.0"
git push origin 0.2.0
.github/workflows/release.yml builds
the plugin, runs tests, and publishes a draft release with
main.js, manifest.json, and styles.css attached.Plugin.loadData()/saveData(). No SQLite, no
vector DB. Entries fit in context for typical journal sizes; if/when
they don't, plug a vector store into agents/value-agent.ts.runValueAgent() takes only one value's
(id, name, definition) plus the shared corpus. The Compiler is the
only module that sees all reports; its output is never fed back into
the agents.llm/index.ts funnels generation through one
Promise so single-GPU backends don't trample each other when value
agents fan out in parallel. Hosted backends can lift this gate.[date — part k/N] blocks across LLM calls — never
silently truncated.MIT — see LICENSE.