Metadata-Version: 2.4
Name: scribe-gen
Version: 0.1.0
Summary: AI-powered CLI for blog generation, SEO scoring, and content repurposing
Project-URL: Homepage, https://github.com/khizerarain/scribe
Project-URL: Repository, https://github.com/khizerarain/scribe
Author-email: Khizar Arain <your@email.com>
License: MIT License
        
        Copyright (c) 2026 SCRIBE Contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ai,blog,cli,content-generation,openai,seo
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: jinja2>=3.1.0
Requires-Dist: markdown>=3.5.0
Requires-Dist: newspaper4k>=0.9.0
Requires-Dist: nltk>=3.8.0
Requires-Dist: openai>=1.0.0
Requires-Dist: pyfiglet>=1.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: python-slugify>=8.0.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: reportlab>=4.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: textstat>=0.7.0
Requires-Dist: typer>=0.12.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# SCRIBE

> **AI Content Generation Engine** — turn a single topic into a publish-ready blog post, then repurpose it for SEO and social media.

![Python](https://img.shields.io/badge/python-3.11%2B-blue)
![License](https://img.shields.io/badge/license-MIT-green)
![Status](https://img.shields.io/badge/status-portfolio--piece-purple)
![PyPI](https://img.shields.io/pypi/v/scribe-gen)

A production-quality Python CLI that goes from `topic` → `markdown` in one command, with built-in SEO scoring, tone rewrites, and social-media repurposing. Built to demonstrate clean architecture, prompt engineering discipline, and UX polish.

---

## Why this exists

Most "AI blog generator" demos stop at "ask the model for a post." SCRIBE goes further:

- **Real SEO scoring**, not AI-hallucinated numbers — readability via `textstat`, keyword density from actual counts, structure heuristics. The model only fills the qualitative gaps.
- **Single-responsibility modules** behind one API wrapper, so swapping OpenAI for Anthropic is a one-file change.
- **A real CLI** with Rich panels, spinners, tables, and a `--no-export` escape hatch — not a notebook.
- **Typed tone rewrites** with a Typer enum that rejects bad input before the API call.

It's a portfolio piece: the code is the resume.

---

## Features

- `scribe title` — generate `n` varied title candidates (list / how-to / question / contrarian angles)
- `scribe outline` — produce a structured `[{section, description}, ...]` outline
- `scribe generate` — full pipeline: title → outline → draft → export to Markdown with YAML frontmatter
- `scribe seo` — real computed score (readability 40% / keyword density 30% / structure 30%) + AI meta description + 3 suggestions; keywords auto-detected via NLTK when `--keywords` is omitted
- `scribe improve` — rewrite for clarity, flow, and engagement; renders a unified diff
- `scribe tone <professional|casual|witty|technical|persuasive>` — tone-shift rewrites with a Typer enum
- `scribe social` — LinkedIn post, X/Twitter thread (`1/`, `2/`, ...), Facebook post — three Rich panels; `--save` writes each to `output/social/`
- `scribe pdf` — export a Markdown post to a clean, single-column PDF
- `scribe import-url` — extract an article with `newspaper4k` and run `improve`, `social`, or `seo` on it
- `scribe history` — Rich table of past generations
- Friendly errors (Rich panels, no stack traces) for missing keys, empty topics, bad tones, API hiccups

---

## Installation

### From PyPI (recommended)

```bash
pip install scribe-gen
```

### From source

```bash
git clone https://github.com/khizerarain/scribe.git
cd scribe
pip install -e .
```

Create a `.env` file in your working directory and add your OpenAI key:

```bash
cp .env.example .env
# edit .env and set OPENAI_API_KEY
```

**Windows users:** set `PYTHONIOENCODING=utf-8` once per shell to keep Typer's Rich help (it uses `→`) from crashing the legacy cp1252 stdout.

---

## Usage

```bash
scribe title --topic "AI startup ideas" --count 5
scribe outline --topic "AI startup ideas" --sections 6
scribe generate --topic "AI startup ideas" --tone casual --length 1500
scribe generate --topic "AI startup ideas" --no-export   # print only
scribe seo --file output/ai-startup-ideas.md --keywords "AI startup, founder"
scribe improve --file output/ai-startup-ideas.md
scribe tone casual --file output/ai-startup-ideas.md
scribe tone technical --text "Paste draft here..."
scribe social --file output/ai-startup-ideas.md
scribe social --file output/ai-startup-ideas.md --save    # write to output/social/
scribe pdf --file output/ai-startup-ideas.md --output outputs/
scribe import-url https://example.com/article --action social
scribe history
scribe --version
```

If you run `scribe` with no args you get a small ASCII banner and a quick-start hint.

### Example output

```
   ____  ___  ____ ___ ___  __  __
  / ___|| _ \/ ___|_ _|_ _||  \/  |
  \___ \|  _/\___ \| | | | | |\/| |
   ___) | |  ___) | | | | | |  | |
  |____/|_| |____/___|___| |_|  |_|

  SCRIBE v0.1.0 · AI content generation engine
```

---

## Architecture

Every module has one job. Every API call goes through `client.py` so swapping providers is a single-file change.

| Module | Responsibility |
|---|---|
| `cli.py` | Typer app, command registration, banner, error panels |
| `client.py` | OpenAI wrapper (`chat_completion()` w/ exponential backoff) — the only module that talks to the API |
| `prompts.py` | All system/user prompt templates — no API calls live here |
| `generator.py` | `generate_titles()`, `generate_draft()` |
| `outlines.py` | `generate_outline()` |
| `seo.py` | `analyze_seo()` — computed score + AI-suggested meta/suggestions |
| `improver.py` | `improve_content()`, `change_tone()` |
| `social.py` | `generate_social_posts()` → `{linkedin, twitter_thread, facebook}` |
| `exporter.py` | `export_markdown()` — YAML frontmatter + slugified filename |
| `config.py` | Env loading, defaults, paths |
| `utils.py` | Shared Rich console, `with_spinner()`, slugify, history I/O |

### SEO scoring formula

```
score = round(
    readability_score  * 0.40
  + keyword_score      * 0.30    (skipped if no --keywords; weight redistributed)
  + structure_score    * 0.30
)
```

- **Readability** (40%): `textstat.flesch_reading_ease(text)` — clamped to 0-100
- **Keyword density** (30%): per-keyword `count / total_words * 100`; 1-2% ideal, 0.5-1% or 2-3% acceptable, <0.5% low, >3% stuffed
- **Structure** (30%): H2 headings + intro paragraph + conclusion section + paragraph-length distribution

The AI is asked for exactly two qualitative outputs: a meta description (150-160 chars) and three concrete improvement suggestions. It is never asked for the score.

---

## Configuration

| Env var | Default | Purpose |
|---|---|---|
| `OPENAI_API_KEY` | _(required)_ | Your OpenAI API key |
| `SCRIBE_MODEL` | `gpt-4o-mini` | Any chat-completions-compatible model |

`.env` is gitignored. If the key is missing, SCRIBE prints a Rich error panel and exits 1 — never a stack trace.

---

## Error handling

| Situation | Behavior |
|---|---|
| Missing `OPENAI_API_KEY` | Rich red panel with setup steps, exit 1 |
| Empty / too-short `--topic` | Friendly yellow panel asking for more detail, exit 1 |
| Invalid `--tone` | Typer auto-rejects with valid options listed, exit 2 |
| OpenAI rate-limit / network error | Retried 3× with exponential backoff (`client.py`); clear Rich panel if all fail |
| AI returns malformed JSON for SEO suggestions | Falls back to a deterministic truncated meta; the score (computed) is unaffected |

---

## Roadmap (v2 — seams are in place, not implemented)

- **SQLite history** with full-text search, tags, and per-topic stats
- **LangChain orchestration** for prompt chaining and tool use
- **Vector DB style-matching** — pull the top 3 past posts in a similar tone and use them as few-shot examples
- **Template library** — load user-defined prompt templates from disk
- **Streaming responses** for live diff rendering in `improve` and `tone`
- **Concurrent social generation** with bounded concurrency (3 calls today run sequentially)

---

## Development

```bash
# Verify the CLI
python -m scribe.cli --help
python -m scribe.cli --version

# Manual smoke test of a single command without hitting the API
PYTHONIOENCODING=utf-8 python -m scribe.cli seo --file output/<some>.md
```

The `v2 hook:` comments in `config.py`, `prompts.py`, and `client.py` mark the seams where new pieces slot in.

---

## License

MIT — see `LICENSE`.

---

## Sample output

The `.gitignore` excludes `output/*.md` by default so generated content doesn't pollute commits. To produce a real screenshot for the README, run something like:

```bash
scribe generate --topic "Starting an AI business in 2026" --tone professional --length 1500
scribe seo --file output/starting-an-ai-business-in-2026.md --keywords "AI business"
```

Then commit the resulting `.md` file manually with `git add -f output/<file>.md` for the portfolio screenshot.
