redakt — an AI-assisted, provider-agnostic TUI for drafting and publishing to WriteFreely
Find a file
2026-08-03 16:12:25 -04:00
.forgejo redakt: fix curl proto-redir no-op, wire release asset + CI, surface checksum diagnostic 2026-08-01 15:21:17 -04:00
cmd/redakt retrieval: whole-branch review fix pass — 4 findings 2026-08-02 15:57:36 -04:00
compose build: Go 1.25 toolchain, release packaging, compose + CI 2026-07-30 19:26:17 -04:00
docs retrieval: whole-branch review fix pass — 4 findings 2026-08-02 15:57:36 -04:00
internal retrieval: re-review fixes — Debug-level degrade log, reject nil embedding entries 2026-08-02 16:26:44 -04:00
.editorconfig Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
.env.example Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
.gitattributes Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
.gitignore redakt: gitignore .worktrees/ for isolated feature-branch workspaces 2026-08-02 14:55:29 -04:00
AGENTS.md fix(tui): inline textarea editor for candidates (replaces external $EDITOR) 2026-07-30 21:11:25 -04:00
CHANGELOG.md Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
CLA.md Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
COMMERCIAL-LICENSE.md Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
CONTRIBUTING.md Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
Dockerfile build: Go 1.25 toolchain, release packaging, compose + CI 2026-07-30 19:26:17 -04:00
embed.go feat(config): XDG config/env loader, secret-scrubbing logs, atomic fs 2026-07-30 19:26:17 -04:00
go.mod redakt: sentinel-substitution content pipeline for preview graphics 2026-08-01 13:06:29 -04:00
go.sum redakt: header section progress bar via bubbles/progress 2026-07-31 19:52:04 -04:00
install.sh redakt: fix install.sh's broken releases/latest/download URL scheme (Forgejo has no GitHub-style alias) 2026-08-01 22:02:10 -04:00
install_test.sh redakt: add regression test pinning the resolved-tag download URL shape 2026-08-01 22:09:54 -04:00
LICENSE Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
LICENSE-why-affero.html Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
LICENSE.header.txt Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00
Makefile redakt: fix curl proto-redir no-op, wire release asset + CI, surface checksum diagnostic 2026-08-01 15:21:17 -04:00
MODELNOTES.md redakt: phase 4 — code-level guardrails + context UX + opt-in gate + bake-off docs 2026-07-31 15:10:21 -04:00
NOTICE.md redakt: config example + NOTICE attribution — final-review findings 7, 9 2026-08-01 13:47:06 -04:00
README.md redakt: TUI context picker — add d to select a folder as context 2026-08-02 12:43:40 -04:00
redakt.toml.example tui: wire retriever construction from [embeddings] config 2026-08-02 15:33:41 -04:00
SECURITY.md docs: build guide, acceptance contract, security/readme sync 2026-07-30 19:26:17 -04:00
STYLE.md.example Scaffold redakt 0.0.0 2026-07-30 14:44:07 -04:00

redakt

Status: scaffold (v0.0.0-scaffold). This commit is the AGPLv3+ dual-licensed FOSS skeleton. The TUI, provider layer, ensemble, style learning, and WriteFreely adapter land in PRs #1#5. Today's binary prints its version and exits.

Interactive multi-model ensemble blog assistant for Linux.

You write a rough outline. redakt fans it out to N language models (local + cloud), shows you their rewrites side-by-side in a terminal UI, remembers what you accept, drifts toward your voice over time, and posts the finished Markdown to WriteFreely with one keystroke.

Why

I wanted a workflow where:

  • the rough outline is mine,
  • several models propose rewrites for each section,
  • I accept what I like,
  • the tool learns what "what I like" means,
  • the completed post is one keystroke from WriteFreely.

Nothing I tried scratched this itch. So I built redakt.

Stack

  • Language: Go 1.25+
  • UI: Bubble Tea + Lipgloss + Bubbles + Huh + Glamour (Charmbracelet: charm.land). The project's charm-first reuse rule is documented in AGENTS.md; the file picker that powers mid-session context loading is bubbles/filepicker and the inline candidate editor is bubbles/textarea.
  • Logging: charmbracelet/log feeds a secret-scrubbing slog handler.
  • LLM clients: OpenAI-compatible (sashabaranov/go-openai). Works with any OpenAI-style endpoint — local llama-server (via llama-toolcall-proxy for buggy tool-call emitters), Ollama, Groq, Gemini, OpenRouter, etc.
  • Style learning: STYLE.md (you own it) + an accepted-line corpus + a periodic auto-merge proposal you approve before it lands.
  • Blog backend: WriteFreely (POST /api/posts), pluggable later.

Build from source

git clone https://git.ourserver.party/xenarathon/redakt.git
cd redakt
make install   # builds and installs to $(go env GOPATH)/bin — no sudo

One-liner (downloads, verifies, and installs the right build for your OS/arch; on Linux, also adds a desktop menu entry):

curl -fsSL https://git.ourserver.party/xenarathon/redakt/raw/branch/main/install.sh | sh

Covers linux-amd64, linux-arm64, darwin-amd64, darwin-arm64 — no other CPU architecture is built today (no ppc64le, i386/i686, or armv6l/armv7l); the script exits with a named error on anything else rather than guessing.

If you'd rather read the script before piping it to sh (a reasonable habit) — or do it by hand for any other reason — here are the same steps manually:

