Files
council/scripts
jpmschweitzerandClaude Opus 4.7 2c8df9425b add AudioPen ingest pipeline and sync architecture setup docs
Voice-note capture as the primary mobile input channel. AudioPen
polishes on their cloud, POSTs to a self-hosted receiver on the
desktop (exposed via Tailscale Funnel so no router ports open and
nothing behind Authentik). The receiver writes to inbox/raw/; a bash
normaliser wraps each drop in frontmatter and moves it to inbox/;
/triage-inbox routes them from there.

scripts/audiopen-ingest.sh — 80-line bash normaliser. Idempotent;
safe to re-run. Extracts title, slugifies, computes capture timestamp
from mtime, rewrites with fleeting-note frontmatter.

scripts/audiopen-webhook/main.py — stdlib-only Python HTTP server.
Zero pip deps; binds to 127.0.0.1 by default. Accepts flexible
payload shapes (title/name + body/output/summary/polished/
orig_transcript) so AudioPen version drift is logged rather than
silently dropped.

scripts/audiopen-webhook/*.example — systemd user-unit templates for
the receiver and the path/service pair that fires the ingest wrapper
on inbox/raw/ changes.

scripts/pyproject.toml + README.md — Python venv convention. Zero
deps today; venv location reserved at scripts/.venv/ (gitignored),
manifest at scripts/pyproject.toml, bootstrap documented for both
plain pip and uv. Optional-dependencies groups let individual tools
pull what they need without bloating the whole env.

docs/setup/audiopen.md — full setup guide: generating the shared
secret, installing the systemd units, pairing with Tailscale Funnel,
configuring AudioPen's webhook, and the IMAP-fallback path for
setups that can't run a public-reachable receiver.

docs/setup/sync.md — companion guide: Gitea SSH remote (works even
with Authentik gating HTTPS), obsidian-git plugin configuration,
Syncthing desktop↔phone pairing with the critical .stignore patterns,
and the three phone-role tiers so the user can pick Tier 1 / 2 / 3
at their own pace.

.gitignore gains **/.venv/, **/venv/, **/__pycache__/, and *.pyc so
nobody accidentally commits a materialised environment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:17:48 +02:00
..

scripts/

Operational scripts for the PKB. Everything here is side-effectful — writing files, running webhooks, ingesting voice notes. Keep it small; anything analytical belongs in .claude/commands/ or in the mql CLI.

Current contents

Path Language Purpose
audiopen-ingest.sh bash Normalises raw AudioPen drops (inbox/raw/*.md) into properly-frontmattered fleeting notes in inbox/. Idempotent.
audiopen-webhook/main.py Python (stdlib) Tiny HTTP server that receives AudioPen webhook POSTs and writes to inbox/raw/. Designed to sit behind Tailscale Funnel.
audiopen-webhook/*.example systemd User-unit examples for the receiver + the path/service that runs audiopen-ingest.sh on file change.

Setup guide for the full pipeline: docs/setup/audiopen.md.

Python venv convention

Python code in this repo is stdlib-only as of now. No pip-installable dependencies. If/when a real dependency arrives (e.g. watchdog, imap-tools, anything heavier than stdlib), the convention is:

  • Venv lives at scripts/.venv/ (gitignored — every user materialises locally).

  • Dependencies tracked in scripts/pyproject.toml (committed).

  • Bootstrap on a fresh machine:

    cd scripts
    python3 -m venv .venv
    .venv/bin/pip install -e .
    

    Or with uv (recommended if available):

    cd scripts
    uv venv
    uv pip install -e .
    
  • Scripts that need the venv should either:

    • Invoke scripts/.venv/bin/python3 explicitly in their shebang or systemd ExecStart.
    • Or document activation (source scripts/.venv/bin/activate) before running.

Keeping the venv under scripts/ rather than the repo root keeps the Obsidian file tree uncluttered — scripts/ is already excluded from Obsidian's index (userIgnoreFilters in .obsidian/app.json) so nothing Python-related will ever show in the graph or search.

Don't create the venv preemptively. When the first dependency lands, that's when you create it. Keeps the repo lighter and avoids stale venv directories.

The pyproject.toml uses [project.optional-dependencies] to split deps by tool — e.g. pip install -e .[imap] installs only the IMAP fetcher's deps. This lets the webhook receiver stay dep-free while heavier tools can pull in what they need.

Shell scripts

Kept in plain bash. Portable to any Linux running GNU coreutils (which Bazzite does). No zsh-isms, no bashisms beyond set -euo pipefail and arrays. If a script grows past ~200 lines or needs real argument parsing, rewrite it in Python (and you're now back in the venv convention above).