Skip to content

Commit 6771c0e

Browse files
binarykclaude
andcommitted
feat: add aidocs serve command with MkDocs Material theme
- Add `aidocs serve` command to serve docs with live reload - Auto-discovers navigation from folder structure - Material Design theme with light/dark mode - Hot reload when markdown files change - Full-text search and code highlighting - Optional `--build` flag for static site export - Combine Quick Start and Installation sections in README 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2 parents de7b8a5 + ba7f070 commit 6771c0e

18 files changed

Lines changed: 2026 additions & 140 deletions

File tree

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"Bash(brew install:*)",
1919
"Bash(brew untap:*)",
2020
"Bash(aidocs version:*)",
21-
"Bash(uv pip install:*)"
21+
"Bash(uv pip install:*)",
22+
"Bash(git checkout:*)"
2223
]
2324
}
2425
}

README.md

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
AI-powered documentation generator for web applications.
44

5+
[![Watch the video](https://img.youtube.com/vi/cmwt4XizcTw/maxresdefault.jpg)](https://youtu.be/cmwt4XizcTw)
6+
7+
▶️ **[Watch the demo on YouTube](https://youtu.be/cmwt4XizcTw)**
8+
59
## How It Works
610

711
aidocs generates comprehensive documentation by combining **three sources of truth**:
@@ -27,44 +31,34 @@ This produces documentation that's accurate to both the code AND the actual user
2731
└────────────────────────┘
2832
```
2933

30-
## Installation
34+
## Quick Start
3135

3236
```bash
33-
# Install from PyPI
37+
# 1. Install the CLI
3438
uv tool install aidocs
3539

36-
# Or install from GitHub
37-
uv tool install aidocs --from git+https://github.com/binarcode/aidocs-cli.git
40+
# 2. Add to your project
41+
cd your-project
42+
aidocs init .
3843

39-
# Or use pipx
40-
pipx install aidocs
44+
# 3. Generate docs (in Claude Code)
45+
/docs:generate https://myapp.com/dashboard
4146
```
4247

43-
## Updating
44-
45-
When a new version is released, update the CLI and reinstall commands in your project:
46-
48+
**Alternative installation:**
4749
```bash
48-
# 1. Update the CLI
49-
aidocs update
50+
# From GitHub (latest)
51+
uv tool install aidocs --from git+https://github.com/binarcode/aidocs-cli.git
5052

51-
# 2. Reinstall commands in your project (adds new slash commands)
52-
cd your-project
53-
aidocs init . --force
53+
# Or use pipx
54+
pipx install aidocs
5455
```
5556

56-
The `--force` flag overwrites existing command files, adding any new commands from the latest version.
57-
58-
**Tip:** Run `aidocs update --github` to get the latest unreleased features from GitHub.
59-
60-
## Quick Start
61-
57+
**Updating:**
6258
```bash
63-
# Install the CLI
64-
uv tool install aidocs
65-
66-
# Add to your project
67-
aidocs init .
59+
aidocs update # Update from PyPI
60+
aidocs update --github # Update from GitHub (latest)
61+
aidocs init . --force # Reinstall commands in project
6862
```
6963

7064
## Usage Flow
@@ -258,6 +252,43 @@ docs/
258252

259253
**Next step:** Run `aidocs rag-vectors` to generate embeddings
260254

255+
### `aidocs export-pdf`
256+
257+
Export markdown documentation to PDF with auto-generated table of contents.
258+
259+
```bash
260+
aidocs export-pdf docs/projects/index.md # Export to docs/exports/
261+
aidocs export-pdf docs/flows/sync-users.md -o manual.pdf # Custom output path
262+
```
263+
264+
**Options:**
265+
| Option | Description |
266+
|--------|-------------|
267+
| `--output, -o` | Output PDF path (default: `docs/exports/{name}.pdf`) |
268+
269+
**What it does:**
270+
1. Reads the markdown file
271+
2. Extracts H1/H2 headings for table of contents
272+
3. Converts markdown to styled HTML
273+
4. Uses Chrome/Chromium headless to render PDF
274+
5. Saves with proper page breaks and formatting
275+
276+
**Output:**
277+
```
278+
╭──────────── Success ────────────╮
279+
│ PDF exported successfully! │
280+
│ │
281+
│ Title: Projects Overview │
282+
│ TOC entries: 8 │
283+
│ Size: 245.3 KB │
284+
│ │
285+
│ Output: docs/exports/index.pdf │
286+
╰─────────────────────────────────╯
287+
```
288+
289+
**Requirements:**
290+
- Chrome or Chromium installed (uses headless mode)
291+
261292
### `aidocs rag-vectors`
262293

263294
Generate embeddings and SQL for vector database import.
@@ -303,6 +334,8 @@ psql $DATABASE_URL -f docs/.chunks/sync.sql
303334

304335
Serve documentation with live reload using MkDocs Material theme.
305336

337+
![aidocs serve](docs/aidocs-serve.png)
338+
306339
```bash
307340
aidocs serve # Serve docs/ on port 8000
308341
aidocs serve --port 3000 # Custom port

docs/aidocs-serve.png

176 KB
Loading

docs/exports/README.pdf

697 KB
Binary file not shown.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "aidocs"
3-
version = "0.13.2"
3+
version = "0.14.0"
44
description = "AI-powered documentation generator for web applications. Install docs commands into your Claude Code project."
55
readme = "README.md"
66
license = { text = "MIT" }

src/aidocs_cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""AI-powered documentation generator CLI for Claude Code projects."""
22

3-
__version__ = "0.13.2"
3+
__version__ = "0.14.0"
44

55
from .cli import app
66

src/aidocs_cli/cli.py

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .chunker import chunk_directory
1515
from .embeddings import generate_sync_sql, get_openai_api_key
1616
from .installer import check_tools, install_docs_module
17+
from .pdf_exporter import export_markdown_to_pdf
1718
from .server import generate_mkdocs_config, validate_docs_directory, write_mkdocs_config
1819

1920
console = Console()
@@ -436,6 +437,65 @@ def on_status(message: str) -> None:
436437
raise typer.Exit(1)
437438

438439

440+
@app.command("export-pdf")
441+
def export_pdf(
442+
markdown_file: str = typer.Argument(
443+
...,
444+
help="Path to the markdown file to export.",
445+
),
446+
output: Optional[str] = typer.Option(
447+
None,
448+
"--output",
449+
"-o",
450+
help="Output PDF path (default: docs/exports/{name}.pdf).",
451+
),
452+
) -> None:
453+
"""Export markdown documentation to PDF.
454+
455+
Converts a markdown file to a styled PDF with auto-generated
456+
table of contents. Uses Chrome/Chromium for rendering.
457+
458+
Examples:
459+
aidocs export-pdf docs/projects/index.md
460+
aidocs export-pdf docs/flows/sync-users.md -o manual.pdf
461+
"""
462+
md_path = Path(markdown_file)
463+
out_path = Path(output) if output else None
464+
465+
console.print(f"[blue]Exporting {markdown_file} to PDF...[/blue]")
466+
console.print()
467+
468+
def on_status(msg: str) -> None:
469+
console.print(f" [dim]{msg}[/dim]")
470+
471+
try:
472+
result = export_markdown_to_pdf(md_path, out_path, on_status=on_status)
473+
474+
if not result["success"]:
475+
console.print(f"[red]Error: {result.get('error', 'Unknown error')}[/red]")
476+
raise typer.Exit(1)
477+
478+
stats = result["stats"]
479+
console.print()
480+
console.print(Panel.fit(
481+
f"[green]PDF exported successfully![/green]\n\n"
482+
f"[bold]Title:[/bold] {stats['title']}\n"
483+
f"[bold]TOC entries:[/bold] {stats['toc_entries']}\n"
484+
f"[bold]Size:[/bold] {stats['size_kb']} KB\n\n"
485+
f"[bold]Output:[/bold] {result['output_path']}\n\n"
486+
f"[dim]Open with:[/dim]\n"
487+
f" [cyan]open {result['output_path']}[/cyan]",
488+
title="Success",
489+
border_style="green",
490+
))
491+
492+
except typer.Exit:
493+
raise
494+
except Exception as e:
495+
console.print(f"[red]Error: {e}[/red]")
496+
raise typer.Exit(1)
497+
498+
439499
@app.command()
440500
def serve(
441501
docs_dir: Optional[str] = typer.Argument(
@@ -512,7 +572,7 @@ def serve(
512572

513573
try:
514574
result = subprocess.run(
515-
["mkdocs", "build", "-f", str(config_path)],
575+
[sys.executable, "-m", "mkdocs", "build", "-f", str(config_path)],
516576
capture_output=True,
517577
text=True,
518578
)
@@ -533,7 +593,7 @@ def serve(
533593
raise typer.Exit(1)
534594

535595
except FileNotFoundError:
536-
console.print("[red]Error: mkdocs not found. Install with: pip install mkdocs mkdocs-material[/red]")
596+
console.print("[red]Error: Failed to run mkdocs. Try reinstalling aidocs.[/red]")
537597
raise typer.Exit(1)
538598
else:
539599
url = f"http://{host}:{port}"
@@ -549,9 +609,10 @@ def serve(
549609

550610
try:
551611
cmd = [
552-
"mkdocs", "serve",
612+
sys.executable, "-m", "mkdocs", "serve",
553613
"-f", str(config_path),
554614
"-a", f"{host}:{port}",
615+
"--watch", str(target_dir),
555616
]
556617

557618
if open_browser:
@@ -564,7 +625,7 @@ def open_after_delay() -> None:
564625
subprocess.run(cmd)
565626

566627
except FileNotFoundError:
567-
console.print("[red]Error: mkdocs not found. Install with: pip install mkdocs mkdocs-material[/red]")
628+
console.print("[red]Error: Failed to run mkdocs. Try reinstalling aidocs.[/red]")
568629
raise typer.Exit(1)
569630
except KeyboardInterrupt:
570631
console.print("\n[yellow]Server stopped.[/yellow]")

src/aidocs_cli/installer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ def install_docs_module(
6666
console.print("[dim]Copying workflow files...[/dim]")
6767
workflows_src = templates_path / "workflows"
6868
if workflows_src.exists():
69-
if workflows_dest.exists() and force:
70-
shutil.rmtree(workflows_dest)
7169
shutil.copytree(workflows_src, workflows_dest, dirs_exist_ok=True)
7270

7371
for workflow_dir in workflows_dest.iterdir():

0 commit comments

Comments
 (0)