diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index f6d0d32..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,26 +0,0 @@ -# AGENTS - -## Memory Bank Requirements -- **Always read the Memory Bank before starting any task.** -- Memory Bank lives in `memory-bank/` and contains: - - `projectbrief.md` - - `productContext.md` - - `systemPatterns.md` - - `techContext.md` - - `activeContext.md` - - `progress.md` -- The Memory Bank is the single source of project context. If a user requests **update memory bank**, review every file in the directory before making changes. -- After significant work or when insights are gained, update `activeContext.md` and `progress.md`. Create additional files in `memory-bank/` when useful for organizing new documentation. - -## Development Guidelines -- **Language:** Go using modules. -- **Formatting:** run `gofmt -w` on modified Go files. -- **Testing:** practice TDD and run `go test ./...` before committing, also Test the Application interactively, to ensure the UI is also correct. -- **Linting:** run `golangci-lint run` when available. -- **Structure:** keep application code inside `internal/` packages and follow existing patterns for `core`, `tui`, and `utils`. -- **Error Handling:** return errors instead of panicking and provide clear messages. - -## Commit Process -- Ensure Memory Bank is updated when project state changes. -- Run the formatting, lint, and test commands above. -- Commit only when the worktree is clean and all commands pass. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 904d2aa..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,87 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -This is a Go TUI application for managing `/etc/hosts` files using the Bubble Tea framework. The app provides a two-pane interface (list view + detail view) for viewing, editing, and managing host entries with features like activation/deactivation, sorting, and DNS resolution. - -## Architecture - -The codebase follows a clean architecture pattern with separation of concerns: - -- `cmd/hosts/main.go` - Entry point that parses `/etc/hosts` and launches the TUI -- `internal/core/` - Core business logic and data models - - `models.go` - Data structures for HostEntry and HostsFile with validation - - `parser.go` - Hosts file parsing, formatting, and writing with intelligent formatting detection -- `internal/tui/` - Bubble Tea TUI components - - `model.go` - Main Bubble Tea model with pane navigation and mode management - - `view.go` - Rendering logic for the two-pane interface - - `update.go` - Message handling and state updates -- `tests/` - Test files following TDD approach - -## Key Technical Patterns - -### Data Models -- `HostEntry` represents individual host entries with IP, hostname, aliases, comments, and active status -- `HostsFile` contains collections of entries with methods for searching, adding, and removing -- All models include validation methods and proper error handling - -### TUI Architecture -- Uses Bubble Tea's Model-View-Update pattern -- Two-pane layout with list and detail views -- Mode switching between ViewMode and EditMode -- Pane focus management (listPane/detailPane) - -### File Operations -- Intelligent formatting detection preserves original hosts file style -- Atomic file operations with backup creation -- Proper validation before writing changes - -## Development Commands - -### Build and Run -```bash -go run cmd/hosts/main.go -go build -o hosts cmd/hosts/main.go -``` - -### Testing -```bash -go test ./... # Run all tests -go test ./tests/ # Run tests in tests directory -go test -v ./internal/core/ # Run core package tests with verbose output -go test -cover ./... # Run tests with coverage -``` - -### Dependencies -Key dependencies are managed via `go.mod`: -- Bubble Tea framework for TUI -- Bubbles for common components -- Lip Gloss for styling -- testify for test assertions - -## Important Implementation Details - -### Hosts File Parsing -The parser in `internal/core/parser.go` handles: -- Active and inactive (commented) entries -- Inline comments preservation -- Intelligent formatting detection (tabs vs spaces) -- IPv4/IPv6 address validation -- RFC-compliant hostname validation - -### TUI Navigation -- Tab/Shift+Tab for pane switching -- Arrow keys for list navigation -- Space for toggling entry activation -- 'q' to quit application - -### Error Handling -- Comprehensive validation at model level -- Parse warnings collection during file parsing -- Graceful error recovery in TUI operations - -## Memory Bank Integration - -This project uses Cline's Memory Bank system located in `memory-bank/` directory. The project brief and context files provide additional architectural context and development history. Always consult these files when making significant changes to understand the project's evolution and design decisions. \ No newline at end of file diff --git a/internal/tui/update.go b/internal/tui/update.go index 8092961..e29fd15 100644 --- a/internal/tui/update.go +++ b/internal/tui/update.go @@ -18,13 +18,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } else { m.focus = listPane } - case "ctrl+e": + case "e": if m.mode == ViewMode { m.mode = EditMode } else { m.mode = ViewMode } - case " ": + case "a": if m.mode == EditMode { if entry := m.SelectedEntry(); entry != nil { entry.Active = !entry.Active @@ -34,7 +34,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case "up", "k": if m.focus == detailPane { - m.detail.ScrollUp(1) + m.detail.LineUp(1) } else { m.list, cmd = m.list.Update(msg) m.refreshDetail() @@ -42,7 +42,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd case "down", "j": if m.focus == detailPane { - m.detail.ScrollDown(1) + m.detail.LineDown(1) } else { m.list, cmd = m.list.Update(msg) m.refreshDetail() diff --git a/memory-bank/activeContext.md b/memory-bank/activeContext.md index 5a6e125..c19e750 100644 --- a/memory-bank/activeContext.md +++ b/memory-bank/activeContext.md @@ -24,8 +24,8 @@ - ✅ **Parser integration** loading `/etc/hosts` into the UI ### Phase 3: Edit Mode (IN PROGRESS) -- 🔄 **Edit mode toggle** via 'ctrl+e' key with status bar indication -- 🔄 **Entry activation toggle** using spacebar +- 🔄 **Edit mode toggle** via 'e' key with status bar indication +- 🔄 **Entry activation toggle** using 'a' key - 🔄 **Model tests** covering edit mode behavior ### Parser Capabilities Achieved diff --git a/memory-bank/progress.md b/memory-bank/progress.md index 13272c7..aedc400 100644 --- a/memory-bank/progress.md +++ b/memory-bank/progress.md @@ -80,7 +80,6 @@ - **Active work**: Expand edit mode with file integration and advanced editing - **Blockers**: None - comprehensive parser foundation with 54 tests completed - **Parser status**: Production-ready with all safety features implemented -- **Key bindings updated**: `ctrl+e` for edit mode, spacebar to toggle entries ### Development Readiness - ✅ **Architecture designed**: Clear technical approach documented diff --git a/memory-bank/projectbrief.md b/memory-bank/projectbrief.md index fb4ecde..692059f 100644 --- a/memory-bank/projectbrief.md +++ b/memory-bank/projectbrief.md @@ -29,17 +29,6 @@ The user can: - Use DNS-based resolution for hostnames - Quickly update IP addresses -Key Bindings: -- `ctrl`+`e`: Change to edit mode -- `e`: Edit the currently selected hostname entry -- `space`: Entry activation toggle -- `shift`+`up`/`down`: Move the selected entry up or down -- `i` Sort by IP addresses -- `n` Sort by (the first) hostname -- `ctrl`+`s`: Save -- `c` To open the tool configuration -- `?` or `h`: Display help about all Key Bindings - The program will operate in **view-only mode** by default and require explicit entry into **edit mode**, at which point it will request elevated (sudo) permissions until editing is disabled. The project uses: diff --git a/tests/tui_test.go b/tests/tui_test.go index ae7ce72..a73719a 100644 --- a/tests/tui_test.go +++ b/tests/tui_test.go @@ -72,12 +72,12 @@ func TestEditModeToggleAndActivation(t *testing.T) { m := tui.NewModel(hf) // enter edit mode - nm, _ := m.Update(tea.KeyMsg{Type: tea.KeyCtrlE}) + nm, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'e'}}) m = nm.(tui.Model) assert.Equal(t, tui.EditMode, m.Mode()) // toggle active state of first entry - nm, _ = m.Update(tea.KeyMsg{Type: tea.KeySpace}) + nm, _ = m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'a'}}) m = nm.(tui.Model) assert.False(t, m.SelectedEntry().Active)