# Project Context ## What This File Is This is the persistent context file for Claude Code. Keep it concise and useful. ## CLAUDE.md Maintenance Rules - Keep this file under 160 lines - Only record decisions, not explanations of common knowledge - When adding something, check if anything existing is now outdated and remove it - Use short bullet points, not paragraphs - No boilerplate or filler text - If a section grows past 10 items, consolidate or prune the least relevant ones - Format: what we chose + why in one line (e.g., "imv over feh — WebP/Wayland support") ## Overview - Fork of [ayn2op/discordo](https://github.com/ayn2op/discordo) — a Discord TUI client - Upstream: `https://github.com/ayn2op/discordo.git` - Our repo: `https://gogs.altsol.dev/claude/discordo-plus.git` (branch: `master`) - Binary name: `discordo-plus` (installed to `/usr/local/bin/`) ## Stack - Go (module: `github.com/ayn2op/discordo`) - TUI: `github.com/ayn2op/tview` (custom tview fork) + `tcell/v3` - Discord API: `arikawa/v3` + `ningen/v3` (state management + Discord markdown) - Markdown: `goldmark` parser + `chroma/v2` syntax highlighting - Config: TOML via `BurntSushi/toml`, file at `~/.config/discordo/config.toml` - Cache: `~/.cache/discordo/` (attachments, logs, state) ## Architecture - `main.go` → `cmd/root.go` (app init) → `internal/ui/` (TUI layers) - `internal/ui/chat/` — core chat UI: `messages_list.go` (1500+ lines, message rendering/keybinds), `message_input.go`, `guilds_tree.go`, `attachments_picker.go` - `internal/markdown/renderer.go` — AST→styled lines, handles Discord markdown flavors - `internal/config/` — `config.go` (struct + loader), `config.toml` (defaults, embedded), `keybinds.go`, `theme.go` - `internal/consts/` — app name, cache dir - `internal/ui/chat/guildstate.go` — persists guild expand/collapse state to `~/.cache/discordo/state.json` - Rendering pipeline: messages → `tview.LineBuilder` → `[]tview.Line` (segments with `tcell.Style`) - URLs get `style.Url(rawURL)` metadata for OSC 8 terminal hyperlinks - External commands (editor, image viewer) use `app.Suspend()` pattern — suspends TUI, runs command, resumes ## Key Patterns - Keybinds: defined in `config/keybinds.go` structs, matched in `HandleEvent()` via `keybind.Matches()` - Help tooltips: `ShortHelp()` (bottom bar, contextual) and `FullHelp()` (full overlay via `?`) - Attachments: downloaded to `~/.cache/discordo/attachments/`, opened via configured viewer or `open.Start()` - Embeds: rendered with `▎` bar prefix, wrapped to viewport width, markdown in descriptions - Config defaults embedded via `//go:embed config.toml` ## Our Changes (vs upstream) - **Image viewer**: `image_viewer` config (default: `mpv`) — opens image attachments in configured viewer with TUI suspend/resume instead of browser - **mpv geometry**: `viewerArgs()` auto-detects terminal geometry via `xdotool` on X11, passes `--geometry`, `--force-window`, `--loop-file=inf` to mpv - **Save image**: `save_image` keybind (`S`) — saves image attachment to `image_save_dir` - **Attachment URL fix**: split `builder.Write(filename+"\n"+url)` into proper `NewLine()` + `.Url()` style - **Supported image types**: jpeg, png, webp, gif (via `supportedImageTypes` map) - **ShortHelp**: `o` (open) now shows in bottom tooltip bar when message has attachments/URLs - **Help keybind**: changed from `ctrl+.` to `?` — `ctrl+.` not reliably handled by terminals - **Edit config**: `E` keybind (only active in help overlay) opens config in `$EDITOR`/vim via `app.Suspend()` - **Editor default**: falls back to `vim` when `editor = "default"` and `$EDITOR` is unset - **Guild state persistence**: expanded/collapsed guild state saved to `~/.cache/discordo/state.json`, restored on launch via `guildstate.go` - **Focus on channel select**: AutoFocus now targets messages list instead of message input when selecting a channel ## Config Fields We Added - `image_viewer` — external image viewer command (default: `"mpv"`, `"default"` = system opener) - `image_save_dir` — directory for saved images (supports `~/`, default: current dir) - `keybinds.messages_list.save_image` — save image keybind (default: `S`) - `keybinds.edit_config` — open config in editor from help overlay (default: `E`) - `keybinds.toggle_help` — changed default from `ctrl+.` to `?` ## Build & Run - Build: `go build -o discordo-plus .` - Install: `sudo mv discordo-plus /usr/local/bin/` - Run: `discordo-plus` - Test: `go test ./...` (only config + keyring packages have tests) - Dependencies: `mpv` (or configured image viewer), `xdotool` (optional, X11 geometry detection) ## Git - Identity: `claude ` - Commit style: `type(scope): description` (e.g., `feat(ui/chat): add image viewer`) - Branch: `master` ## Known Issues - Discord ToS discourages third-party clients — use at own risk - `xdotool` geometry detection only works on X11; on Wayland use compositor window rules for mpv positioning - `viewerArgs()` only adds special flags for mpv; other viewers get plain `viewer path` invocation