| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 5 | 18 | 0% |
| Commands | 3 | 3 | 10 | 19% |
| Section tags | 3 | 0 | 2 | 60% |
What each file covers
Sections
0 shared · 5 only in A · 18 only in B- − Gemini Agent Guide for Hermes
- − Project Overview & Architecture
- − Developer Workflow
- − Key Development Patterns
- − Gemini Agent Specific Notes
- + CLAUDE.md
- + Key Commands
- + Architecture Overview
- + CLI Framework (Kong)
- + Enhance Command
- + Basic usage - enhance all notes in a directory
- + Recursive scan with TMDB content generation
- + Download cover images and generate content
- + Interactive mode for manual TMDB selection
- + Dry run to see what would be enhanced
- + Configuration
- + Development Patterns
- + Caching Patterns
- + Testing Requirements
- + Datasette Integration
- + Logging
- + Output Formats & Handling
- + Important Notes
Commands
3 shared · 3 only in A · 10 only in B- − go run . <command> [flags]
- − go run . import goodreads -f path/to/export.csv
- − go.mod
- + task
- + task clean
- + task upgrade-deps
- + task build-linux
- + task test-ci
- + go run . import goodreads -f goodreads_library_export.csv
- + go run . import goodreads --automated --headful
- + go run . import goodreads --automated --dry-run
- + go run . enhance -d markdown/imdb --tmdb-generate-content
- + go test ./...
- task build
- task test
- task lint
Section tags
3 shared · 0 only in A · 2 only in B- + test
- + lint-format
- code-style
- architecture
- agent-behaviour
Line diff
lepinkainen/hermes · GEMINI.md
@@ −1 @@
1# Gemini Agent Guide for Hermes
2
3This guide provides essential information for developing in the Hermes codebase.
4
5## Project Overview & Architecture
6
7Hermes is a Go-based CLI tool for importing data from sources like Goodreads, IMDb, and Steam, and exporting it into Markdown, JSON, or SQLite/Datasette formats.
8
9- **Entrypoint**: `main.go` calls `cmd.Execute()` to start the Kong CLI application.
10- **Commands (`cmd/`)**: Each data importer is a self-contained package within a subdirectory (e.g., `cmd/goodreads/`, `cmd/steam/`). This is the primary location for adding or modifying importer logic.
11- **Shared Logic (`internal/`)**: Contains reusable packages for common functionality:
12 - `config`: Viper-based configuration management.
13 - `fileutil`: Helpers for writing Markdown and JSON files.
14 - `datastore`: SQLite and Datasette integration.
15 - `errors`: Custom error types (e.g., for rate limiting).
16- **Configuration**: Managed via a `config.yaml` file. CLI flags take precedence over config file settings.
17- **Output**: Data is written to `json/` and `markdown/` directories by default.
18- **Caching**: API responses are cached in the `cache/` directory, with subdirectories for each importer, to minimize external calls.
19
20## Developer Workflow
21
22The project uses `Taskfile.yml` for task automation.
23
24- **Build & Test**: `task build` - This is the primary command for development. It automatically runs tests, lints the code, and compiles the binary to `build/hermes`.
25- **Run Tests**: `task test` - Runs all tests and generates a coverage report in `coverage/`.
26- **Lint Code**: `task lint` - Runs `golangci-lint`.
27- **Run the CLI**: For development, use `go run . <command> [flags]`. For example: `go run . import goodreads -f path/to/export.csv`.
28
29## Key Development Patterns
30
31- **Adding a New Importer**:
32 1. Create a new package under `cmd/`.
33 2. Mimic the structure of an existing importer (e.g., `cmd/goodreads`):
34 - `cmd.go`: Kong command definition.
35 - `parser.go`: Logic for parsing the source data file.
36 - `types.go`: Structs for the data models.
37 - `api.go` (or similar): Client for external APIs (e.g., OMDB, OpenLibrary).
38 - `cache.go`, `json.go`, `markdown.go`: Handlers for caching and output formats.
39 3. Add the new command to `cmd/root.go`.
40
41- **Error Handling**:
42 - Return errors up the call stack.
43 - Wrap errors with context using `fmt.Errorf("...: %w", err)` to provide a clear trace.
44 - Use custom error types from `internal/errors` where applicable.
45
46- **Utilities**:
47 - Always use helpers from `internal/` for common tasks like file writing (`fileutil`) and configuration (`config`).
48 - Contribute new, reusable logic back to the `internal/` packages.
49
50- **Dependencies**:
51 - The project uses Go modules. Key libraries include `kong` for the CLI, `viper` for configuration, and `modernc.org/sqlite` for the database. Add new dependencies to `go.mod` only when necessary.
52
53## Gemini Agent Specific Notes
54- Always use `task build` to build the project.
lepinkainen/hermes · CLAUDE.md
@@ +1 @@
1# CLAUDE.md
2
3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
5Refer to llm-shared/project_tech_stack.md for core technology choices, build system configuration, and library preferences.
6
7## Key Commands
8
9- `task` or `task build` - Build the application (runs tests and lint first)
10- `task test` - Run tests with coverage report (generates coverage/coverage.html)
11- `task lint` - Run golangci-lint
12- `task clean` - Clean build artifacts
13- `task upgrade-deps` - Update all dependencies
14- `task build-linux` - Cross-compile for Linux
15- `task test-ci` - Run tests for CI (with ci build tag)
16
17**Running the application:**
18
19- `./build/hermes --help` - View available commands
20- `./build/hermes import goodreads --help` - View importer-specific options
21- `./build/hermes enhance --help` - View enhance command options
22- `go run . import goodreads -f goodreads_library_export.csv` - Run directly without building
23- `go run . import goodreads --automated --headful` - Automated Goodreads export download (Chrome required)
24- `go run . import goodreads --automated --dry-run` - Test automation without import
25- `go run . enhance -d markdown/imdb --tmdb-generate-content` - Enhance existing notes with TMDB data
26
27**Development workflow:**
28
29- Tests must pass before builds (enforced by Taskfile dependencies)
30- Always run `goimports -w .` after modifying Go files
31- Use `go test ./...` for quick test runs during development
32
33## Architecture Overview
34
35Hermes is a data import/export tool that converts exports from various sources (Goodreads, IMDb, Letterboxd, Steam) into unified formats (JSON, Markdown, SQLite/Datasette). It also provides an `enhance` command to enrich existing markdown notes with TMDB data.
36
37**Key Components:**
38
39- `cmd/root.go` - Kong-based CLI structure with nested commands
40- `cmd/{source}/` - Each data source has its own package (goodreads, imdb, letterboxd, steam)
41- `cmd/enhance/` - Enhance existing markdown notes with TMDB data
42- `internal/` - Shared utilities and packages
43 - `cache/` - API response caching
44 - `cmdutil/` - Command setup helpers
45 - `config/` - Global configuration management
46 - `datastore/` - SQLite/Datasette integration
47 - `enrichment/` - TMDB enrichment functionality
48 - `errors/` - Custom error types
49 - `fileutil/` - File operations, markdown/JSON utilities
50 - `tmdb/` - TMDB API client
51 - `tui/` - Interactive terminal UI for TMDB selection
52
53**Standard Importer Structure:**
54
55```plain
56cmd/{source}/
57├── cmd.go # Command setup and execution
58├── parser.go # Input data parsing
59├── types.go # Data models
60├── {api}.go # External API integration (e.g., omdb.go, openlibrary.go)
61├── cache.go # API response caching
62├── json.go # JSON output formatting
63├── markdown.go # Markdown output formatting
64├── testdata/ # Test fixtures and expected outputs
65└── *_test.go # Unit tests
66```
67
68## CLI Framework (Kong)
69
70- Uses Kong for command-line parsing (defined in `cmd/root.go`)
71- CLI structure: `CLI` struct contains global flags and `ImportCmd` with subcommands
72- Each importer command (GoodreadsCmd, IMDBCmd, etc.) implements a `Run() error` method
73- Kong automatically handles help text, usage messages, and error handling
74- Commands read from config file if CLI flags not provided (CLI flags take precedence)
75
76**Adding a new importer command:**
77
781. Add command struct to `cmd/root.go` (e.g., `type NewSourceCmd struct`)
792. Add struct field to `ImportCmd` with cmd and help tags
803. Implement `Run() error` method that calls the importer package
814. Follow pattern of reading from config with CLI flag override
82
83## Enhance Command
84
85The `enhance` command enriches existing markdown notes with TMDB data without re-importing from original sources.
86
87**Usage:**
88
89```bash
90# Basic usage - enhance all notes in a directory
91./build/hermes enhance -d markdown/imdb
92
93# Recursive scan with TMDB content generation
94./build/hermes enhance -d markdown/letterboxd -r --tmdb-generate-content
95
96# Download cover images and generate content
97./build/hermes enhance -d markdown/imdb --tmdb-download-cover --tmdb-generate-content
98
99# Interactive mode for manual TMDB selection
100./build/hermes enhance -d markdown/letterboxd --tmdb-interactive
101
102# Dry run to see what would be enhanced
103./build/hermes enhance -d markdown/imdb --dry-run
104```
105
106**Key Features:**
107
108- Scans directory for markdown files with YAML frontmatter
109- Extracts title, year, and IMDB ID from existing notes
110- Searches TMDB for matching content
111- Updates frontmatter with TMDB ID, runtime, genres, etc.
112- Optionally downloads cover images
113- Optionally generates TMDB content sections (cast, crew, similar titles, etc.)
114- Supports interactive TUI for selecting from multiple TMDB matches
115- Skips notes that already have TMDB data (unless `--overwrite` flag is used)
116- Dry-run mode to preview changes without modifying files
117
118**Implementation:**
119
120- `cmd/enhance/cmd.go` - Command logic, file discovery, and processing
121- `cmd/enhance/parser.go` - YAML frontmatter parsing and markdown rebuilding
122- Uses `internal/enrichment` for TMDB API integration
123- Leverages existing TMDB client and TUI components
124
125## Configuration
126
127- Primary config: `config.yaml` (YAML format, auto-generated on first run)
128- CLI flags override config file values
129- Global settings in `cmd/root.go`: output directories, overwrite flag, datasette config
130- Command-specific config uses namespaced keys (e.g., `goodreads.csvfile`, `steam.apikey`)
131- Viper manages config loading with defaults in `initConfig()`
132
133## Development Patterns
134
135**Adding New Importers:**
136
1371. Create new package under `cmd/{source}/`
1382. Implement standard structure (cmd.go, parser.go, types.go, etc.)
1393. Add command struct and Run() method to `cmd/root.go`
1404. Add struct field to `ImportCmd` in `cmd/root.go`
1415. Follow existing patterns for API integration, caching, and output formatting
1426. Add tests in `testdata/` subdirectory
143
144**Common Utilities:**
145
146- `internal/cmdutil` - Command setup helpers
147- `internal/fileutil` - File operations, markdown/JSON utilities
148- `internal/config` - Global configuration management
149- `internal/datastore` - SQLite/Datasette integration
150- `internal/cache` - API response caching
151- `internal/errors` - Custom error types (e.g., RateLimitError)
152
153**API Integration:**
154
155- All API responses cached in SQLite database (`cache.db` in project root, configurable via `cache.dbfile`)
156- Cache TTL defaults to 720h (30 days), configurable via `cache.ttl`
157- Implement API client logic within relevant command package (e.g., `cmd/goodreads/openlibrary.go`)
158- Respect API rate limits using delays (`time.Sleep`) or by handling specific rate limit errors
159- Handle common API errors gracefully (log warnings for 404s, retry or fail on persistent errors)
160- Use existing patterns from OMDB or OpenLibrary integration
161
162**Error Handling:**
163
164- Use standard Go error handling (`errors.New`, `fmt.Errorf`)
165- Return errors up the call stack for handling by Kong's command execution
166- Wrap errors with context: `fmt.Errorf("failed to process item %s: %w", itemID, err)`
167- Use custom error types from `internal/errors/` for specific conditions
168- Log significant errors but return them to let top level handle exit codes
169
170## Caching Patterns
171
172Use the appropriate caching strategy from `internal/cache`:
173
174- **`cache.GetOrFetch()`** - Cache all responses with global TTL (default 30 days)
175 - Use for: Steam games, TMDB details by ID
176 - Example: `cache.GetOrFetch("steam_cache", appID, fetchFunc)`
177
178- **`cache.GetOrFetchWithPolicy()`** - Cache only certain responses (conditional)
179 - Use for: TMDB searches (don't cache empty results)
180 - Example: `cache.GetOrFetchWithPolicy("tmdb_cache", key, fetchFunc, shouldCache)`
181
182- **`cache.GetOrFetchWithTTL()`** - Different TTLs for different result types (negative caching)
183 - Use for: Goodreads books (7 days for "not found", 30 days for successful)
184 - Helper: `cache.SelectNegativeCacheTTL(func(r *CachedResult) bool { return r.NotFound })`
185 - Example: See `cmd/goodreads/cache.go` for reference implementation
186
187**When adding new cached operations:**
1881. Choose appropriate strategy (GetOrFetch, GetOrFetchWithPolicy, or GetOrFetchWithTTL)
1892. Design deterministic cache keys (normalize if needed)
1903. Add table schema to `internal/cache/schema.go`
1914. Add table name to `ValidCacheTableNames` map
1925. Add source to cache invalidation in `internal/cache/cmd.go`
193
194**For detailed guidance:**
195- Developer guide: `docs/cache-architecture.md`
196- User documentation: `docs/caching.md`
197- Architecture decisions: `docs/decisions/001-cache-architecture.md`
198
199## Testing Requirements
200
201- Write unit tests for parsing logic, API interaction, and output generation
202- Test files in same package with `_test.go` suffix
203- Tests must pass before builds (enforced by Taskfile)
204- Use `testdata/` subdirectory within each command package for fixtures
205- Employ table-driven tests for validating multiple input cases
206- Use `//go:build !ci` to skip tests in CI that require external dependencies
207
208## Datasette Integration
209
210- Supports both local SQLite and remote Datasette storage
211- `internal/datastore` provides unified interface
212- Configuration under `datasette:` key in config (enabled, mode, dbfile, remote_url, api_token)
213- Local mode writes to `hermes.db`, remote mode uses API
214- Enable via `--datasette` flag or config file
215
216## Logging
217
218- Uses `log/slog` with custom handler from `github.com/lepinkainen/humanlog`
219- Initialized in `cmd/root.go` with `slog.LevelInfo` default
220- `InfoLevel` for progress messages (starting import, items processed)
221- `DebugLevel` for verbose debugging info (API request/response details, cache hits/misses)
222- `WarnLevel` for recoverable issues (skipping items but continuing)
223- `ErrorLevel` for significant problems before returning an error
224
225## Output Formats & Handling
226
227- Default output directories (`markdown/`, `json/`) set in `cmd/root.go`, configurable via `config.yaml`
228- Commands allow specifying subdirectories for output via `-o` flag (e.g., `markdown/goodreads/`)
229- Use `internal/fileutil` for writing files (WriteMarkdownFile for Markdown, WriteJSONFile for JSON); compose markdown notes with `internal/obsidian` (Frontmatter, TagSet, BuildNoteMarkdown)
230- Markdown files use YAML frontmatter (Obsidian-compatible)
231- Follow existing patterns for Markdown frontmatter and JSON structure for each data type
232- Respect `--overwrite` flag logic
233
234## Important Notes
235
236- Go-only project (Go 1.24+)
237- Follows standard Go project layout and idioms
238- Each importer handles its own data enrichment and API integration
239- Use `goimports -w .` after making changes (not gofmt)
240- Use shared utility functions from `internal/` packages
241- Build artifacts go to `build/` directory
242- Cache stored in SQLite database (`cache.db`, safe to delete for cache invalidation)
243
@@ −1 +1 @@
1−# Gemini Agent Guide for Hermes
1+# CLAUDE.md
22
3−This guide provides essential information for developing in the Hermes codebase.
3+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
44
5−## Project Overview & Architecture
5+Refer to llm-shared/project_tech_stack.md for core technology choices, build system configuration, and library preferences.
66
7−Hermes is a Go-based CLI tool for importing data from sources like Goodreads, IMDb, and Steam, and exporting it into Markdown, JSON, or SQLite/Datasette formats.
7+## Key Commands
88
9−- **Entrypoint**: `main.go` calls `cmd.Execute()` to start the Kong CLI application.
10−- **Commands (`cmd/`)**: Each data importer is a self-contained package within a subdirectory (e.g., `cmd/goodreads/`, `cmd/steam/`). This is the primary location for adding or modifying importer logic.
11−- **Shared Logic (`internal/`)**: Contains reusable packages for common functionality:
12− - `config`: Viper-based configuration management.
13− - `fileutil`: Helpers for writing Markdown and JSON files.
14− - `datastore`: SQLite and Datasette integration.
15− - `errors`: Custom error types (e.g., for rate limiting).
16−- **Configuration**: Managed via a `config.yaml` file. CLI flags take precedence over config file settings.
17−- **Output**: Data is written to `json/` and `markdown/` directories by default.
18−- **Caching**: API responses are cached in the `cache/` directory, with subdirectories for each importer, to minimize external calls.
9+- `task` or `task build` - Build the application (runs tests and lint first)
10+- `task test` - Run tests with coverage report (generates coverage/coverage.html)
11+- `task lint` - Run golangci-lint
12+- `task clean` - Clean build artifacts
13+- `task upgrade-deps` - Update all dependencies
14+- `task build-linux` - Cross-compile for Linux
15+- `task test-ci` - Run tests for CI (with ci build tag)
1916
20−## Developer Workflow
17+**Running the application:**
2118
22−The project uses `Taskfile.yml` for task automation.
19+- `./build/hermes --help` - View available commands
20+- `./build/hermes import goodreads --help` - View importer-specific options
21+- `./build/hermes enhance --help` - View enhance command options
22+- `go run . import goodreads -f goodreads_library_export.csv` - Run directly without building
23+- `go run . import goodreads --automated --headful` - Automated Goodreads export download (Chrome required)
24+- `go run . import goodreads --automated --dry-run` - Test automation without import
25+- `go run . enhance -d markdown/imdb --tmdb-generate-content` - Enhance existing notes with TMDB data
2326
24−- **Build & Test**: `task build` - This is the primary command for development. It automatically runs tests, lints the code, and compiles the binary to `build/hermes`.
25−- **Run Tests**: `task test` - Runs all tests and generates a coverage report in `coverage/`.
26−- **Lint Code**: `task lint` - Runs `golangci-lint`.
27−- **Run the CLI**: For development, use `go run . <command> [flags]`. For example: `go run . import goodreads -f path/to/export.csv`.
27+**Development workflow:**
2828
29−## Key Development Patterns
29+- Tests must pass before builds (enforced by Taskfile dependencies)
30+- Always run `goimports -w .` after modifying Go files
31+- Use `go test ./...` for quick test runs during development
3032
31−- **Adding a New Importer**:
32− 1. Create a new package under `cmd/`.
33− 2. Mimic the structure of an existing importer (e.g., `cmd/goodreads`):
34− - `cmd.go`: Kong command definition.
35− - `parser.go`: Logic for parsing the source data file.
36− - `types.go`: Structs for the data models.
37− - `api.go` (or similar): Client for external APIs (e.g., OMDB, OpenLibrary).
38− - `cache.go`, `json.go`, `markdown.go`: Handlers for caching and output formats.
39− 3. Add the new command to `cmd/root.go`.
33+## Architecture Overview
4034
41−- **Error Handling**:
42− - Return errors up the call stack.
43− - Wrap errors with context using `fmt.Errorf("...: %w", err)` to provide a clear trace.
44− - Use custom error types from `internal/errors` where applicable.
35+Hermes is a data import/export tool that converts exports from various sources (Goodreads, IMDb, Letterboxd, Steam) into unified formats (JSON, Markdown, SQLite/Datasette). It also provides an `enhance` command to enrich existing markdown notes with TMDB data.
4536
46−- **Utilities**:
47− - Always use helpers from `internal/` for common tasks like file writing (`fileutil`) and configuration (`config`).
48− - Contribute new, reusable logic back to the `internal/` packages.
37+**Key Components:**
4938
50−- **Dependencies**:
51− - The project uses Go modules. Key libraries include `kong` for the CLI, `viper` for configuration, and `modernc.org/sqlite` for the database. Add new dependencies to `go.mod` only when necessary.
39+- `cmd/root.go` - Kong-based CLI structure with nested commands
40+- `cmd/{source}/` - Each data source has its own package (goodreads, imdb, letterboxd, steam)
41+- `cmd/enhance/` - Enhance existing markdown notes with TMDB data
42+- `internal/` - Shared utilities and packages
43+ - `cache/` - API response caching
44+ - `cmdutil/` - Command setup helpers
45+ - `config/` - Global configuration management
46+ - `datastore/` - SQLite/Datasette integration
47+ - `enrichment/` - TMDB enrichment functionality
48+ - `errors/` - Custom error types
49+ - `fileutil/` - File operations, markdown/JSON utilities
50+ - `tmdb/` - TMDB API client
51+ - `tui/` - Interactive terminal UI for TMDB selection
5252
53−## Gemini Agent Specific Notes
54−- Always use `task build` to build the project.
53+**Standard Importer Structure:**
54+
55+```plain
56+cmd/{source}/
57+├── cmd.go # Command setup and execution
58+├── parser.go # Input data parsing
59+├── types.go # Data models
60+├── {api}.go # External API integration (e.g., omdb.go, openlibrary.go)
61+├── cache.go # API response caching
62+├── json.go # JSON output formatting
63+├── markdown.go # Markdown output formatting
64+├── testdata/ # Test fixtures and expected outputs
65+└── *_test.go # Unit tests
66+```
67+
68+## CLI Framework (Kong)
69+
70+- Uses Kong for command-line parsing (defined in `cmd/root.go`)
71+- CLI structure: `CLI` struct contains global flags and `ImportCmd` with subcommands
72+- Each importer command (GoodreadsCmd, IMDBCmd, etc.) implements a `Run() error` method
73+- Kong automatically handles help text, usage messages, and error handling
74+- Commands read from config file if CLI flags not provided (CLI flags take precedence)
75+
76+**Adding a new importer command:**
77+
78+1. Add command struct to `cmd/root.go` (e.g., `type NewSourceCmd struct`)
79+2. Add struct field to `ImportCmd` with cmd and help tags
80+3. Implement `Run() error` method that calls the importer package
81+4. Follow pattern of reading from config with CLI flag override
82+
83+## Enhance Command
84+
85+The `enhance` command enriches existing markdown notes with TMDB data without re-importing from original sources.
86+
87+**Usage:**
88+
89+```bash
90+# Basic usage - enhance all notes in a directory
91+./build/hermes enhance -d markdown/imdb
92+
93+# Recursive scan with TMDB content generation
94+./build/hermes enhance -d markdown/letterboxd -r --tmdb-generate-content
95+
96+# Download cover images and generate content
97+./build/hermes enhance -d markdown/imdb --tmdb-download-cover --tmdb-generate-content
98+
99+# Interactive mode for manual TMDB selection
100+./build/hermes enhance -d markdown/letterboxd --tmdb-interactive
101+
102+# Dry run to see what would be enhanced
103+./build/hermes enhance -d markdown/imdb --dry-run
104+```
105+
106+**Key Features:**
107+
108+- Scans directory for markdown files with YAML frontmatter
109+- Extracts title, year, and IMDB ID from existing notes
110+- Searches TMDB for matching content
111+- Updates frontmatter with TMDB ID, runtime, genres, etc.
112+- Optionally downloads cover images
113+- Optionally generates TMDB content sections (cast, crew, similar titles, etc.)
114+- Supports interactive TUI for selecting from multiple TMDB matches
115+- Skips notes that already have TMDB data (unless `--overwrite` flag is used)
116+- Dry-run mode to preview changes without modifying files
117+
118+**Implementation:**
119+
120+- `cmd/enhance/cmd.go` - Command logic, file discovery, and processing
121+- `cmd/enhance/parser.go` - YAML frontmatter parsing and markdown rebuilding
122+- Uses `internal/enrichment` for TMDB API integration
123+- Leverages existing TMDB client and TUI components
124+
125+## Configuration
126+
127+- Primary config: `config.yaml` (YAML format, auto-generated on first run)
128+- CLI flags override config file values
129+- Global settings in `cmd/root.go`: output directories, overwrite flag, datasette config
130+- Command-specific config uses namespaced keys (e.g., `goodreads.csvfile`, `steam.apikey`)
131+- Viper manages config loading with defaults in `initConfig()`
132+
133+## Development Patterns
134+
135+**Adding New Importers:**
136+
137+1. Create new package under `cmd/{source}/`
138+2. Implement standard structure (cmd.go, parser.go, types.go, etc.)
139+3. Add command struct and Run() method to `cmd/root.go`
140+4. Add struct field to `ImportCmd` in `cmd/root.go`
141+5. Follow existing patterns for API integration, caching, and output formatting
142+6. Add tests in `testdata/` subdirectory
143+
144+**Common Utilities:**
145+
146+- `internal/cmdutil` - Command setup helpers
147+- `internal/fileutil` - File operations, markdown/JSON utilities
148+- `internal/config` - Global configuration management
149+- `internal/datastore` - SQLite/Datasette integration
150+- `internal/cache` - API response caching
151+- `internal/errors` - Custom error types (e.g., RateLimitError)
152+
153+**API Integration:**
154+
155+- All API responses cached in SQLite database (`cache.db` in project root, configurable via `cache.dbfile`)
156+- Cache TTL defaults to 720h (30 days), configurable via `cache.ttl`
157+- Implement API client logic within relevant command package (e.g., `cmd/goodreads/openlibrary.go`)
158+- Respect API rate limits using delays (`time.Sleep`) or by handling specific rate limit errors
159+- Handle common API errors gracefully (log warnings for 404s, retry or fail on persistent errors)
160+- Use existing patterns from OMDB or OpenLibrary integration
161+
162+**Error Handling:**
163+
164+- Use standard Go error handling (`errors.New`, `fmt.Errorf`)
165+- Return errors up the call stack for handling by Kong's command execution
166+- Wrap errors with context: `fmt.Errorf("failed to process item %s: %w", itemID, err)`
167+- Use custom error types from `internal/errors/` for specific conditions
168+- Log significant errors but return them to let top level handle exit codes
169+
170+## Caching Patterns
171+
172+Use the appropriate caching strategy from `internal/cache`:
173+
174+- **`cache.GetOrFetch()`** - Cache all responses with global TTL (default 30 days)
175+ - Use for: Steam games, TMDB details by ID
176+ - Example: `cache.GetOrFetch("steam_cache", appID, fetchFunc)`
177+
178+- **`cache.GetOrFetchWithPolicy()`** - Cache only certain responses (conditional)
179+ - Use for: TMDB searches (don't cache empty results)
180+ - Example: `cache.GetOrFetchWithPolicy("tmdb_cache", key, fetchFunc, shouldCache)`
181+
182+- **`cache.GetOrFetchWithTTL()`** - Different TTLs for different result types (negative caching)
183+ - Use for: Goodreads books (7 days for "not found", 30 days for successful)
184+ - Helper: `cache.SelectNegativeCacheTTL(func(r *CachedResult) bool { return r.NotFound })`
185+ - Example: See `cmd/goodreads/cache.go` for reference implementation
186+
187+**When adding new cached operations:**
188+1. Choose appropriate strategy (GetOrFetch, GetOrFetchWithPolicy, or GetOrFetchWithTTL)
189+2. Design deterministic cache keys (normalize if needed)
190+3. Add table schema to `internal/cache/schema.go`
191+4. Add table name to `ValidCacheTableNames` map
192+5. Add source to cache invalidation in `internal/cache/cmd.go`
193+
194+**For detailed guidance:**
195+- Developer guide: `docs/cache-architecture.md`
196+- User documentation: `docs/caching.md`
197+- Architecture decisions: `docs/decisions/001-cache-architecture.md`
198+
199+## Testing Requirements
200+
201+- Write unit tests for parsing logic, API interaction, and output generation
202+- Test files in same package with `_test.go` suffix
203+- Tests must pass before builds (enforced by Taskfile)
204+- Use `testdata/` subdirectory within each command package for fixtures
205+- Employ table-driven tests for validating multiple input cases
206+- Use `//go:build !ci` to skip tests in CI that require external dependencies
207+
208+## Datasette Integration
209+
210+- Supports both local SQLite and remote Datasette storage
211+- `internal/datastore` provides unified interface
212+- Configuration under `datasette:` key in config (enabled, mode, dbfile, remote_url, api_token)
213+- Local mode writes to `hermes.db`, remote mode uses API
214+- Enable via `--datasette` flag or config file
215+
216+## Logging
217+
218+- Uses `log/slog` with custom handler from `github.com/lepinkainen/humanlog`
219+- Initialized in `cmd/root.go` with `slog.LevelInfo` default
220+- `InfoLevel` for progress messages (starting import, items processed)
221+- `DebugLevel` for verbose debugging info (API request/response details, cache hits/misses)
222+- `WarnLevel` for recoverable issues (skipping items but continuing)
223+- `ErrorLevel` for significant problems before returning an error
224+
225+## Output Formats & Handling
226+
227+- Default output directories (`markdown/`, `json/`) set in `cmd/root.go`, configurable via `config.yaml`
228+- Commands allow specifying subdirectories for output via `-o` flag (e.g., `markdown/goodreads/`)
229+- Use `internal/fileutil` for writing files (WriteMarkdownFile for Markdown, WriteJSONFile for JSON); compose markdown notes with `internal/obsidian` (Frontmatter, TagSet, BuildNoteMarkdown)
230+- Markdown files use YAML frontmatter (Obsidian-compatible)
231+- Follow existing patterns for Markdown frontmatter and JSON structure for each data type
232+- Respect `--overwrite` flag logic
233+
234+## Important Notes
235+
236+- Go-only project (Go 1.24+)
237+- Follows standard Go project layout and idioms
238+- Each importer handles its own data enrichment and API integration
239+- Use `goimports -w .` after making changes (not gofmt)
240+- Use shared utility functions from `internal/` packages
241+- Build artifacts go to `build/` directory
242+- Cache stored in SQLite database (`cache.db`, safe to delete for cache invalidation)
243+