# 1. Find the latest release tag (Forgejo has no GitHub-style "latest" URL alias)
TAG=$(curl -s https://git.ourserver.party/api/v1/repos/xenarathon/redakt/releases/latest \
  | grep -o '"tag_name":"[^"]*"' | cut -d'"' -f4)

# 2. Download
curl -LO https://git.ourserver.party/xenarathon/redakt/releases/download/$TAG/redakt.linux-amd64.tar.xz

# 3. Verify sha256 (fail-closed)
curl -L https://git.ourserver.party/xenarathon/redakt/releases/download/$TAG/SHA256SUMS \
  | grep redakt.linux-amd64.tar.xz | sha256sum -c -

# 4. Install
tar -xJf redakt.linux-amd64.tar.xz
sudo install -m 0755 redakt /usr/local/bin/redakt

# 5. First run
redakt init

darwin/arm64, linux/arm64, and darwin/amd64 builds drop with matching SHA256SUMS. Optional Homebrew tap lands later.

Trust model: the install path relies on TLS to git.ourserver.party, the SHA256SUMS file shipped alongside each release, and whoever has Forgejo push access to cut a release — there are no PGP-signed releases yet. That's a deliberate choice for a single-maintainer, self-hosted project today, not an oversight.

Docker (optional, for the homelab): see compose/redakt.yaml.

Configure

~/.config/redakt/redakt.toml — see redakt.toml.example for a starting point.

[ensemble]
default_providers = ["nanbeige", "groq", "gemini"]

~/.config/redakt/.env — keep it out of git:

GROQ_API_KEY=...
GEMINI_API_KEY=...
OPENROUTER_API_KEY=...
NANBEIGE_URL=http://192.168.1.209:8094/v1   # local llama-server via the toolcall proxy
WRITEFREELY_INSTANCE=https://blog.ourserver.party
WRITEFREELY_TOKEN=...

Get the WriteFreely token with redakt auth login (lands in PR #3).

Voice guide

~/.config/redakt/STYLE.md is your hand-written style guide. It's the base of every system prompt; edit it freely — the tool does not auto-overwrite your manual changes. A starter seed ships in STYLE.md.example.

Use

redakt new path/to/outline.md     # seed the post from an outline
redakt new                        # start with an empty post
redakt resume                     # pick up an unfinished post

Inside the TUI:

  • j / k — navigate candidates
  • a — accept the selected candidate
  • r — re-roll candidates for the current section
  • c — open the file picker (bubbles/filepicker) to add context files mid-session. Navigates to .md / .markdown / .txt anywhere on disk and appends to the live post's context — never replaces the --context list passed at launch. Navigate into a folder and press d to add every top-level .md/.markdown/.txt file in it (non-recursive) instead of a single file — Enter alone can only select a file, never a folder. Esc cancels and returns to the candidate review without changes.
  • m — edit the selected candidate inline (Ctrl+S save, Esc cancel)
  • Ctrl+P — preview the assembled post
  • p (from Reviewing) — enter Publish phase
  • y / n — confirm / reject (publish, style merge, etc.)
  • q — quit; any unsaved post becomes a draft in ~/.local/share/redakt/drafts/

How style learning works

Three layers; each is opt-in and reversible.

  1. STYLE.md (you own it). Base of every system prompt.
  2. Accepted corpus (~/.local/share/redakt/accepted_corpus.jsonl). Every accepted line appended. Last 10 + 5 deterministic-random older entries injected as few-shot examples. Atomic-rename writes; SIGINT-safe.
  3. Periodic auto-merge (every 25 accepts). redakt runs an internal "reconcile recent corpus + STYLE.md → proposed update" against a stable local provider. The proposal is written to style_proposal.md and you must approve it before it merges into STYLE.md. Never silent.

License

redakt is dual-licensed:

  • Open source: GNU Affero General Public License, version 3 or later (see LICENSE). Strong copyleft with the network clause.
  • Commercial: available if AGPL terms don't fit. See COMMERCIAL-LICENSE.md.

Every .go file carries the AGPL SPDX header from LICENSE.header.txt; enforced by the make license-check target.

Third-party NOTICE (AGPL §5 compliance)

The redakt binary prints its license + third-party attribution on demand via redakt license. The full per-dep attribution table — including transitive dependency licenses — lives in NOTICE.md at the project root. The AGPL §5 obligation on interactive user interfaces is satisfied by three surfaces: the redakt license subcommand, the TUI ?-key banner, and the NOTICE.md file itself.

Contributors sign a CLA (terms in CONTRIBUTING.md).

Security defaults

The tool never:

  • posts to WriteFreely without an explicit keypress and confirmation (a second confirm when safer_posting is on, the default),
  • prints Authorization headers or *_API_KEY to logs,
  • overwrites your STYLE.md silently.

See CONTRIBUTING.md.

Status

This is the scaffold commit (0.0.0-scaffold). Subsequent PRs land:

  1. Config layer + XDG + slog with secret scrubbing
  2. Provider abstraction + ensemble orchestrator
  3. WriteFreely adapter
  4. Style learning module
  5. Bubble Tea TUI
  6. Tests
  7. Native release pipeline + optional Homebrew tap

Disclaimer

🤖 This project was built with the help of AI assistants: the scaffold, review, and architecture with Claude (Opus 4.8) by Anthropic, and the implementation PRs with Kimi. All code is human-reviewed before merge.