Skip to main content
notewise is a Python CLI application built with a clean, layered architecture. Each layer has a single responsibility and strict import boundaries, making the codebase easy to reason about, test, and extend.

Layer overview


Layer responsibilities

The only entry point for human users. Uses Typer for argument parsing and Rich for terminal output. Heavy dependencies are loaded lazily inside each command body to keep startup time low.
FileRole
cli/app.pyCommand definitions
cli/_batch_runner.pyMulti-video orchestration, feeds events to PipelineDashboard
cli/_single_runner.pySingle-video run path
cli/_runtime.pyCliProcessRunner top-level coordinator
cli/_display.pyRich table and panel helpers
cli/_admin.pyinfo / stats / history / cache / logs implementations
Import rule: The CLI layer may import from all other layers. It must not contain business logic — it delegates entirely to the pipeline.
Owns the core processing workflow. The only layer that coordinates between YouTube extraction, LLM generation, and storage.
FileRole
pipeline/core.pyCorePipeline: state, semaphores, DB singleton, public run()
pipeline/_execution.pyprocess_single_video and run_pipeline implementations
pipeline/generation.pyStudyMaterialGenerator: token counting, chunking, LLM calls
Import rule: May import from YouTube, LLM, storage, and domain layers. Must not import from the CLI layer.
Handles all YouTube-specific I/O: transcript fetching, metadata retrieval, playlist enumeration, and URL parsing.
FileRole
youtube/parser.pyURL and bare-ID parsing → ParsedURL
youtube/transcript.pyfetch_transcript() with language fallback and retries
youtube/metadata.pyget_video_metadata(), get_playlist_info(), get_source_metadata()
youtube/playlist.pyextract_playlist_videos()
youtube/extractor/Low-level HTTP client built from mixins
Import rule: Must not import from the LLM or pipeline layers.
Provider-agnostic interface over LiteLLM.
FileRole
llm/provider.pyLLMProvider, UsageTotals, get_provider() factory
llm/prompts/study_notes.pyStudy note generation prompts
llm/prompts/chapter_notes.pyPer-chapter generation prompts
llm/prompts/quiz.pyQuiz generation prompts
Import rule: Must not import from the YouTube, pipeline, or CLI layers.
Thread-safe SQLite persistence built on SQLAlchemy 2.0.
FileRole
storage/repository.pyDatabaseRepository: singleton per path, sync/async read/write
storage/models.pyORM models: VideoRecord, TranscriptRecord, RunStatsRecord, ExportRecord
storage/schemas.pyPydantic schemas for reading data out of the DB
storage/migrations.pyHand-rolled migration runner (no Alembic)
Import rule: Must not import from YouTube, LLM, pipeline, or CLI layers.
Pure Python value objects — no I/O of any kind. Safe to import from everywhere.
FileRole
domain/youtube.pyVideoMetadata, VideoTranscript, TranscriptSegment, VideoChapter, ParsedURL
domain/events.pyEventType enum, PipelineEvent dataclass
domain/results.pyPipelineResult, PipelineMetrics

Cross-Cutting Concerns

ConcernDescription
Configurationconfig.py exports a module-level settings object. Loaded once on first access and cached.
Error HandlingAll custom exceptions in errors.py. See Error Reference.
Logginglogging.py configures structlog at CLI startup. API keys are automatically redacted.
State DirectoryOverride with NOTEWISE_HOME environment variable. Default: ~/.notewise/

State Directory Structure

.notewise
config.env
.notewise_cache.db
logs
notewise-20260101-120000.log
notewise-20260102-080000.log
Last modified on March 28, 2026