diff options
41 files changed, 8 insertions, 3767 deletions
@@ -5,7 +5,6 @@ /hexai-lsp-server /hexai-mcp-server /hexai-tmux-action -/hexai-tmux-edit /bin/ # Coverage artifacts (mage coverage, mage covercheck) @@ -14,7 +13,6 @@ docs/coverage.html docs/coverage/ # Temp/scratch files -.tmux-edit-send.*.md /.local/ /.gomodcache/ /*.out diff --git a/Magefile.go b/Magefile.go index 9fc5be7..4c636ef 100644 --- a/Magefile.go +++ b/Magefile.go @@ -39,7 +39,7 @@ func Default() error { // Build builds binaries. func Build() error { printCoverage() - mg.Deps(BuildAsk, BuildHexaiLSP, BuildHexaiCLI, BuildHexaiTmuxAction, BuildHexaiTmuxEdit) + mg.Deps(BuildAsk, BuildHexaiLSP, BuildHexaiCLI, BuildHexaiTmuxAction) return nil } @@ -67,12 +67,6 @@ func BuildHexaiTmuxAction() error { return sh.RunV("go", "build", "-o", "hexai-tmux-action", "./cmd/hexai-tmux-action") } -// BuildHexaiTmuxEdit builds the hexai-tmux-edit popup editor binary. -func BuildHexaiTmuxEdit() error { - printCoverage() - return sh.RunV("go", "build", "-o", "hexai-tmux-edit", "./cmd/hexai-tmux-edit") -} - // BuildHexaiMCPServer builds the MCP server binary (DEPRECATED - experimental, not actively maintained). func BuildHexaiMCPServer() error { printCoverage() @@ -92,10 +86,7 @@ func Dev() error { if err := sh.RunV("go", "build", "-race", "-o", binaryName, "./cmd/hexai"); err != nil { return err } - if err := sh.RunV("go", "build", "-race", "-o", "hexai-tmux-action", "./cmd/hexai-tmux-action"); err != nil { - return err - } - return sh.RunV("go", "build", "-race", "-o", "hexai-tmux-edit", "./cmd/hexai-tmux-edit") + return sh.RunV("go", "build", "-race", "-o", "hexai-tmux-action", "./cmd/hexai-tmux-action") } // Run launches the LSP server via go run (useful during development). @@ -134,7 +125,6 @@ func Install() error { "hexai-lsp-server", binaryName, "hexai-tmux-action", - "hexai-tmux-edit", } { if err := atomicInstallBinary(filepath.Join(".", name), bin); err != nil { return err @@ -37,11 +37,6 @@ It has got improved capabilities for Go code understanding (for example, create - Fully configurable menu via `[[tmux_action.menu]]` — reorder, remove, rename, rebind hotkeys, embed custom actions directly in main menu - All action prompts overridable via `[prompts.code_action]` in `config.toml` - Custom prompt action opens your editor (`$HEXAI_EDITOR` or `$EDITOR`) on a temporary Markdown file -* Tmux popup editor (`hexai-tmux-edit`) for composing longer AI agent prompts - - Opens `$EDITOR` in a tmux popup, pre-filled with the current prompt text - - Auto-detects Cursor, Amp, Aider (WIP), and other agents - - OpenAI Codex CLI and Claude Code CLI have native external-editor support via `Ctrl+G` - - Config-driven: add new agents via `[tmux_edit]` in config.toml * Support for Ollama (local + Ollama Cloud), OpenAI, OpenRouter, Anthropic, and You.com (YouSearch Research API) — Ollama Cloud (`kimi-k2.6` at `https://ollama.com`) is the default > **Note on hexai-mcp-server:** This component is currently experimental and not actively maintained. The author manages prompts through slash commands and meta-commands in the hexai agent system, making the MCP server redundant for its original purpose. The code is preserved for potential future enhancements with different functionality beyond prompt management. See the [MCP documentation](docs/mcp-setup.md) for reference only. @@ -71,9 +66,7 @@ hexai follows the XDG Base Directory Specification: - `stats.json` - LLM usage tracking (regenerable) - `stats.lock` - File lock for stats access - **State & Logs:** `~/.local/hexai/state/` (or `$XDG_STATE_HOME/state/`) - - `tmux-edit-history.jsonl` - History of text submitted via tmux popup - `hexai-lsp-server.log` - LSP server debug logs - - `hexai-tmux-edit.log` - Tmux edit debug logs - `hexai-mcp-server.log` - MCP server debug logs - **Data:** `~/.local/hexai/data/` (or `$XDG_DATA_HOME/`) - `prompts/user.jsonl` - User-created custom prompts (built-in prompts are compiled into the binary) diff --git a/cmd/hexai-tmux-edit/main.go b/cmd/hexai-tmux-edit/main.go deleted file mode 100644 index d61f68a..0000000 --- a/cmd/hexai-tmux-edit/main.go +++ /dev/null @@ -1,63 +0,0 @@ -// hexai-tmux-edit opens a tmux popup with $EDITOR for composing AI agent -// prompts. It captures existing prompt text from the target pane, pre-fills -// the editor, and sends the edited text back via tmux send-keys. -// -// Usage: -// -// hexai-tmux-edit [--config <path>] [--agent <name>] [--pane <id>] -// -// Tmux keybinding (add to ~/.tmux.conf): -// -// bind e run-shell -b "cd '#{pane_current_path}' && hexai-tmux-edit --pane '#{pane_id}'" -package main - -import ( - "flag" - "fmt" - "io" - "os" - "strings" - - "codeberg.org/snonux/hexai/internal/appconfig" - "codeberg.org/snonux/hexai/internal/tmuxedit" -) - -type app struct { - runTmuxEdit func(tmuxedit.Options) error -} - -func newApp() *app { return &app{runTmuxEdit: tmuxedit.Run} } - -func main() { os.Exit(newApp().runMain(os.Args[1:], os.Stderr)) } - -// runMain parses flags from args and runs the tmux edit popup. It returns -// the process exit code; flag errors return 2 (matching stdlib convention), -// runtime failures return 1. -func (a *app) runMain(args []string, stderr io.Writer) int { - defaultPath := appconfig.DefaultConfigPath() - fs := flag.NewFlagSet("hexai-tmux-edit", flag.ContinueOnError) - fs.SetOutput(stderr) - configPath := fs.String("config", "", fmt.Sprintf("path to config file (default: %s)", defaultPath)) - agent := fs.String("agent", "", "AI agent name (auto-detected if omitted)") - pane := fs.String("pane", "", "tmux target pane ID (e.g. %5)") - if err := fs.Parse(args); err != nil { - return 2 - } - - opts := buildOptions(*configPath, *agent, *pane) - if err := a.runTmuxEdit(opts); err != nil { - fmt.Fprintln(stderr, err) - return 1 - } - return 0 -} - -// buildOptions constructs tmuxedit.Options from the parsed flag values, -// trimming whitespace from each field. -func buildOptions(configPath, agent, pane string) tmuxedit.Options { - return tmuxedit.Options{ - ConfigPath: strings.TrimSpace(configPath), - Agent: strings.TrimSpace(agent), - Pane: strings.TrimSpace(pane), - } -} diff --git a/cmd/hexai-tmux-edit/main_test.go b/cmd/hexai-tmux-edit/main_test.go deleted file mode 100644 index 3171b86..0000000 --- a/cmd/hexai-tmux-edit/main_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package main - -import ( - "bytes" - "errors" - "strings" - "testing" - - "codeberg.org/snonux/hexai/internal/tmuxedit" -) - -func TestBuildOptions_AllEmpty(t *testing.T) { - opts := buildOptions("", "", "") - if opts.ConfigPath != "" || opts.Agent != "" || opts.Pane != "" { - t.Fatalf("expected all empty, got %+v", opts) - } -} - -func TestBuildOptions_TrimsWhitespace(t *testing.T) { - opts := buildOptions(" /tmp/cfg.toml ", " claude ", " %5 ") - if opts.ConfigPath != "/tmp/cfg.toml" { - t.Fatalf("expected trimmed config path, got %q", opts.ConfigPath) - } - if opts.Agent != "claude" { - t.Fatalf("expected trimmed agent, got %q", opts.Agent) - } - if opts.Pane != "%5" { - t.Fatalf("expected trimmed pane, got %q", opts.Pane) - } -} - -func TestRunTmuxEdit_Success(t *testing.T) { - var gotOpts tmuxedit.Options - a := &app{runTmuxEdit: func(opts tmuxedit.Options) error { - gotOpts = opts - return nil - }} - - opts := buildOptions("/tmp/cfg.toml", "cursor", "%3") - if err := a.runTmuxEdit(opts); err != nil { - t.Fatalf("runTmuxEdit: %v", err) - } - if gotOpts.ConfigPath != "/tmp/cfg.toml" || gotOpts.Agent != "cursor" || gotOpts.Pane != "%3" { - t.Fatalf("unexpected opts: %+v", gotOpts) - } -} - -func TestRunTmuxEdit_Error(t *testing.T) { - wantErr := errors.New("tmux not found") - a := &app{runTmuxEdit: func(_ tmuxedit.Options) error { return wantErr }} - - if err := a.runTmuxEdit(tmuxedit.Options{}); !errors.Is(err, wantErr) { - t.Fatalf("expected error, got: %v", err) - } -} - -// runMain happy path: flags parse, runTmuxEdit returns nil, exit code 0. -// We capture the resolved Options to confirm flags map onto fields correctly. -func TestRunMain_FlagsForwardedToTmuxedit(t *testing.T) { - var got tmuxedit.Options - a := &app{runTmuxEdit: func(opts tmuxedit.Options) error { - got = opts - return nil - }} - - var stderr bytes.Buffer - code := a.runMain([]string{"-config", " /tmp/cfg.toml ", "-agent", "claude", "-pane", "%9"}, &stderr) - if code != 0 { - t.Fatalf("runMain code = %d, want 0", code) - } - if got.ConfigPath != "/tmp/cfg.toml" || got.Agent != "claude" || got.Pane != "%9" { - t.Fatalf("unexpected opts: %+v", got) - } - if stderr.Len() != 0 { - t.Fatalf("stderr should be empty on success, got %q", stderr.String()) - } -} - -// runMain reports tmuxedit.Run failures by writing to stderr and returning 1 -// — the production exit code that the shipped binary uses. -func TestRunMain_RunErrorReturnsOne(t *testing.T) { - a := &app{runTmuxEdit: func(tmuxedit.Options) error { return errors.New("boom") }} - - var stderr bytes.Buffer - code := a.runMain(nil, &stderr) - if code != 1 { - t.Fatalf("runMain code = %d, want 1", code) - } - if !strings.Contains(stderr.String(), "boom") { - t.Fatalf("stderr missing error: %q", stderr.String()) - } -} - -// Unknown flags must yield exit 2 (the convention used by stdlib `flag` when -// ExitOnError aborts) without ever invoking runTmuxEdit. -func TestRunMain_BadFlagReturnsTwo(t *testing.T) { - called := false - a := &app{runTmuxEdit: func(tmuxedit.Options) error { - called = true - return nil - }} - - var stderr bytes.Buffer - code := a.runMain([]string{"--no-such-flag"}, &stderr) - if code != 2 { - t.Fatalf("runMain code = %d, want 2", code) - } - if called { - t.Fatal("runTmuxEdit must not be called on flag-parse failure") - } -} diff --git a/config.toml.example b/config.toml.example index 5526e7f..9018a3d 100644 --- a/config.toml.example +++ b/config.toml.example @@ -200,29 +200,3 @@ research_effort = "standard" # gitignore = true # respect .gitignore patterns (default: true) # extra_patterns = ["*.min.js", "vendor/**", "*.generated.go"] # lsp_notify_ignored = true # show "file ignored" in LSP completions (default: true) - -[tmux_edit] -# popup_width = "80%" # tmux popup width (default: 80%) -# popup_height = "80%" # tmux popup height (default: 80%) -# default_agent = "" # force agent name; skip auto-detect - -# Override or add agent definitions (merged with built-in defaults by name). -# Built-in agents (checked in order): cursor, amp, aider. -# OpenAI Codex CLI and Claude Code CLI both support external editor mode via -# Ctrl+G, so no built-in tmux_edit agent profiles are needed for them. -# - cursor: Box UI │...│, clears with End+BSpace*200 -# - amp: Box UI │...│ (TUI mode), clears with C-u (Emacs/readline) -# - aider: Shell-style > prompt, clears with C-u (Emacs/readline) -# Tmux keybinding (add to ~/.tmux.conf): -# bind e run-shell -b "cd '#{pane_current_path}' && hexai-tmux-edit --pane '#{pane_id}'" - -# [[tmux_edit.agents]] -# name = "cursor" -# display_name = "Cursor" -# detect_pattern = "(?i)cursor" -# prompt_pattern = '(?m)│\s*(.+)$' -# strip_patterns = ["INSERT", "Add a follow-up"] -# clear_first = true -# clear_keys = "C-u" -# newline_keys = "S-Enter" -# submit_keys = "Enter" diff --git a/docs/buildandinstall.md b/docs/buildandinstall.md index 8e7a4f8..94de7b4 100644 --- a/docs/buildandinstall.md +++ b/docs/buildandinstall.md @@ -3,7 +3,7 @@ Hexai uses Mage for developer tasks. Install Mage, then run targets like build, dev, test, and install. - Install Mage: `go install github.com/magefile/mage@latest` -- Build binaries: `mage build` (produces `ask`, `hexai`, `hexai-lsp-server`, `hexai-tmux-action`, and `hexai-tmux-edit`) +- Build binaries: `mage build` (produces `ask`, `hexai`, `hexai-lsp-server`, and `hexai-tmux-action`) - Dev build (+ tests, vet, lint): `mage dev` - Run tests: `mage test` - Run tests with coverage: `go test ./... -cover` @@ -23,4 +23,3 @@ Either use the Mage method as mentioned above, or install directly with: - CLI: `go install codeberg.org/snonux/hexai/cmd/hexai@latest` - LSP: `go install codeberg.org/snonux/hexai/cmd/hexai-lsp-server@latest` - Action runner: `go install codeberg.org/snonux/hexai/cmd/hexai-tmux-action@latest` -- Tmux popup editor: `go install codeberg.org/snonux/hexai/cmd/hexai-tmux-edit@latest` diff --git a/docs/configuration.md b/docs/configuration.md index fd5a703..96cfa0b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -157,33 +157,3 @@ All prompts used by `hexai-tmux-action` (and the LSP code actions) can be overri | `fix_typos_*` | Fix typos and improve grammar and clarity | User templates support `{{selection}}` (always available) and `{{diagnostics}}` (diagnostics scope). See [config.toml.example](../config.toml.example) for the full defaults. - -Hexai Tmux Edit (popup editor) - -- `hexai-tmux-edit` opens `$EDITOR` in a tmux popup for composing longer AI agent prompts. -- Configure popup dimensions and agent detection patterns in the `[tmux_edit]` section: - - ```toml - [tmux_edit] - popup_width = "80%" - popup_height = "80%" - # default_agent = "claude" # force agent; skip auto-detect - ``` - -- Override or add agent definitions with `[[tmux_edit.agents]]` (merged with built-in defaults by name): - - ```toml - [[tmux_edit.agents]] - name = "claude" - display_name = "Claude Code" - detect_pattern = "(?i)(claude|anthropic)" - prompt_pattern = '(?m)>\s*(.+)$' - clear_first = true - clear_keys = "C-u" - newline_keys = "S-Enter" - submit_keys = "Enter" - ``` - -- Built-in agents: `cursor`, `amp`, `aider`. See [config.toml.example](../config.toml.example) for all fields. -- OpenAI Codex CLI and Claude Code CLI use their native external editor shortcut (`Ctrl+G`) instead of a built-in `tmux_edit` agent profile. -- Tmux keybinding: `bind e run-shell -b "cd '#{pane_current_path}' && hexai-tmux-edit --pane '#{pane_id}'"` diff --git a/docs/tmux-edit-popup.png b/docs/tmux-edit-popup.png Binary files differdeleted file mode 100644 index 5985d55..0000000 --- a/docs/tmux-edit-popup.png +++ /dev/null diff --git a/docs/tmux-edit-result.png b/docs/tmux-edit-result.png Binary files differdeleted file mode 100644 index 1d7f26d..0000000 --- a/docs/tmux-edit-result.png +++ /dev/null diff --git a/docs/tmux.md b/docs/tmux.md index ba024e3..a5e397c 100644 --- a/docs/tmux.md +++ b/docs/tmux.md @@ -68,36 +68,3 @@ window_minutes = 60 # default 60; min 1, max 1440 ``` - The tmux status shows the window as `Σ@1h` or `Σ@45m`. - -## Popup editor for AI agent prompts - -`hexai-tmux-edit` opens your `$EDITOR` in a tmux popup to compose longer prompts when working with AI CLI agents (Cursor, Amp, Aider, etc.). - -OpenAI Codex CLI and Claude Code CLI both support editing in an external editor natively via `Ctrl+G`, so neither needs a built-in `hexai-tmux-edit` agent profile. - - - -The editor opens as a tmux popup overlay, pre-filled with any existing prompt text from the agent's input. After saving and closing, the text is sent back: - - - -*(Screenshots from the [original blog post](https://foo.zone/gemfeed/2026-02-02-tmux-popup-editor-for-cursor-agent-prompts.html) showing the concept with Cursor Agent.)* - -Add this keybinding to `~/.tmux.conf`: - -``` -bind e run-shell -b "cd '#{pane_current_path}' && hexai-tmux-edit --pane '#{pane_id}'" -``` - -Then press `prefix + e` in any pane running an AI agent. Hexai auto-detects the agent, extracts any existing prompt text, and pre-fills the editor. After saving and closing, the edited text is sent back to the agent's pane. - -See the [configuration guide](configuration.md) for customizing popup dimensions and agent patterns, or the [usage guide](usage.md) for the full workflow description. - -**Input mode notes**: Each agent uses different clearing methods based on their input handling: -- **Cursor**: Uses simple backspace clearing (`End BSpace*200`) -- **Amp**: Uses Emacs/readline keybindings (`C-u`) -- **Aider**: Uses Emacs/readline keybindings (`C-u`) - -The popup editor uses `$EDITOR` (or `$HEXAI_EDITOR`), so your normal vim/neovim setup is used for composing prompts. - -**Note**: Agent detection and prompt extraction rely on regex patterns matched against each agent's terminal UI (box-drawing characters, prompt symbols, status text). When agents update their TUI layout, these patterns may need adjustment. You can override patterns per-agent in `[[tmux_edit.agents]]` config without code changes -- see the [configuration guide](configuration.md). diff --git a/docs/usage.md b/docs/usage.md index c6c55db..14a85ba 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -275,62 +275,6 @@ Tips: - Ensure Helix runs inside tmux to see the status updates. - You can also set a language-specific binding in `languages.toml` if preferred. -## Hexai Tmux Edit (Popup Editor) - -`hexai-tmux-edit` opens your `$EDITOR` in a tmux popup for composing longer AI agent prompts. It captures existing prompt text from the target pane, pre-fills the editor, and sends the edited text back via `tmux send-keys`. - -This is useful when working with AI CLI agents (Cursor, Amp, Aider, etc.) and you need to compose a longer, multi-line prompt with the comfort of your regular editor (spellcheck, search/replace, etc.). - -OpenAI Codex CLI and Claude Code CLI are not built-in `hexai-tmux-edit` agents. Both support editing in an external editor natively via `Ctrl+G`. - -### Supported agents - -Built-in agent detection (auto-detected from pane content, checked in order): - -1. **Cursor** -- detects box-drawing UI `│ →` or footer `/ commands · @ files` - - Clears with: `End BSpace*200` (backspace method) - - Prompt pattern: Extracts from last `│...│` box -2. **Amp** -- detects "amp" or "sourcegraph" in pane (TUI mode) - - Clears with: `C-u` (Emacs/readline style) - - Prompt pattern: Extracts from `│...│` box UI (similar to Cursor) -3. **Aider** -- detects "aider" in pane - - Clears with: `C-u` (Emacs/readline style) - - Prompt pattern: Shell-style `> prompt` - -**Detection order matters**: Cursor is checked first to avoid false positives. For example, Cursor may display "Claude 4.5 Sonnet" as its model name, but Cursor's distinctive `│ →` box UI is matched first. - -Additional agents can be added via `[tmux_edit.agents]` in config.toml without code changes. - -### Tmux keybinding - -Add to `~/.tmux.conf`: - -``` -bind e run-shell -b "cd '#{pane_current_path}' && hexai-tmux-edit --pane '#{pane_id}'" -``` - -The `#{pane_id}` is expanded by tmux to the active pane at keypress time, so the popup editor always knows which pane to send text back to. - -### Flags - -- `--config` path to config file (default: `$XDG_CONFIG_HOME/hexai/config.toml`) -- `--agent` explicit agent name (auto-detected if omitted) -- `--pane` tmux target pane ID (e.g. `%5`) - -### Workflow - -1. Press your tmux keybinding (e.g. `prefix + e`) -2. A tmux popup opens with your `$EDITOR`, pre-filled with any existing prompt text -3. Edit or compose your prompt -4. Save and close the editor -5. The edited text is sent to the agent's pane via `tmux send-keys` - -If you keep the original text unchanged and append new text, only the appended text is sent. If you rewrite the prompt entirely, the full new text is sent. If you save an empty file or don't change anything, nothing is sent. - -### Configuration - -See `[tmux_edit]` in [config.toml.example](../config.toml.example) for all options, including custom popup dimensions and agent overrides. - ### Slash commands Type a slash command at the end of a chat line (for example `/? reload>`). Available commands: diff --git a/internal/appconfig/app_feature_sections.go b/internal/appconfig/app_feature_sections.go index 2513946..da944d3 100644 --- a/internal/appconfig/app_feature_sections.go +++ b/internal/appconfig/app_feature_sections.go @@ -20,13 +20,6 @@ func (a *App) StatsSection() StatsConfig { return a.StatsConfig } -// TmuxEditSection returns a copy of the tmux popup editor settings. -func (a *App) TmuxEditSection() TmuxEditConfig { - c := a.TmuxEditConfig - c.TmuxEditAgents = append([]TmuxEditAgentCfg{}, a.TmuxEditAgents...) - return c -} - // TmuxActionSection returns a copy of the tmux action menu settings. func (a *App) TmuxActionSection() TmuxActionConfig { c := a.TmuxActionConfig diff --git a/internal/appconfig/app_feature_sections_test.go b/internal/appconfig/app_feature_sections_test.go index 1f9ac2d..b217146 100644 --- a/internal/appconfig/app_feature_sections_test.go +++ b/internal/appconfig/app_feature_sections_test.go @@ -33,18 +33,6 @@ func TestStatsSectionReads(t *testing.T) { } } -func TestTmuxEditSectionCopies(t *testing.T) { - cfg := buildFeatureApp() - got := cfg.TmuxEditSection() - if got.TmuxEditDefaultAgent != "codex" || len(got.TmuxEditAgents) != 1 { - t.Fatalf("unexpected tmux edit section: %+v", got) - } - got.TmuxEditAgents[0].Name = "mutated" - if cfg.TmuxEditAgents[0].Name == "mutated" { - t.Fatal("TmuxEditSection did not return a defensive copy") - } -} - func TestTmuxActionSectionCopies(t *testing.T) { cfg := App{} cfg.TmuxActionMenu = []TmuxActionMenuEntry{{Kind: "rewrite"}} diff --git a/internal/appconfig/app_sections.go b/internal/appconfig/app_sections.go index 5919db1..afa7bf0 100644 --- a/internal/appconfig/app_sections.go +++ b/internal/appconfig/app_sections.go @@ -111,7 +111,6 @@ type PromptConfig struct { type FeatureConfig struct { StatsConfig // usage statistics window IgnoreConfig // gitignore-aware file filtering for LSP - TmuxEditConfig // popup editor settings for hexai-tmux-edit TmuxActionConfig // configurable main menu for hexai-tmux-action MCPConfig // Model Context Protocol server settings } @@ -200,7 +199,6 @@ func (a *App) ApplyPromptSection(prompts PromptConfig) { func (a *App) FeatureSection() FeatureConfig { f := a.FeatureConfig f.IgnoreExtraPatterns = slices.Clone(a.IgnoreExtraPatterns) - f.TmuxEditAgents = append([]TmuxEditAgentCfg{}, a.TmuxEditAgents...) f.TmuxActionMenu = append([]TmuxActionMenuEntry{}, a.TmuxActionMenu...) return f } @@ -210,6 +208,5 @@ func (a *App) FeatureSection() FeatureConfig { func (a *App) ApplyFeatureSection(features FeatureConfig) { a.FeatureConfig = features a.IgnoreExtraPatterns = slices.Clone(features.IgnoreExtraPatterns) - a.TmuxEditAgents = append([]TmuxEditAgentCfg{}, features.TmuxEditAgents...) a.TmuxActionMenu = append([]TmuxActionMenuEntry{}, features.TmuxActionMenu...) } diff --git a/internal/appconfig/app_sections_test.go b/internal/appconfig/app_sections_test.go index bcd1cbe..2ff002d 100644 --- a/internal/appconfig/app_sections_test.go +++ b/internal/appconfig/app_sections_test.go @@ -28,7 +28,6 @@ func TestSectionsDefensiveCopies(t *testing.T) { sections.Providers.CLIConfigs[0].Model = "mutated" sections.Prompts.CustomActions[0].Title = "mutated" sections.Features.IgnoreExtraPatterns[0] = "mutated" - sections.Features.TmuxEditAgents[0].Name = "mutated" assertNotEqual(t, cfg.TriggerCharacters[0], "mutated", "trigger characters") assertNotEqual(t, cfg.ChatPrefixes[0], "mutated", "chat prefixes") @@ -36,7 +35,6 @@ func TestSectionsDefensiveCopies(t *testing.T) { assertNotEqual(t, cfg.CLIConfigs[0].Model, "mutated", "cli configs") assertNotEqual(t, cfg.CustomActions[0].Title, "mutated", "custom actions") assertNotEqual(t, cfg.IgnoreExtraPatterns[0], "mutated", "ignore patterns") - assertNotEqual(t, cfg.TmuxEditAgents[0].Name, "mutated", "tmux agents") out := cfg.Sections() out.Core.TriggerCharacters[0] = "mutated" @@ -45,7 +43,6 @@ func TestSectionsDefensiveCopies(t *testing.T) { out.Providers.CLIConfigs[0].Model = "mutated" out.Prompts.CustomActions[0].Title = "mutated" out.Features.IgnoreExtraPatterns[0] = "mutated" - out.Features.TmuxEditAgents[0].Name = "mutated" assertNotEqual(t, cfg.TriggerCharacters[0], "mutated", "sections trigger characters") assertNotEqual(t, cfg.ChatPrefixes[0], "mutated", "sections chat prefixes") @@ -53,7 +50,6 @@ func TestSectionsDefensiveCopies(t *testing.T) { assertNotEqual(t, cfg.CLIConfigs[0].Model, "mutated", "sections cli configs") assertNotEqual(t, cfg.CustomActions[0].Title, "mutated", "sections custom actions") assertNotEqual(t, cfg.IgnoreExtraPatterns[0], "mutated", "sections ignore patterns") - assertNotEqual(t, cfg.TmuxEditAgents[0].Name, "mutated", "sections tmux agents") } func assertNotEqual(t *testing.T, got, want, field string) { @@ -175,23 +171,6 @@ func testFeatureConfig() FeatureConfig { IgnoreExtraPatterns: []string{"vendor/**", "tmp/**"}, IgnoreLSPNotify: sectionBoolPtr(false), }, - TmuxEditConfig: TmuxEditConfig{ - TmuxEditPopupWidth: "80%", - TmuxEditPopupHeight: "75%", - TmuxEditDefaultAgent: "codex", - TmuxEditAgents: []TmuxEditAgentCfg{{ - Name: "codex", - DisplayName: "Codex", - DetectPattern: "(?i)codex", - SectionPattern: "section", - PromptPattern: "prompt", - StripPatterns: []string{"x", "y"}, - ClearFirst: sectionBoolPtr(true), - ClearKeys: "C-u", - NewlineKeys: "S-Enter", - SubmitKeys: "Enter", - }}, - }, MCPConfig: MCPConfig{ MCPPromptsDir: ".hexai/prompts", MCPSlashCommandSync: true, diff --git a/internal/appconfig/config_features_test.go b/internal/appconfig/config_features_test.go index 2b8c769..3d94c77 100644 --- a/internal/appconfig/config_features_test.go +++ b/internal/appconfig/config_features_test.go @@ -1,4 +1,4 @@ -// Tests for ignore config, tmux-edit config, and low-level parsing helpers +// Tests for ignore config and low-level parsing helpers // (temperature, model entries, surface entries, resolved model). package appconfig @@ -119,106 +119,6 @@ gitignore = false } } -func TestTmuxEditConfig_FromFile(t *testing.T) { - clearHexaiEnv(t) - dir := t.TempDir() - cfgPath := filepath.Join(dir, "config.toml") - writeFile(t, cfgPath, ` -[tmux_edit] -popup_width = "90%" -popup_height = "85%" -default_agent = "claude" - -[[tmux_edit.agents]] -name = "claude" -display_name = "Claude Code" -detect_pattern = "(?i)(claude|anthropic)" -prompt_pattern = '(?s)>\s*(.+?)$' -clear_first = true -clear_keys = "C-u" -newline_keys = "S-Enter" -submit_keys = "Enter" - -[[tmux_edit.agents]] -name = "cursor" -display_name = "Cursor" -detect_pattern = "(?i)cursor" -prompt_pattern = '(?s)│\s*(.+?)$' -strip_patterns = ["INSERT", "Add a follow-up"] -clear_first = true -clear_keys = "C-u" -newline_keys = "S-Enter" -submit_keys = "Enter" -`) - cfg := LoadWithOptions(context.Background(), newLogger(), LoadOptions{ConfigPath: cfgPath, Proj |
