{"id":45885278,"url":"https://github.com/fmueller/scribae","last_synced_at":"2026-02-27T15:50:17.955Z","repository":{"id":322972110,"uuid":"1091321720","full_name":"fmueller/scribae","owner":"fmueller","description":"CLI to turn Markdown notes into SEO briefs, drafts, metadata, and translations using LLMs.","archived":false,"fork":false,"pushed_at":"2026-02-18T18:44:18.000Z","size":930,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-18T19:52:51.330Z","etag":null,"topics":["ai-tools","cli","content-generation","knowledge-management","llm","machine-translation","markdown","nlp","python","seo","text-generation","transformers"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fmueller.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-11-06T21:29:40.000Z","updated_at":"2026-02-18T18:44:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/fmueller/scribae","commit_stats":null,"previous_names":["fmueller/scribae"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/fmueller/scribae","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmueller%2Fscribae","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmueller%2Fscribae/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmueller%2Fscribae/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmueller%2Fscribae/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fmueller","download_url":"https://codeload.github.com/fmueller/scribae/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmueller%2Fscribae/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29903283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T14:46:13.553Z","status":"ssl_error","status_checked_at":"2026-02-27T14:46:10.522Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tools","cli","content-generation","knowledge-management","llm","machine-translation","markdown","nlp","python","seo","text-generation","transformers"],"created_at":"2026-02-27T15:50:17.180Z","updated_at":"2026-02-27T15:50:17.949Z","avatar_url":"https://github.com/fmueller.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scribae\n\n[![Build](https://github.com/fmueller/scribae/actions/workflows/build.yml/badge.svg)](https://github.com/fmueller/scribae/actions/workflows/build.yml)\n[![PyPI version](https://img.shields.io/pypi/v/scribae.svg)](https://pypi.org/project/scribae/)\n[![Python versions](https://img.shields.io/pypi/pyversions/scribae.svg)](https://pypi.org/project/scribae/)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/fmueller/scribae/blob/main/LICENSE)\n\n\u003e *From Latin scribae, \"the scribes.\" The professional copyists and secretaries of the ancient world.*\n\nScribae is a CLI that turns local Markdown notes into structured SEO content packages with human-in-the-loop\nreview. It keeps the research-to-publication flow reproducible by combining deterministic prompts, typed outputs,\nand LLMs via OpenAI-compatible APIs.\n\n## Why Scribae?\n\n- **Keep source material local.** Point the CLI at a Markdown note and run everything against an OpenAI-compatible API endpoint you control.\n- **Human in the loop.** Each stage is designed for review and editing before you publish.\n- **Repeatable prompts.** Each command builds structured prompts and validates model responses to catch schema drift early.\n- **End-to-end workflow.** Move from ideation to translation within one tool instead of juggling separate scripts.\n\n## Installation\n\nRun Scribae without installing it:\n\n```bash\nuvx scribae --help\n```\n\nRun with translation support enabled:\n\n```bash\nuvx \"scribae[translation]\" --help\n```\n\n\u003e **Note:** `uvx` creates a temporary environment on each run. With the translation extra, this downloads PyTorch (~2GB) every time. For repeated use, install with pipx or pip instead.\n\nInstall it globally with an isolated environment using `uv`:\n\n```bash\nuv tool install scribae\n```\n\nOr using `pipx`:\n\n```bash\npipx install scribae\n```\n\nOr use pip directly:\n\n```bash\npip install scribae\n```\n\n### Translation support\n\nTranslation uses PyTorch and Hugging Face Transformers. Install with the translation extra:\n\n```bash\npip install scribae[translation]\n```\n\nPrefer a CPU-only PyTorch wheel with pipx:\n\n```bash\npipx install \"scribae[translation]\" --pip-args=\"--index-url https://download.pytorch.org/whl/cpu\"\n```\n\n## Prerequisites\n\nScribae requires an **OpenAI-compatible API endpoint**. The easiest option is [Ollama](https://ollama.com) running locally:\n\n```bash\n# Install Ollama (see https://ollama.com for other platforms)\ncurl -fsSL https://ollama.com/install.sh | sh\n\n# Start the server\nollama serve\n\n# Pull the default model\nollama pull ministral-3:8b\n```\n\nAlternatively, point Scribae at any OpenAI-compatible endpoint:\n\n```bash\nexport OPENAI_BASE_URL=\"https://api.openai.com/v1\"\nexport OPENAI_API_KEY=\"sk-...\"\n```\n\n## Quick start\n\n1. **Generate ideas** from a Markdown note:\n   ```bash\n   scribae idea --note my-notes.md --json\n   ```\n\n2. **Create an SEO brief** from your note:\n   ```bash\n   scribae brief --note my-notes.md --out brief.json\n   ```\n\n3. **Write a draft** using the brief:\n   ```bash\n   scribae write --note my-notes.md --brief brief.json --out draft.md\n   ```\n\n4. **Add metadata** to your draft:\n   ```bash\n   scribae meta --body draft.md --brief brief.json --format frontmatter --out draft.md\n   ```\n\n5. **Translate** to another language:\n   ```bash\n   scribae translate --src en --tgt de --in draft.md --out draft.de.md\n   ```\n\nRun `scribae --help` to see all commands and options.\n\n## Core workflow\n\n```\nidea → brief → write → feedback → refine → meta → translate\n```\n\n1. **idea** — Brainstorm article ideas from a note with project-aware guidance.\n2. **brief** — Generate a validated SEO brief (keywords, outline, FAQ, metadata).\n3. **write** — Produce an article draft using your note, project context, and brief.\n4. **feedback** — Review a draft against a brief and generate a focused improvement report.\n5. **refine** — Improve a draft against a brief while preserving intent and structure.\n6. **meta** — Create publication metadata/frontmatter for a finished draft.\n7. **translate** — Translate Markdown using MT + LLM post-edit while preserving formatting.\n\n## Configuration\n\n### Environment variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `OPENAI_BASE_URL` | `http://localhost:11434/v1` | API endpoint URL |\n| `OPENAI_API_KEY` | `no-key` | API key (not needed for Ollama) |\n\nYou can also use `OPENAI_API_BASE` as an alternative to `OPENAI_BASE_URL`.\n\n### Project files\n\nCreate a `scribae.yaml` in your project directory to set defaults:\n\n```yaml\nsite_name: My Blog\ndomain: https://example.com\naudience: developers interested in Python\ntone: conversational\nlanguage: en\nkeywords:\n  - python\n  - programming\n```\n\n### LLM settings\n\nAll commands that use LLMs support `--temperature`, `--top-p`, and `--seed` for controlling output variability:\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--temperature` | 0.2–0.4 | Sampling temperature. Lower values produce more deterministic output. |\n| `--top-p` | (none) | Nucleus sampling threshold. Set to `1.0` for full distribution. |\n| `--seed` | (none) | Random seed for reproducible outputs. |\n\nFor fully deterministic output, set `--temperature 0`. For reproducible creative output, combine `--seed` with `--top-p 1.0`.\n\n```bash\n# Deterministic mode\nscribae brief --note notes.md --temperature 0 --out brief.json\n\n# Reproducible creative mode\nscribae write --note notes.md --brief brief.json --seed 42 --top-p 1.0 --out draft.md\n```\n\nThe `translate` command uses `--postedit-temperature`, `--postedit-top-p`, and `--postedit-seed` for the LLM post-edit pass.\n\n\u003e **Note:** Seed behavior depends on the underlying model. Some models (e.g., certain Ollama models) may not fully support deterministic output even with `--seed` set. For guaranteed reproducibility, test with your specific model and endpoint.\n\n## Usage examples\n\n### Idea discovery\n\nStart with a note and generate a structured list of candidate articles:\n\n```bash\nscribae idea --note notes.md --project demo --out ideas.json\n```\n\nUse `--language` or `--model` to override project defaults, and `--dry-run` to preview the prompt without calling the model.\n\n### SEO brief creation\n\nConvert a note into a validated brief, optionally anchored to a specific idea:\n\n```bash\n# From a note directly\nscribae brief --note notes.md --out brief.json\n\n# From a specific idea\nscribae brief --note notes.md --ideas ideas.json --idea-index 1 --out brief.json\n\n# Generate briefs for all ideas\nscribae brief --note notes.md --ideas ideas.json --idea-all --out-dir briefs/\n```\n\n### Draft writing\n\nTurn a note + brief into a draft:\n\n```bash\n# Full article\nscribae write --note notes.md --brief brief.json --out draft.md\n\n# Only sections 1-3\nscribae write --note notes.md --brief brief.json --section 1..3 --out draft.md\n\n# Require citations\nscribae write --note notes.md --brief brief.json --evidence required --out draft.md\n```\n\n### Metadata generation\n\nCreate JSON frontmatter or merge into an existing draft:\n\n```bash\nscribae meta --body draft.md --brief brief.json --format both --out meta.json\n```\n\nUse `--overwrite` to control how existing fields are preserved.\n\n### Translation\n\nTranslate Markdown while preserving structure:\n\n```bash\nscribae translate --src en --tgt de --in draft.md --out draft.de.md\n```\n\nOptions:\n- `--glossary` — Lock specific terminology\n- `--postedit` / `--no-postedit` — Toggle LLM cleanup pass\n- `--allow-pivot` — Enable English pivoting for unsupported language pairs\n- `--debug` — Write detailed translation report\n\n#### Supported language pairs\n\n**Direct MarianMT pairs:** `en`↔`de/es/fr/it/pt`, `de`→`es/fr/it/pt`, `es`→`de/fr/it/pt`\n\n**Pivoting:** When no direct pair exists and `--allow-pivot` is enabled, Scribae routes through English (`src → en → tgt`).\n\n**NLLB fallback:** For other pairs, the pipeline falls back to NLLB. Standard ISO codes (`en`, `de`, `es`) are mapped automatically, or pass NLLB codes directly (`eng_Latn`, `deu_Latn`).\n\n## Development\n\n### Setup\n\nThe `--all-extras` flag is required for development as it installs PyTorch, which is needed for mypy type checking to pass.\n\n```bash\ngit clone https://github.com/fmueller/scribae.git\ncd scribae\nuv sync --locked --all-extras --dev\n```\n\nFor CPU-only PyTorch (~200MB vs ~2GB):\n\n```bash\nuv sync --locked --all-extras --dev --index pytorch-cpu\n```\n\n### Running from source\n\n```bash\nuv run scribae --help\n```\n\n### Testing\n\n```bash\nuv run ruff check   # Lint\nuv run mypy         # Type check\nuv run pytest       # Run tests\n```\n\n## License\n\nThis project is licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffmueller%2Fscribae","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffmueller%2Fscribae","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffmueller%2Fscribae/lists"}