Guidance for AI assistants working with the greg codebase.
greg is a unified terminal UI for streaming anime, movies, TV shows and reading manga with AniList progress tracking.
- Built with Go 1.25.3
- TUI framework: Bubble Tea (charmbracelet/bubbletea)
- Player: mpv via gopv IPC library
- Database: SQLite with GORM
- Config: Viper with XDG support
# Essential commands
just build # Build dev binary
just test # Run unit tests
just lint # Run linters
just fmt # Format code
just pre-commit # fmt + lint + test (run before commits)
# Development
just dev # Hot reload with air
just run # Build and run
just doctor # Check dev environment
# Testing
just test-coverage # Generate coverage report
just test-integration # Integration tests (requires network)
just test-race # Race condition detection
just test-pkg <name> # Test specific packagecmd/greg/ Entry point (main.go)
internal/
├── tui/ Bubble Tea UI
│ ├── model.go Main app model (1,377 lines, refactored from 4,822)
│ ├── *_handlers.go Message handlers (organized by domain)
│ │ ├── keyboard_handlers.go Keyboard input routing
│ │ ├── navigation_handlers.go Navigation messages
│ │ ├── media_message_handlers.go Media operations
│ │ ├── anilist_handlers.go AniList integration
│ │ ├── download_handlers.go Download operations
│ │ ├── watchparty_handlers.go WatchParty features
│ │ ├── manga_handlers.go Manga operations
│ │ ├── debug_handlers.go Debug utilities
│ │ └── state_handlers.go State management
│ ├── playback.go Playback operations (1,375 lines)
│ ├── components/ Individual views (home, search, results, etc.)
│ └── styles/ Oxocarbon color scheme
├── providers/ Streaming providers
│ ├── provider.go Core interface
│ ├── registry.go Provider registration
│ ├── hianime/ Default anime provider
│ ├── allanime/ Alternative anime
│ ├── sflix/ Default movies/TV
│ ├── flixhq/ Alternative movies/TV
│ ├── hdrezka/ Russian provider (multi-language)
│ └── mangaprovider/comix/ Manga provider
├── player/mpv/ mpv integration via gopv
├── tracker/anilist/ AniList OAuth2 + GraphQL
├── downloader/ Download manager with worker pool
├── database/ SQLite models (history, downloads, mappings)
└── config/ Viper config + slog logger
pkg/
├── extractors/ Stream URL extractors (megacloud, vidcloud)
└── interfaces/ Shared interfaces
All providers implement:
type Provider interface {
Name() string
Type() MediaType // Anime, Movie, TV, MovieTV, Manga, All
Search(ctx context.Context, query string) ([]Media, error)
GetTrending(ctx context.Context) ([]Media, error)
GetRecent(ctx context.Context) ([]Media, error)
GetMediaDetails(ctx context.Context, id string) (*MediaDetails, error)
GetSeasons(ctx context.Context, mediaID string) ([]Season, error)
GetEpisodes(ctx context.Context, seasonID string) ([]Episode, error)
GetStreamURL(ctx context.Context, episodeID string, quality Quality) (*StreamURL, error)
GetAvailableQualities(ctx context.Context, episodeID string) ([]Quality, error)
IsAvailable(ctx context.Context) bool
}Current providers:
| Provider | Type | Default | Notes |
|---|---|---|---|
| hianime | Anime | Yes | Fast search (~62ms) |
| allanime | Anime | No | Multiple sources per episode |
| hdrezka | Anime/Movies/TV | No | Multi-language, mostly Russian |
| sflix | Movies/TV | Yes | Large library |
| flixhq | Movies/TV | No | Multiple servers |
| comix | Manga | Yes | Default manga provider |
- Create package in
internal/providers/<name>/ - Implement Provider interface
- Use
sync.Mapfor response caching - Handle movies vs TV (empty seasons array for movies)
- Register in
internal/providers/registry.go - Write tests with
httptest.NewServerfor mocking
Important:
- Always use
context.Contextas first parameter - Wrap errors:
fmt.Errorf("operation: %w", err) - Never cache stream URLs (they expire)
- Cache media info to reduce requests
Uses gopv
// Platform-specific IPC
// Linux/macOS/WSL: Unix sockets /tmp/greg-mpv-{random}.sock
// Windows: Named pipes \\.\pipe\greg-mpv-{random}
// Key flow:
// 1. Generate socket path
// 2. Launch mpv with --input-ipc-server=<socket>
// 3. Connect via gopv.Connect() with timeout
// 4. Background goroutine polls progress every 2 seconds
// 5. Auto-return to UI when playback endsPackage Organization (Refactored Jan 2026):
The internal/tui package was refactored from a monolithic 4,822-line model.go into a modular structure:
- model.go (1,377 lines) - Core App struct, Update/View methods, state management
- Handler files (by domain):
keyboard_handlers.go- Keyboard input routing with component delegationnavigation_handlers.go- GoToSearch, GoToHome, Back, etc.media_message_handlers.go- Search, seasons, episodes, media selectionanilist_handlers.go- AniList library, tracking, mappingdownload_handlers.go- Download operations and notificationswatchparty_handlers.go- WatchParty URL generation and sharingmanga_handlers.go- Manga info and chapter navigationdebug_handlers.go- Debug popup and source inspectionstate_handlers.go- Simple state transitions
- playback.go (1,375 lines) - Playback operations, progress tracking, resume logic
All methods remain on the App struct - no architectural changes, just better organization.
Bubble Tea message-passing model:
// View states (internal/tui/model.go)
type sessionState int
const (
homeView sessionState = iota
searchView
resultsView
loadingView
errorView
seasonView
episodeView
launchingPlayerView
playingView
playbackCompletedView
anilistView
providerSelectionView
downloadsView
historyView
mangaReaderView
mangaInfoView
providerStatusView
mangaDownloadProgressView
// 18 states total
)
// Smart navigation:
// - Auto-skip season selection for single-season content
// - Auto-skip episode selection for single-episode content (movies)
// - Direct movie playback without selection screensSQLite tables (internal/database/models.go):
history- Watch history with progress trackingstatistics- Total watch time, genre statssync_queue- Pending AniList syncsdownloads- Download queue and statussettings- Key-value config cacheanilist_mappings- Provider to AniList media mappings
Hierarchy (from lowest to highest importance):
- Hard-coded defaults
~/.config/greg/config.yaml- Environment variables (
GREG_*) - Command-line flags
XDG directories:
- Config:
$XDG_CONFIG_HOME/greg/or~/.config/greg/ - Data:
$XDG_DATA_HOME/greg/or~/.local/share/greg/ - Cache:
$XDG_CACHE_HOME/greg/or~/.cache/greg/
Defaults work out of the box. No configuration required for basic usage.
The external API server at localhost:8080 is optional and experimental. It is NOT required.
- Default mode:
local- providers use internal scraping - Optional mode:
remote- delegate to external API server
This feature is not fully supported yet. When working with providers, assume local mode unless explicitly told otherwise.
- Verify provider health checks actually work
- Change manga DB storage to use chapters instead of reusing episodes field
- Add CHANGELOG
Manga reading mode has various bugs and UX issues. It works but needs polish before considered stable.
- Follow Go Code Review Comments
- Run
just fmtbefore commits (gofmt + goimports) - Run
just lint(golangci-lint) - Context as first parameter
- Wrap errors:
fmt.Errorf("context: %w", err) - Never panic in library code
- Comment all exported types/functions
- Aim for 80%+ test coverage on new code
just test # Unit tests
just test-integration # Requires network
just test-race # Race detector
just test-coverage # HTML report
just test-pkg providers # Specific packageWriting tests:
- Unit tests: Mock HTTP with
httptest.NewServer - Table-driven tests for parsing/validation
- Integration tests: Tag with
//go:build integration - TUI snapshot tests exist in
internal/tui/
Core libraries:
- cobra - CLI framework
- viper - Configuration
- bubbletea, lipgloss, bubbles - TUI
- goquery - HTML parsing
- gorm - SQLite ORM
- oauth2 - AniList auth
- gopv - mpv IPC (local fork)
External tools:
- mpv (required) - Video playback
- ffmpeg (required for downloads) - Subtitle embedding
- air (optional) - Hot reload
- Version info injected via ldflags at build time (see justfile)
- Entry point is
cmd/greg/main.go - AniList sync triggers at 85% watch threshold
- Platform detection is automatic (Linux/macOS/Windows/WSL)
- WSL uses Linux mpv (not Windows mpv.exe) for better IPC compatibility
README.org- User documentationdocs/dev/ARCHITECTURE.org- Detailed system designdocs/PROVIDERS.org- Provider development guidedocs/CONFIG.org- Configuration referencedocs/dev/CONTRIBUTING.org- Contribution guidelinesAGENTS.md- AI agent descriptions for this project