Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Stable goals for this repository:

1. **Embeddable generator** — **`pip install docgen`** (or editable install from source), a `docgen.yaml`, and shell/CI are enough to build and maintain narrated demos. **No IDE assistant is required**; optional **`docgen wizard`** is a local web app only.
1. **Embeddable generator** — **`pip install docgen`** (git URL or editable install from this repo), a consumer **bundle** (`docgen.yaml` + hints/narration), and shell/CI are enough to build and maintain narrated demos. **Do not vendor** this library into a product repo’s `src/`; pin via `requirements-docgen.txt` / `pipx` / `uv tool`. **No IDE assistant is required**; optional **`docgen wizard`** is a local web app only.
2. **Hybrid config and prose** — **`docgen.yaml`** should stay maintainable: deterministic merges (**`yaml-generate`**, gap checks) plus **optional OpenAI** where it adds value (narration hints, declarative scene YAML). Prefer **Git-reviewed** changes over opaque single-shot generation.
3. **Video stack** — Long-form demos pair **Markdown narration**, **OpenAI TTS**, **Whisper-style timestamps**, **Manim** visuals, **`compose`** (ffmpeg), **`concat`**, and **`validate`** (sync and narration lint). The CLI also supports **`pages`** for static preview sites.
4. **Stable contracts** — CLI, exit codes, and reusable workflows should stay predictable for downstream repos and automation.
Expand Down Expand Up @@ -41,7 +41,7 @@ The Playwright/VHS/demo-function/per-function/discover-tests/catalog surface are
Commands registered on the **`docgen`** CLI include:

- **`init`** — scaffold bundle layout and `docgen.yaml`.
- **`wizard`** — local web UI for narration/bootstrap workflows (focus files, **in-place narration revise**, per-segment **asset freshness** + **rebuild-from-here**).
- **`wizard`** — local web UI for narration/bootstrap workflows (focus files, **in-place narration revise**, per-segment **asset freshness** + **rebuild-from-here**, **Tool** tab to pip-upgrade docgen and pin `requirements-docgen.txt`).
- **`tts`** — text-to-speech for segment files.
- **`timestamps`** — word/segment timing (`timing.json`). Default engine **`local`** aligns the known narration text against the mp3 offline (ffmpeg silencedetect, no API); **`--engine whisper`** keeps OpenAI whisper-1 transcription. Both emit the same Whisper-shaped blocks.
- **`image-generate`** — render scene-spec **image elements** (`image:` + `prompt:` boxes) via the OpenAI Images API into the bundle (also runs for missing assets inside `generate-all`).
Expand Down
34 changes: 27 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,31 @@ If you still need the legacy behaviour, pin a pre-removal commit
OpenAI where a command calls the API). The wizard is a local Flask app, not a
plugin tied to one editor.

## Install
## Install (external tool — do not vendor into project `src/`)

`docgen` is a **pip-installable CLI/library**. Consumer projects keep only a
**bundle** (`docs/demos/docgen.yaml`, hints, narration, …). They should **not**
copy or submodule this repository into application source.

```bash
pip install docgen @ git+https://github.com/jmjava/documentation-generator.git
# Project / CI venv
pip install 'docgen @ git+https://github.com/jmjava/documentation-generator.git'
# Prefer a SHA pin in CI:
# pip install 'docgen @ git+https://github.com/jmjava/documentation-generator.git@<sha>'

# Optional Manim extra
pip install 'docgen[manim] @ git+https://github.com/jmjava/documentation-generator.git'

# Isolated global CLI (no project venv)
pipx install 'docgen @ git+https://github.com/jmjava/documentation-generator.git'
# or: uv tool install 'docgen @ git+https://github.com/jmjava/documentation-generator.git'

docgen --version
```

## Development setup
`docgen init` writes `requirements-docgen.txt` + a bundle `README.md` with the same guidance.

## Development setup (this library)

```bash
git clone https://github.com/jmjava/documentation-generator.git
Expand All @@ -87,10 +105,11 @@ CI installs `ffmpeg` and `tesseract` via apt — see `.github/workflows/ci.yml`.

**Roadmap:** [milestones/README.md](milestones/README.md).

## Quick start
## Quick start (in a consumer repo)

```bash
cd your-project/docs/demos
cd your-project/docs/demos # bundle only — library is on PATH via pip
pip install -r requirements-docgen.txt # after docgen init, or use the pip line above
docgen wizard # optional: bootstrap narration from project docs
docgen generate-all # TTS → timestamps → scene retime → Manim → compose → validate
docgen validate --pre-push
Expand All @@ -100,8 +119,9 @@ docgen validate --pre-push

