CLAUDE.md
CLAUDE.mdCLAUDE.mdroot
Quality
89/100
Scores the file, not the repository.Length
1,476 words
18 headings · 2 code blocksRepository
5
— · pushed 14 days agoLast changed
3 days ago
First indexed 3 days ago.1# CLAUDE.md23This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.45Refer to llm-shared/project_tech_stack.md for core technology choices, build system configuration, and library preferences.67## Key Commands89- `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-lint12- `task clean` - Clean build artifacts13- `task upgrade-deps` - Update all dependencies14- `task build-linux` - Cross-compile for Linux15- `task test-ci` - Run tests for CI (with ci build tag)1617**Running the application:**1819- `./build/hermes --help` - View available commands20- `./build/hermes import goodreads --help` - View importer-specific options21- `./build/hermes enhance --help` - View enhance command options22- `go run . import goodreads -f goodreads_library_export.csv` - Run directly without building23- `go run . import goodreads --automated --headful` - Automated Goodreads export download (Chrome required)24- `go run . import goodreads --automated --dry-run` - Test automation without import25- `go run . enhance -d markdown/imdb --tmdb-generate-content` - Enhance existing notes with TMDB data2627**Development workflow:**2829- Tests must pass before builds (enforced by Taskfile dependencies)30- Always run `goimports -w .` after modifying Go files31- Use `go test ./...` for quick test runs during development3233## Architecture Overview3435Hermes 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.3637**Key Components:**3839- `cmd/root.go` - Kong-based CLI structure with nested commands40- `cmd/{source}/` - Each data source has its own package (goodreads, imdb, letterboxd, steam)41- `cmd/enhance/` - Enhance existing markdown notes with TMDB data42- `internal/` - Shared utilities and packages43 - `cache/` - API response caching44 - `cmdutil/` - Command setup helpers45 - `config/` - Global configuration management46 - `datastore/` - SQLite/Datasette integration47 - `enrichment/` - TMDB enrichment functionality48 - `errors/` - Custom error types49 - `fileutil/` - File operations, markdown/JSON utilities50 - `tmdb/` - TMDB API client51 - `tui/` - Interactive terminal UI for TMDB selection5253**Standard Importer Structure:**5455```plain56cmd/{source}/57├── cmd.go # Command setup and execution58├── parser.go # Input data parsing59├── types.go # Data models60├── {api}.go # External API integration (e.g., omdb.go, openlibrary.go)61├── cache.go # API response caching62├── json.go # JSON output formatting63├── markdown.go # Markdown output formatting64├── testdata/ # Test fixtures and expected outputs65└── *_test.go # Unit tests66```6768## CLI Framework (Kong)6970- Uses Kong for command-line parsing (defined in `cmd/root.go`)71- CLI structure: `CLI` struct contains global flags and `ImportCmd` with subcommands72- Each importer command (GoodreadsCmd, IMDBCmd, etc.) implements a `Run() error` method73- Kong automatically handles help text, usage messages, and error handling74- Commands read from config file if CLI flags not provided (CLI flags take precedence)7576**Adding a new importer command:**77781. Add command struct to `cmd/root.go` (e.g., `type NewSourceCmd struct`)792. Add struct field to `ImportCmd` with cmd and help tags803. Implement `Run() error` method that calls the importer package814. Follow pattern of reading from config with CLI flag override8283## Enhance Command8485The `enhance` command enriches existing markdown notes with TMDB data without re-importing from original sources.8687**Usage:**8889```bash90# Basic usage - enhance all notes in a directory91./build/hermes enhance -d markdown/imdb9293# Recursive scan with TMDB content generation94./build/hermes enhance -d markdown/letterboxd -r --tmdb-generate-content9596# Download cover images and generate content97./build/hermes enhance -d markdown/imdb --tmdb-download-cover --tmdb-generate-content9899# Interactive mode for manual TMDB selection100./build/hermes enhance -d markdown/letterboxd --tmdb-interactive101102# Dry run to see what would be enhanced103./build/hermes enhance -d markdown/imdb --dry-run104```105106**Key Features:**107108- Scans directory for markdown files with YAML frontmatter109- Extracts title, year, and IMDB ID from existing notes110- Searches TMDB for matching content111- Updates frontmatter with TMDB ID, runtime, genres, etc.112- Optionally downloads cover images113- Optionally generates TMDB content sections (cast, crew, similar titles, etc.)114- Supports interactive TUI for selecting from multiple TMDB matches115- Skips notes that already have TMDB data (unless `--overwrite` flag is used)116- Dry-run mode to preview changes without modifying files117118**Implementation:**119120- `cmd/enhance/cmd.go` - Command logic, file discovery, and processing121- `cmd/enhance/parser.go` - YAML frontmatter parsing and markdown rebuilding122- Uses `internal/enrichment` for TMDB API integration123- Leverages existing TMDB client and TUI components124125## Configuration126127- Primary config: `config.yaml` (YAML format, auto-generated on first run)128- CLI flags override config file values129- Global settings in `cmd/root.go`: output directories, overwrite flag, datasette config130- Command-specific config uses namespaced keys (e.g., `goodreads.csvfile`, `steam.apikey`)131- Viper manages config loading with defaults in `initConfig()`132133## Development Patterns134135**Adding New Importers:**1361371. 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 formatting1426. Add tests in `testdata/` subdirectory143144**Common Utilities:**145146- `internal/cmdutil` - Command setup helpers147- `internal/fileutil` - File operations, markdown/JSON utilities148- `internal/config` - Global configuration management149- `internal/datastore` - SQLite/Datasette integration150- `internal/cache` - API response caching151- `internal/errors` - Custom error types (e.g., RateLimitError)152153**API Integration:**154155- 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 errors159- Handle common API errors gracefully (log warnings for 404s, retry or fail on persistent errors)160- Use existing patterns from OMDB or OpenLibrary integration161162**Error Handling:**163164- Use standard Go error handling (`errors.New`, `fmt.Errorf`)165- Return errors up the call stack for handling by Kong's command execution166- Wrap errors with context: `fmt.Errorf("failed to process item %s: %w", itemID, err)`167- Use custom error types from `internal/errors/` for specific conditions168- Log significant errors but return them to let top level handle exit codes169170## Caching Patterns171172Use the appropriate caching strategy from `internal/cache`:173174- **`cache.GetOrFetch()`** - Cache all responses with global TTL (default 30 days)175 - Use for: Steam games, TMDB details by ID176 - Example: `cache.GetOrFetch("steam_cache", appID, fetchFunc)`177178- **`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)`181182- **`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 implementation186187**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` map1925. Add source to cache invalidation in `internal/cache/cmd.go`193194**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`198199## Testing Requirements200201- Write unit tests for parsing logic, API interaction, and output generation202- Test files in same package with `_test.go` suffix203- Tests must pass before builds (enforced by Taskfile)204- Use `testdata/` subdirectory within each command package for fixtures205- Employ table-driven tests for validating multiple input cases206- Use `//go:build !ci` to skip tests in CI that require external dependencies207208## Datasette Integration209210- Supports both local SQLite and remote Datasette storage211- `internal/datastore` provides unified interface212- Configuration under `datasette:` key in config (enabled, mode, dbfile, remote_url, api_token)213- Local mode writes to `hermes.db`, remote mode uses API214- Enable via `--datasette` flag or config file215216## Logging217218- Uses `log/slog` with custom handler from `github.com/lepinkainen/humanlog`219- Initialized in `cmd/root.go` with `slog.LevelInfo` default220- `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 error224225## Output Formats & Handling226227- 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 type232- Respect `--overwrite` flag logic233234## Important Notes235236- Go-only project (Go 1.24+)237- Follows standard Go project layout and idioms238- Each importer handles its own data enrichment and API integration239- Use `goimports -w .` after making changes (not gofmt)240- Use shared utility functions from `internal/` packages241- Build artifacts go to `build/` directory242- Cache stored in SQLite database (`cache.db`, safe to delete for cache invalidation)243
Also in lepinkainen/hermes
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| lepinkainen/hermes.cursor/rules/rules.mdc · 5 | Cursor rules | stylearchdo-notagent-behaviour | 51/100 | 3 days ago | |
| lepinkainen/hermes.clinerules/project-rules.md · 5 | Cline rules | testarchapido-not+1 | 71/100 | 3 days ago | |
| lepinkainen/hermes.cursor/rules/mdc.mdc · 5 | Cursor rules | stylearchdo-notagent-behaviour | 69/100 | 3 days ago | |
| lepinkainen/hermes.cursor/rules/project-rules.mdc · 5 | Cursor rules | testlint-formatstylearch+1 | 90/100 | 3 days ago | |
| lepinkainen/hermesAGENTS.md · 5 | AGENTS.md | buildtestlint-formatstyle+3 | 96/100 | 3 days ago | |
| lepinkainen/hermesGEMINI.md · 5 | GEMINI.md | stylearchagent-behaviour | 76/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| livewire/livewireCLAUDE.md · 24k | CLAUDE.md | setupbuildteststyle+4 | 100/100 | 3 days ago | |
| filamentphp/filamentCLAUDE.md · 32k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| stacklok/toolhiveCLAUDE.md · 2.0k | CLAUDE.md | buildteststylearch+4 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| Adit-Jain-srm/NightmareNetCLAUDE.md · 45 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 3 days ago | |
| microsoft/playwrightCLAUDE.md · 94k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 3 days ago | |
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 3 days ago |
