---
type: plan
tags: [architecture, mvp, phase-1, phase-2, phase-3]
tldr: "Original implementation plan for anyscribecli — phased build from MVP to multi-provider multi-platform tool"
created: 2026-03-26
status: phase-1-complete
---

# anyscribecli (`ascli`) — Original Implementation Plan

> This is the original plan created during the first build session on 2026-03-26.
> Preserved as-is for historical reference. See `BACKLOG.md` for current status.

## Context

Build a Python CLI tool that downloads video/audio from YouTube/Instagram, transcribes via API (OpenAI default), and outputs structured markdown into an Obsidian vault at `~/.anyscribecli/workspace/`. Provider architecture is pluggable (OpenAI, OpenRouter, ElevenLabs, Sargam, future local models). Download patterns borrowed from existing Dropzone bundles (yt-dlp for YouTube, instaloader with session caching for Instagram). Transcription logic informed by the existing AnyScribe web app at `/Users/rish/labs/01-Active-Projects/anyscribe`.

## Project Structure

```
~/labs/projects/anyscribecli/
├── pyproject.toml
├── .gitignore
├── CLAUDE.md                        # AI dev instructions + documentation ethic
├── AGENTS.md                        # Agent-specific instructions
├── docs/
│   ├── building/                    # Developer docs (Foundry-inspired)
│   │   ├── _index.md               # Building docs MOC
│   │   ├── architecture.md         # System design decisions
│   │   ├── providers.md            # How to add a provider
│   │   └── journal/                # Dev memory layer (dated entries)
│   │       └── YYYY-MM-DD-<slug>.md
│   └── user/                        # User-facing docs
│       ├── getting-started.md
│       ├── commands.md
│       └── configuration.md
├── src/anyscribecli/
│   ├── __init__.py                  # __version__
│   ├── cli/
│   │   ├── __init__.py
│   │   ├── main.py                  # Typer app: root + help panel config
│   │   ├── onboard.py               # Onboarding wizard
│   │   ├── transcribe.py            # Transcribe command
│   │   └── config_cmd.py            # Config + providers subcommands
│   ├── config/
│   │   ├── __init__.py
│   │   ├── paths.py                 # All path constants
│   │   └── settings.py              # Settings dataclass + load/save + load_env
│   ├── downloaders/
│   │   ├── __init__.py
│   │   ├── base.py                  # AbstractDownloader + DownloadResult
│   │   ├── youtube.py               # yt-dlp via subprocess (Dropzone pattern)
│   │   ├── instagram.py             # instaloader Python API (Dropzone pattern)
│   │   └── registry.py              # URL detection + dispatch
│   ├── providers/
│   │   ├── __init__.py              # Provider registry + get_provider()
│   │   ├── base.py                  # TranscriptionProvider ABC + TranscriptResult
│   │   ├── openai.py                # Whisper API via httpx
│   │   ├── openrouter.py            # (Phase 3)
│   │   ├── elevenlabs.py            # (Phase 3)
│   │   └── sargam.py                # (Phase 3)
│   ├── vault/
│   │   ├── __init__.py
│   │   ├── scaffold.py              # Create vault dirs + .obsidian/ + initial index
│   │   ├── writer.py                # Write transcript md + frontmatter
│   │   └── index.py                 # Update _index.md + daily logs
│   └── core/
│       ├── __init__.py
│       ├── orchestrator.py          # download -> transcribe -> write -> index
│       └── audio.py                 # Audio chunking for >25MB files
```

## Runtime Structure

```
~/.anyscribecli/
├── config.yaml              # all settings
├── .env                     # API keys
├── sessions/                # instaloader session cache
├── logs/                    # ascli-YYYY-MM-DD.log
├── tmp/                     # temp downloads (cleaned after processing)
└── workspace/               # Obsidian vault
    ├── .obsidian/
    ├── _index.md            # master MOC (newest-first table)
    ├── sources/
    │   ├── youtube/YYYY-MM-DD/<slug>.md
    │   └── instagram/YYYY-MM-DD/<slug>.md
    ├── daily/YYYY-MM-DD.md
    └── media/YYYY-MM-DD/    # if keep_media=true
```

## CLI Design — Human + AI Agent Friendly

- **Rich-enhanced help panels**: `typer.Typer(rich_markup_mode="rich")`
- **`--json` flag on all commands**: human-readable by default, JSON for scripting/agents
- **`--quiet` flag**: suppress progress output
- **Consistent exit codes**: 0 success, 1 error, 2 invalid input
- **Structured error output**: errors to stderr, results to stdout
- **Shell completion**: Typer built-in for bash/zsh/fish

## Transcription Logic (from AnyScribe web app)

### Whisper API Parameters
```python
model = "whisper-1"
response_format = "verbose_json"
timestamp_granularities = ["segment"]
```

### Audio Download Optimization
```python
audio_quality = "64k"        # safety margin above Whisper's 12kHz threshold
sample_rate = 16000           # Whisper's native processing rate
channels = 1                  # mono — 50% size reduction
format = "mp3"
```

### Chunking for Large Files (>25MB Whisper limit)
```python
chunk_duration = 18 * 60      # 18-minute chunks (stays under 25MB)
```

## Phase 1: MVP — YouTube + OpenAI end-to-end ✅

All steps completed 2026-03-26.

1. Project scaffold + docs foundation
2. Config layer (paths.py, settings.py)
3. Vault scaffold (.obsidian/, _index.md)
4. CLI onboard command (interactive wizard + dep checking)
5. YouTube downloader (yt-dlp subprocess, optimized audio)
6. OpenAI provider (Whisper API, verbose_json, chunking)
7. Vault writer + indexing (frontmatter, MOC, daily logs)
8. Orchestrator (full pipeline)
9. CLI transcribe command (all flags)
10. User docs + building journal entry

### Added beyond original plan:
- Dependency checking + auto-install in onboard wizard
- `ascli update` command (git + pip dual-path)
- `ascli doctor` command (health checks)
- `install.sh` script (zero-friction install)
- MIT LICENSE, PyPI-ready metadata

## Phase 2: Instagram + Config Commands

- `instagram.py` — instaloader Python API, session caching (Dropzone pattern)
- `config_cmd.py` — `ascli config show/set/path`, `ascli providers list/test`

## Phase 3: Additional Providers

- openrouter.py, elevenlabs.py, sargam.py

## Key Design Decisions

- **Python** over JS/TS — pipeline tools are Python-native
- **`ascli` command** — clear, pronounceable, no conflicts
- **`onboard` not `init`** — human-readable
- **yt-dlp via subprocess** — stable CLI, mirrors Dropzone bundle
- **instaloader via Python API** — session management, mirrors Dropzone bundle
- **Audio: 16kHz mono 64kbps** — proven Whisper-optimal from AnyScribe web app
- **18-min chunking** — battle-tested from AnyScribe web app
- **httpx** — async-capable for future batch
- **--json everywhere** — AI agent friendly, scriptable
- **SemVer** — 0.x for pre-stable, 1.0.0 when all platforms + providers working