| Command | Description |
|---------|-------------|
| `docgen init [TARGET_DIR] [--defaults] [--segments-file FILE]` | Scaffold a new project: `docgen.yaml`, wrapper scripts, directories |
| `docgen wizard [--port 8501]` | Local web GUI: focus files, **revise narration in place**, asset freshness chips, **rebuild-from-here** (default cascade: TTS → timestamps → scene-retime → Manim → compose → validate; LLM scene-spec is explicit) |
| `docgen --version` | Show installed version + recommended `pip install` line (external tool) |
| `docgen init [TARGET_DIR] [--defaults] [--segments-file FILE]` | Scaffold a bundle: `docgen.yaml`, `requirements-docgen.txt`, wrapper scripts, directories |
| `docgen wizard [--port 8501]` | Local web GUI: focus files, **revise narration**, asset freshness / rebuild-from-here, and a **Tool** tab to upgrade the installed `docgen` package (pip) + rewrite `requirements-docgen.txt` |
| `docgen tts [--segment 01] [--dry-run]` | Generate TTS audio |
| `docgen timestamps [--engine local\|whisper]` | Extract word/segment timestamps from TTS audio → `timing.json` (default `local`: offline narration-text alignment; `whisper`: OpenAI transcription) |
| `docgen image-generate [--segment 01 \| --all \| --spec PATH] [--force] [--dry-run] [--model …] [--size …]` | Generate scene-spec image assets (`image:` + `prompt:` boxes) via the OpenAI Images API into the bundle |
Expand Down
20 changes: 19 additions & 1 deletion src/docgen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ def _load_env(cfg: Config | None) -> None:
os.environ.setdefault(k, v)


def _cli_version_string(ctx: click.Context, param: click.Parameter, value: bool) -> None:
if not value or ctx.resilient_parsing:
return
from docgen.install_spec import DOCGEN_PIP_SPEC, package_version

click.echo(f"docgen {package_version()}")
click.echo(f"install: pip install '{DOCGEN_PIP_SPEC}'")
ctx.exit()


@click.group()
@click.option(
"--config",
Expand All @@ -84,9 +94,17 @@ def _load_env(cfg: Config | None) -> None:
type=click.Path(exists=False),
help="Path to docgen.yaml (parents of cwd are searched when omitted).",
)
@click.option(
"--version",
is_flag=True,
callback=_cli_version_string,
expose_value=False,
is_eager=True,
help="Show installed docgen version and the recommended pip install line.",
)
@click.pass_context
def main(ctx: click.Context, config_path: str | None) -> None:
"""docgen — demo generation pipeline.
"""docgen — demo generation pipeline (install as an external tool; keep only the bundle in-repo).

Environment: keys already set in the shell are not replaced by ``env_file``
(see ``DOCGEN_ENV_OVERRIDES``). If no docgen.yaml is found, pass ``--config``.
Expand Down
61 changes: 61 additions & 0 deletions src/docgen/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ def generate_files(plan: InitPlan) -> list[str]:
(plan.demo_dir / subdir).mkdir(parents=True, exist_ok=True)

created.append(_write_config(plan))
created.append(_write_requirements_docgen(plan))
created.append(_write_bundle_readme(plan))

for path in _write_wrapper_scripts(plan):
created.append(path)
Expand Down Expand Up @@ -446,6 +448,62 @@ def _write_wrapper_scripts(plan: InitPlan) -> list[str]:
return created


def _write_requirements_docgen(plan: InitPlan) -> str:
"""Write ``requirements-docgen.txt`` so consumers install docgen externally."""
from docgen.install_spec import requirements_docgen_txt

path = plan.demo_dir / "requirements-docgen.txt"
path.write_text(requirements_docgen_txt(), encoding="utf-8")
return str(path)


def _write_bundle_readme(plan: InitPlan) -> str:
"""Short bundle README: install docgen as a tool, keep only this bundle in-repo."""
content = textwrap.dedent(f"""\
# {plan.project_name} demos (docgen bundle)

This directory is a **docgen bundle** (`docgen.yaml` + narration/hints/assets).
The ``docgen`` CLI itself is an **external** package — do **not** vendor the
``documentation-generator`` source tree into this repository.

## Install the tool (once per machine / CI job)

```bash
python3 -m venv ../../.venv # or any project venv
source ../../.venv/bin/activate
pip install -r requirements-docgen.txt
# optional Manim:
# pip install 'docgen[manim] @ git+https://github.com/jmjava/documentation-generator.git'
```

Isolated global install (no project venv):

```bash
pipx install 'docgen @ git+https://github.com/jmjava/documentation-generator.git'
# or: uv tool install 'docgen @ git+https://github.com/jmjava/documentation-generator.git'
```

Verify: ``docgen --version``

## Run from this bundle

```bash
cd {plan.demo_dir.name if plan.demo_dir.name else "."}
docgen wizard
docgen generate-all
docgen validate --pre-push
```

Wrapper scripts (``generate-all.sh``, ``compose.sh``, …) activate a nearby
``.venv`` when present, then call the ``docgen`` console script on ``PATH``.
""")
path = plan.demo_dir / "README.md"
if path.exists():
return str(path)
path.write_text(content, encoding="utf-8")
return str(path)


def _write_narration_readme(plan: InitPlan) -> str:
content = textwrap.dedent("""\
# Narration scripts (TTS source)
Expand Down Expand Up @@ -544,10 +602,13 @@ def print_summary(plan: InitPlan, created: list[str]) -> None:
click.echo()
click.secho(" Next steps:", fg="cyan")
click.echo(f" cd {plan.demo_dir}")
click.echo(" pip install -r requirements-docgen.txt # external tool — not vendored into src")
click.echo(" docgen --version")
click.echo(" docgen wizard # launch GUI to draft narrations")
click.echo(" docgen tts --dry-run # preview TTS text stripping")
click.echo(" docgen validate # check recordings")
click.echo(" docgen generate-all # full pipeline (see docgen generate-all --help)")
click.echo()
click.echo(" Run docgen yaml-generate next, then edit docgen.yaml for segments, visuals, and TTS as needed.")
click.echo(" Keep only this bundle in your repo — install docgen via pip/pipx, do not copy the library source.")
click.echo()
Loading