Sync Harmonica deliberation sessions to markdown files. Run locally or in CI to keep a structured archive of your sessions in a git repo, Quartz wiki, or static site.
# 1. Scaffold config and template
npx harmonica-sync --init
# 2. Edit harmonica.config.json with your search queries
# 3. Set your API key (from Harmonica dashboard → Settings → API Keys)
export HARMONICA_API_KEY=hm_live_...
# 4. Sync
npx harmonica-sync- Searches the Harmonica API with your configured queries
- Filters by keywords, participant count, and summary availability
- Skips sessions already in the output directory (idempotent)
- Renders each session through a Mustache template
- Writes markdown files to the output directory
harmonica.config.json:
{
"sync": {
"search": ["community feedback", "retrospective"],
"keywords": ["our-org", "team"],
"minParticipants": 1,
"requireSummary": true
},
"output": {
"dir": "sessions",
"filename": "{{date}}-{{id}}.md",
"template": "./session-template.md"
}
}| Field | Description | Default |
|---|---|---|
sync.search |
API search queries (required) | — |
sync.keywords |
Filter on topic/goal/context text | all results accepted |
sync.minParticipants |
Skip sessions below this count | 1 |
sync.requireSummary |
Only sync sessions with a summary | true |
output.dir |
Output directory | sessions |
output.filename |
Filename template ({{date}}, {{id}}, {{slug}}) |
{{date}}-{{id}}.md |
output.template |
Path to Mustache template | built-in Quartz-compatible |
The default template produces Quartz/Hugo/Jekyll-compatible markdown with YAML frontmatter. Customize it by editing the session-template.md generated by --init.
Available template variables:
| Variable | Type | Description |
|---|---|---|
topic |
string | Session topic |
date |
string | ISO date (YYYY-MM-DD) |
id |
string | Session ID |
participant_count |
number | Number of participants |
status |
string | Session status |
goal |
string | Session goal |
critical |
string/null | Critical question |
context |
string/null | Session context |
summary |
string/null | AI-generated summary |
tags |
string[] | Matched search queries |
responses |
boolean | Whether responses exist |
participants |
array | Participant responses |
participants[].number |
number | Participant number (1-indexed) |
participants[].messages |
array | User messages |
name: Sync Harmonica Sessions
on:
schedule:
- cron: '0 */6 * * *'
workflow_dispatch:
permissions:
contents: write
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Sync sessions
env:
HARMONICA_API_KEY: ${{ secrets.HARMONICA_API_KEY }}
run: npx harmonica-sync
- name: Commit new sessions
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add sessions/
git diff --cached --quiet || git commit -m "Sync Harmonica sessions" && git pushnpx harmonica-sync # sync using ./harmonica.config.json
npx harmonica-sync --config path/to # custom config path
npx harmonica-sync --init # generate starter config + template
npx harmonica-sync --help # show help
| Variable | Required | Description |
|---|---|---|
HARMONICA_API_KEY |
Yes | API key from Harmonica dashboard |
HARMONICA_API_URL |
No | API base URL (default: https://app.harmonica.chat) |
MIT