Full Code of charmbracelet/crush for AI

main c7ce471bb38e cached
788 files
11.6 MB
3.1M tokens
2878 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (12,365K chars total). Download the full file to get everything.
Repository: charmbracelet/crush
Branch: main
Commit: c7ce471bb38e
Files: 788
Total size: 11.6 MB

Directory structure:
gitextract_j0rg_ehg/

├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── cla-signatures.json
│   ├── dependabot.yml
│   ├── entitlements.plist
│   ├── labeler.yml
│   └── workflows/
│       ├── build.yml
│       ├── cla.yml
│       ├── labeler.yml
│       ├── lint-sync.yml
│       ├── lint.yml
│       ├── nightly.yml
│       ├── release.yml
│       ├── schema-update.yml
│       ├── security.yml
│       └── snapshot.yml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yml
├── AGENTS.md
├── CLA.md
├── LICENSE.md
├── README.md
├── Taskfile.yaml
├── crush.json
├── go.mod
├── go.sum
├── internal/
│   ├── agent/
│   │   ├── agent.go
│   │   ├── agent_test.go
│   │   ├── agent_tool.go
│   │   ├── agentic_fetch_tool.go
│   │   ├── common_test.go
│   │   ├── coordinator.go
│   │   ├── coordinator_test.go
│   │   ├── errors.go
│   │   ├── event.go
│   │   ├── hyper/
│   │   │   ├── provider.go
│   │   │   └── provider.json
│   │   ├── loop_detection.go
│   │   ├── loop_detection_test.go
│   │   ├── notify/
│   │   │   └── notify.go
│   │   ├── prompt/
│   │   │   └── prompt.go
│   │   ├── prompts.go
│   │   ├── templates/
│   │   │   ├── agent_tool.md
│   │   │   ├── agentic_fetch.md
│   │   │   ├── agentic_fetch_prompt.md.tpl
│   │   │   ├── coder.md.tpl
│   │   │   ├── initialize.md.tpl
│   │   │   ├── summary.md
│   │   │   ├── task.md.tpl
│   │   │   └── title.md
│   │   ├── testdata/
│   │   │   └── TestCoderAgent/
│   │   │       ├── anthropic-sonnet/
│   │   │       │   ├── bash_tool.yaml
│   │   │       │   ├── download_tool.yaml
│   │   │       │   ├── fetch_tool.yaml
│   │   │       │   ├── glob_tool.yaml
│   │   │       │   ├── grep_tool.yaml
│   │   │       │   ├── ls_tool.yaml
│   │   │       │   ├── multiedit_tool.yaml
│   │   │       │   ├── parallel_tool_calls.yaml
│   │   │       │   ├── read_a_file.yaml
│   │   │       │   ├── simple_test.yaml
│   │   │       │   ├── sourcegraph_tool.yaml
│   │   │       │   ├── update_a_file.yaml
│   │   │       │   └── write_tool.yaml
│   │   │       ├── openai-gpt-5/
│   │   │       │   ├── bash_tool.yaml
│   │   │       │   ├── download_tool.yaml
│   │   │       │   ├── fetch_tool.yaml
│   │   │       │   ├── glob_tool.yaml
│   │   │       │   ├── grep_tool.yaml
│   │   │       │   ├── ls_tool.yaml
│   │   │       │   ├── multiedit_tool.yaml
│   │   │       │   ├── parallel_tool_calls.yaml
│   │   │       │   ├── read_a_file.yaml
│   │   │       │   ├── simple_test.yaml
│   │   │       │   ├── sourcegraph_tool.yaml
│   │   │       │   ├── update_a_file.yaml
│   │   │       │   └── write_tool.yaml
│   │   │       ├── openrouter-kimi-k2/
│   │   │       │   ├── bash_tool.yaml
│   │   │       │   ├── download_tool.yaml
│   │   │       │   ├── fetch_tool.yaml
│   │   │       │   ├── glob_tool.yaml
│   │   │       │   ├── grep_tool.yaml
│   │   │       │   ├── ls_tool.yaml
│   │   │       │   ├── multiedit_tool.yaml
│   │   │       │   ├── parallel_tool_calls.yaml
│   │   │       │   ├── read_a_file.yaml
│   │   │       │   ├── simple_test.yaml
│   │   │       │   ├── sourcegraph_tool.yaml
│   │   │       │   ├── update_a_file.yaml
│   │   │       │   └── write_tool.yaml
│   │   │       └── zai-glm4.6/
│   │   │           ├── bash_tool.yaml
│   │   │           ├── download_tool.yaml
│   │   │           ├── fetch_tool.yaml
│   │   │           ├── glob_tool.yaml
│   │   │           ├── grep_tool.yaml
│   │   │           ├── ls_tool.yaml
│   │   │           ├── multiedit_tool.yaml
│   │   │           ├── parallel_tool_calls.yaml
│   │   │           ├── read_a_file.yaml
│   │   │           ├── simple_test.yaml
│   │   │           ├── sourcegraph_tool.yaml
│   │   │           ├── update_a_file.yaml
│   │   │           └── write_tool.yaml
│   │   └── tools/
│   │       ├── bash.go
│   │       ├── bash.tpl
│   │       ├── bash_test.go
│   │       ├── context_test.go
│   │       ├── diagnostics.go
│   │       ├── diagnostics.md
│   │       ├── download.go
│   │       ├── download.md
│   │       ├── edit.go
│   │       ├── edit.md
│   │       ├── fetch.go
│   │       ├── fetch.md
│   │       ├── fetch_helpers.go
│   │       ├── fetch_types.go
│   │       ├── glob.go
│   │       ├── glob.md
│   │       ├── grep.go
│   │       ├── grep.md
│   │       ├── grep_test.go
│   │       ├── job_kill.go
│   │       ├── job_kill.md
│   │       ├── job_output.go
│   │       ├── job_output.md
│   │       ├── job_test.go
│   │       ├── list_mcp_resources.go
│   │       ├── list_mcp_resources.md
│   │       ├── ls.go
│   │       ├── ls.md
│   │       ├── lsp_restart.go
│   │       ├── lsp_restart.md
│   │       ├── mcp/
│   │       │   ├── init.go
│   │       │   ├── init_test.go
│   │       │   ├── prompts.go
│   │       │   ├── resources.go
│   │       │   ├── tools.go
│   │       │   └── tools_test.go
│   │       ├── mcp-tools.go
│   │       ├── multiedit.go
│   │       ├── multiedit.md
│   │       ├── multiedit_test.go
│   │       ├── read_mcp_resource.go
│   │       ├── read_mcp_resource.md
│   │       ├── references.go
│   │       ├── references.md
│   │       ├── rg.go
│   │       ├── safe.go
│   │       ├── search.go
│   │       ├── sourcegraph.go
│   │       ├── sourcegraph.md
│   │       ├── testdata/
│   │       │   └── grep.txt
│   │       ├── todos.go
│   │       ├── todos.md
│   │       ├── tools.go
│   │       ├── view.go
│   │       ├── view.md
│   │       ├── view_test.go
│   │       ├── web_fetch.go
│   │       ├── web_fetch.md
│   │       ├── web_search.go
│   │       ├── web_search.md
│   │       ├── write.go
│   │       └── write.md
│   ├── ansiext/
│   │   └── ansi.go
│   ├── app/
│   │   ├── app.go
│   │   ├── app_test.go
│   │   ├── lsp_events.go
│   │   ├── provider.go
│   │   ├── provider_test.go
│   │   └── resolve_session_test.go
│   ├── cmd/
│   │   ├── dirs.go
│   │   ├── dirs_test.go
│   │   ├── login.go
│   │   ├── logs.go
│   │   ├── models.go
│   │   ├── projects.go
│   │   ├── projects_test.go
│   │   ├── root.go
│   │   ├── run.go
│   │   ├── schema.go
│   │   ├── session.go
│   │   ├── stats/
│   │   │   ├── AGENTS.md
│   │   │   ├── index.css
│   │   │   ├── index.html
│   │   │   └── index.js
│   │   ├── stats.go
│   │   └── update_providers.go
│   ├── commands/
│   │   └── commands.go
│   ├── config/
│   │   ├── agent_id_test.go
│   │   ├── attribution_migration_test.go
│   │   ├── catwalk.go
│   │   ├── catwalk_test.go
│   │   ├── config.go
│   │   ├── copilot.go
│   │   ├── docker_mcp.go
│   │   ├── docker_mcp_test.go
│   │   ├── hyper.go
│   │   ├── hyper_test.go
│   │   ├── init.go
│   │   ├── load.go
│   │   ├── load_bench_test.go
│   │   ├── load_test.go
│   │   ├── lsp_defaults_test.go
│   │   ├── provider.go
│   │   ├── provider_empty_test.go
│   │   ├── provider_test.go
│   │   ├── recent_models_test.go
│   │   ├── resolve.go
│   │   ├── resolve_test.go
│   │   ├── scope.go
│   │   └── store.go
│   ├── csync/
│   │   ├── doc.go
│   │   ├── maps.go
│   │   ├── maps_test.go
│   │   ├── slices.go
│   │   ├── slices_test.go
│   │   ├── value.go
│   │   ├── value_test.go
│   │   ├── versionedmap.go
│   │   └── versionedmap_test.go
│   ├── db/
│   │   ├── connect.go
│   │   ├── connect_modernc.go
│   │   ├── connect_ncruces.go
│   │   ├── db.go
│   │   ├── embed.go
│   │   ├── files.sql.go
│   │   ├── messages.sql.go
│   │   ├── migrations/
│   │   │   ├── 20250424200609_initial.sql
│   │   │   ├── 20250515105448_add_summary_message_id.sql
│   │   │   ├── 20250624000000_add_created_at_indexes.sql
│   │   │   ├── 20250627000000_add_provider_to_messages.sql
│   │   │   ├── 20250810000000_add_is_summary_message.sql
│   │   │   ├── 20250812000000_add_todos_to_sessions.sql
│   │   │   └── 20260127000000_add_read_files_table.sql
│   │   ├── models.go
│   │   ├── querier.go
│   │   ├── read_files.sql.go
│   │   ├── sessions.sql.go
│   │   ├── sql/
│   │   │   ├── files.sql
│   │   │   ├── messages.sql
│   │   │   ├── read_files.sql
│   │   │   ├── sessions.sql
│   │   │   └── stats.sql
│   │   └── stats.sql.go
│   ├── diff/
│   │   └── diff.go
│   ├── env/
│   │   ├── env.go
│   │   └── env_test.go
│   ├── event/
│   │   ├── all.go
│   │   ├── event.go
│   │   ├── event_test.go
│   │   ├── identifier.go
│   │   └── logger.go
│   ├── filepathext/
│   │   └── filepath.go
│   ├── filetracker/
│   │   ├── service.go
│   │   └── service_test.go
│   ├── format/
│   │   └── spinner.go
│   ├── fsext/
│   │   ├── drive_other.go
│   │   ├── drive_windows.go
│   │   ├── expand.go
│   │   ├── fileutil.go
│   │   ├── fileutil_test.go
│   │   ├── ignore_test.go
│   │   ├── lookup.go
│   │   ├── lookup_test.go
│   │   ├── ls.go
│   │   ├── ls_test.go
│   │   ├── owner_others.go
│   │   ├── owner_windows.go
│   │   ├── paste.go
│   │   └── paste_test.go
│   ├── history/
│   │   └── file.go
│   ├── home/
│   │   ├── home.go
│   │   └── home_test.go
│   ├── log/
│   │   ├── http.go
│   │   ├── http_test.go
│   │   └── log.go
│   ├── lsp/
│   │   ├── client.go
│   │   ├── client_test.go
│   │   ├── handlers.go
│   │   ├── manager.go
│   │   └── util/
│   │       ├── edit.go
│   │       └── edit_test.go
│   ├── message/
│   │   ├── attachment.go
│   │   ├── content.go
│   │   ├── content_test.go
│   │   └── message.go
│   ├── oauth/
│   │   ├── copilot/
│   │   │   ├── client.go
│   │   │   ├── disk.go
│   │   │   ├── http.go
│   │   │   ├── oauth.go
│   │   │   └── urls.go
│   │   ├── hyper/
│   │   │   └── device.go
│   │   └── token.go
│   ├── permission/
│   │   ├── permission.go
│   │   └── permission_test.go
│   ├── projects/
│   │   ├── projects.go
│   │   └── projects_test.go
│   ├── pubsub/
│   │   ├── broker.go
│   │   └── events.go
│   ├── session/
│   │   └── session.go
│   ├── shell/
│   │   ├── background.go
│   │   ├── background_test.go
│   │   ├── command_block_test.go
│   │   ├── comparison_test.go
│   │   ├── coreutils.go
│   │   ├── doc.go
│   │   ├── shell.go
│   │   └── shell_test.go
│   ├── skills/
│   │   ├── skills.go
│   │   └── skills_test.go
│   ├── stringext/
│   │   └── string.go
│   ├── ui/
│   │   ├── AGENTS.md
│   │   ├── anim/
│   │   │   └── anim.go
│   │   ├── attachments/
│   │   │   └── attachments.go
│   │   ├── chat/
│   │   │   ├── agent.go
│   │   │   ├── assistant.go
│   │   │   ├── bash.go
│   │   │   ├── diagnostics.go
│   │   │   ├── docker_mcp.go
│   │   │   ├── fetch.go
│   │   │   ├── file.go
│   │   │   ├── generic.go
│   │   │   ├── lsp_restart.go
│   │   │   ├── mcp.go
│   │   │   ├── messages.go
│   │   │   ├── references.go
│   │   │   ├── search.go
│   │   │   ├── todos.go
│   │   │   ├── tools.go
│   │   │   └── user.go
│   │   ├── common/
│   │   │   ├── button.go
│   │   │   ├── capabilities.go
│   │   │   ├── common.go
│   │   │   ├── diff.go
│   │   │   ├── elements.go
│   │   │   ├── highlight.go
│   │   │   ├── interface.go
│   │   │   ├── markdown.go
│   │   │   └── scrollbar.go
│   │   ├── completions/
│   │   │   ├── completions.go
│   │   │   ├── item.go
│   │   │   └── keys.go
│   │   ├── dialog/
│   │   │   ├── actions.go
│   │   │   ├── api_key_input.go
│   │   │   ├── arguments.go
│   │   │   ├── commands.go
│   │   │   ├── commands_item.go
│   │   │   ├── common.go
│   │   │   ├── dialog.go
│   │   │   ├── filepicker.go
│   │   │   ├── models.go
│   │   │   ├── models_item.go
│   │   │   ├── models_list.go
│   │   │   ├── oauth.go
│   │   │   ├── oauth_copilot.go
│   │   │   ├── oauth_hyper.go
│   │   │   ├── permissions.go
│   │   │   ├── quit.go
│   │   │   ├── reasoning.go
│   │   │   ├── sessions.go
│   │   │   └── sessions_item.go
│   │   ├── diffview/
│   │   │   ├── Taskfile.yaml
│   │   │   ├── chroma.go
│   │   │   ├── diffview.go
│   │   │   ├── diffview_test.go
│   │   │   ├── split.go
│   │   │   ├── style.go
│   │   │   ├── testdata/
│   │   │   │   ├── TestDefault.after
│   │   │   │   ├── TestDefault.before
│   │   │   │   ├── TestDiffView/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── CustomContextLines/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── Default/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── LargeWidth/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── MultipleHunks/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── Narrow/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── NoLineNumbers/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── NoSyntaxHighlight/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   └── SmallWidth/
│   │   │   │   │   │       ├── DarkMode.golden
│   │   │   │   │   │       └── LightMode.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── CustomContextLines/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── Default/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── LargeWidth/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── MultipleHunks/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── Narrow/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── NoLineNumbers/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── NoSyntaxHighlight/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       └── SmallWidth/
│   │   │   │   │           ├── DarkMode.golden
│   │   │   │   │           └── LightMode.golden
│   │   │   │   ├── TestDiffViewHeight/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── HeightOf001.golden
│   │   │   │   │   │   ├── HeightOf002.golden
│   │   │   │   │   │   ├── HeightOf003.golden
│   │   │   │   │   │   ├── HeightOf004.golden
│   │   │   │   │   │   ├── HeightOf005.golden
│   │   │   │   │   │   ├── HeightOf006.golden
│   │   │   │   │   │   ├── HeightOf007.golden
│   │   │   │   │   │   ├── HeightOf008.golden
│   │   │   │   │   │   ├── HeightOf009.golden
│   │   │   │   │   │   ├── HeightOf010.golden
│   │   │   │   │   │   ├── HeightOf011.golden
│   │   │   │   │   │   ├── HeightOf012.golden
│   │   │   │   │   │   ├── HeightOf013.golden
│   │   │   │   │   │   ├── HeightOf014.golden
│   │   │   │   │   │   ├── HeightOf015.golden
│   │   │   │   │   │   ├── HeightOf016.golden
│   │   │   │   │   │   ├── HeightOf017.golden
│   │   │   │   │   │   ├── HeightOf018.golden
│   │   │   │   │   │   ├── HeightOf019.golden
│   │   │   │   │   │   └── HeightOf020.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── HeightOf001.golden
│   │   │   │   │       ├── HeightOf002.golden
│   │   │   │   │       ├── HeightOf003.golden
│   │   │   │   │       ├── HeightOf004.golden
│   │   │   │   │       ├── HeightOf005.golden
│   │   │   │   │       ├── HeightOf006.golden
│   │   │   │   │       ├── HeightOf007.golden
│   │   │   │   │       ├── HeightOf008.golden
│   │   │   │   │       ├── HeightOf009.golden
│   │   │   │   │       ├── HeightOf010.golden
│   │   │   │   │       ├── HeightOf011.golden
│   │   │   │   │       ├── HeightOf012.golden
│   │   │   │   │       ├── HeightOf013.golden
│   │   │   │   │       ├── HeightOf014.golden
│   │   │   │   │       ├── HeightOf015.golden
│   │   │   │   │       ├── HeightOf016.golden
│   │   │   │   │       ├── HeightOf017.golden
│   │   │   │   │       ├── HeightOf018.golden
│   │   │   │   │       ├── HeightOf019.golden
│   │   │   │   │       └── HeightOf020.golden
│   │   │   │   ├── TestDiffViewLineBreakIssue/
│   │   │   │   │   ├── Split.golden
│   │   │   │   │   └── Unified.golden
│   │   │   │   ├── TestDiffViewTabs/
│   │   │   │   │   ├── Split.golden
│   │   │   │   │   └── Unified.golden
│   │   │   │   ├── TestDiffViewWidth/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── WidthOf001.golden
│   │   │   │   │   │   ├── WidthOf002.golden
│   │   │   │   │   │   ├── WidthOf003.golden
│   │   │   │   │   │   ├── WidthOf004.golden
│   │   │   │   │   │   ├── WidthOf005.golden
│   │   │   │   │   │   ├── WidthOf006.golden
│   │   │   │   │   │   ├── WidthOf007.golden
│   │   │   │   │   │   ├── WidthOf008.golden
│   │   │   │   │   │   ├── WidthOf009.golden
│   │   │   │   │   │   ├── WidthOf010.golden
│   │   │   │   │   │   ├── WidthOf011.golden
│   │   │   │   │   │   ├── WidthOf012.golden
│   │   │   │   │   │   ├── WidthOf013.golden
│   │   │   │   │   │   ├── WidthOf014.golden
│   │   │   │   │   │   ├── WidthOf015.golden
│   │   │   │   │   │   ├── WidthOf016.golden
│   │   │   │   │   │   ├── WidthOf017.golden
│   │   │   │   │   │   ├── WidthOf018.golden
│   │   │   │   │   │   ├── WidthOf019.golden
│   │   │   │   │   │   ├── WidthOf020.golden
│   │   │   │   │   │   ├── WidthOf021.golden
│   │   │   │   │   │   ├── WidthOf022.golden
│   │   │   │   │   │   ├── WidthOf023.golden
│   │   │   │   │   │   ├── WidthOf024.golden
│   │   │   │   │   │   ├── WidthOf025.golden
│   │   │   │   │   │   ├── WidthOf026.golden
│   │   │   │   │   │   ├── WidthOf027.golden
│   │   │   │   │   │   ├── WidthOf028.golden
│   │   │   │   │   │   ├── WidthOf029.golden
│   │   │   │   │   │   ├── WidthOf030.golden
│   │   │   │   │   │   ├── WidthOf031.golden
│   │   │   │   │   │   ├── WidthOf032.golden
│   │   │   │   │   │   ├── WidthOf033.golden
│   │   │   │   │   │   ├── WidthOf034.golden
│   │   │   │   │   │   ├── WidthOf035.golden
│   │   │   │   │   │   ├── WidthOf036.golden
│   │   │   │   │   │   ├── WidthOf037.golden
│   │   │   │   │   │   ├── WidthOf038.golden
│   │   │   │   │   │   ├── WidthOf039.golden
│   │   │   │   │   │   ├── WidthOf040.golden
│   │   │   │   │   │   ├── WidthOf041.golden
│   │   │   │   │   │   ├── WidthOf042.golden
│   │   │   │   │   │   ├── WidthOf043.golden
│   │   │   │   │   │   ├── WidthOf044.golden
│   │   │   │   │   │   ├── WidthOf045.golden
│   │   │   │   │   │   ├── WidthOf046.golden
│   │   │   │   │   │   ├── WidthOf047.golden
│   │   │   │   │   │   ├── WidthOf048.golden
│   │   │   │   │   │   ├── WidthOf049.golden
│   │   │   │   │   │   ├── WidthOf050.golden
│   │   │   │   │   │   ├── WidthOf051.golden
│   │   │   │   │   │   ├── WidthOf052.golden
│   │   │   │   │   │   ├── WidthOf053.golden
│   │   │   │   │   │   ├── WidthOf054.golden
│   │   │   │   │   │   ├── WidthOf055.golden
│   │   │   │   │   │   ├── WidthOf056.golden
│   │   │   │   │   │   ├── WidthOf057.golden
│   │   │   │   │   │   ├── WidthOf058.golden
│   │   │   │   │   │   ├── WidthOf059.golden
│   │   │   │   │   │   ├── WidthOf060.golden
│   │   │   │   │   │   ├── WidthOf061.golden
│   │   │   │   │   │   ├── WidthOf062.golden
│   │   │   │   │   │   ├── WidthOf063.golden
│   │   │   │   │   │   ├── WidthOf064.golden
│   │   │   │   │   │   ├── WidthOf065.golden
│   │   │   │   │   │   ├── WidthOf066.golden
│   │   │   │   │   │   ├── WidthOf067.golden
│   │   │   │   │   │   ├── WidthOf068.golden
│   │   │   │   │   │   ├── WidthOf069.golden
│   │   │   │   │   │   ├── WidthOf070.golden
│   │   │   │   │   │   ├── WidthOf071.golden
│   │   │   │   │   │   ├── WidthOf072.golden
│   │   │   │   │   │   ├── WidthOf073.golden
│   │   │   │   │   │   ├── WidthOf074.golden
│   │   │   │   │   │   ├── WidthOf075.golden
│   │   │   │   │   │   ├── WidthOf076.golden
│   │   │   │   │   │   ├── WidthOf077.golden
│   │   │   │   │   │   ├── WidthOf078.golden
│   │   │   │   │   │   ├── WidthOf079.golden
│   │   │   │   │   │   ├── WidthOf080.golden
│   │   │   │   │   │   ├── WidthOf081.golden
│   │   │   │   │   │   ├── WidthOf082.golden
│   │   │   │   │   │   ├── WidthOf083.golden
│   │   │   │   │   │   ├── WidthOf084.golden
│   │   │   │   │   │   ├── WidthOf085.golden
│   │   │   │   │   │   ├── WidthOf086.golden
│   │   │   │   │   │   ├── WidthOf087.golden
│   │   │   │   │   │   ├── WidthOf088.golden
│   │   │   │   │   │   ├── WidthOf089.golden
│   │   │   │   │   │   ├── WidthOf090.golden
│   │   │   │   │   │   ├── WidthOf091.golden
│   │   │   │   │   │   ├── WidthOf092.golden
│   │   │   │   │   │   ├── WidthOf093.golden
│   │   │   │   │   │   ├── WidthOf094.golden
│   │   │   │   │   │   ├── WidthOf095.golden
│   │   │   │   │   │   ├── WidthOf096.golden
│   │   │   │   │   │   ├── WidthOf097.golden
│   │   │   │   │   │   ├── WidthOf098.golden
│   │   │   │   │   │   ├── WidthOf099.golden
│   │   │   │   │   │   ├── WidthOf100.golden
│   │   │   │   │   │   ├── WidthOf101.golden
│   │   │   │   │   │   ├── WidthOf102.golden
│   │   │   │   │   │   ├── WidthOf103.golden
│   │   │   │   │   │   ├── WidthOf104.golden
│   │   │   │   │   │   ├── WidthOf105.golden
│   │   │   │   │   │   ├── WidthOf106.golden
│   │   │   │   │   │   ├── WidthOf107.golden
│   │   │   │   │   │   ├── WidthOf108.golden
│   │   │   │   │   │   ├── WidthOf109.golden
│   │   │   │   │   │   └── WidthOf110.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── WidthOf001.golden
│   │   │   │   │       ├── WidthOf002.golden
│   │   │   │   │       ├── WidthOf003.golden
│   │   │   │   │       ├── WidthOf004.golden
│   │   │   │   │       ├── WidthOf005.golden
│   │   │   │   │       ├── WidthOf006.golden
│   │   │   │   │       ├── WidthOf007.golden
│   │   │   │   │       ├── WidthOf008.golden
│   │   │   │   │       ├── WidthOf009.golden
│   │   │   │   │       ├── WidthOf010.golden
│   │   │   │   │       ├── WidthOf011.golden
│   │   │   │   │       ├── WidthOf012.golden
│   │   │   │   │       ├── WidthOf013.golden
│   │   │   │   │       ├── WidthOf014.golden
│   │   │   │   │       ├── WidthOf015.golden
│   │   │   │   │       ├── WidthOf016.golden
│   │   │   │   │       ├── WidthOf017.golden
│   │   │   │   │       ├── WidthOf018.golden
│   │   │   │   │       ├── WidthOf019.golden
│   │   │   │   │       ├── WidthOf020.golden
│   │   │   │   │       ├── WidthOf021.golden
│   │   │   │   │       ├── WidthOf022.golden
│   │   │   │   │       ├── WidthOf023.golden
│   │   │   │   │       ├── WidthOf024.golden
│   │   │   │   │       ├── WidthOf025.golden
│   │   │   │   │       ├── WidthOf026.golden
│   │   │   │   │       ├── WidthOf027.golden
│   │   │   │   │       ├── WidthOf028.golden
│   │   │   │   │       ├── WidthOf029.golden
│   │   │   │   │       ├── WidthOf030.golden
│   │   │   │   │       ├── WidthOf031.golden
│   │   │   │   │       ├── WidthOf032.golden
│   │   │   │   │       ├── WidthOf033.golden
│   │   │   │   │       ├── WidthOf034.golden
│   │   │   │   │       ├── WidthOf035.golden
│   │   │   │   │       ├── WidthOf036.golden
│   │   │   │   │       ├── WidthOf037.golden
│   │   │   │   │       ├── WidthOf038.golden
│   │   │   │   │       ├── WidthOf039.golden
│   │   │   │   │       ├── WidthOf040.golden
│   │   │   │   │       ├── WidthOf041.golden
│   │   │   │   │       ├── WidthOf042.golden
│   │   │   │   │       ├── WidthOf043.golden
│   │   │   │   │       ├── WidthOf044.golden
│   │   │   │   │       ├── WidthOf045.golden
│   │   │   │   │       ├── WidthOf046.golden
│   │   │   │   │       ├── WidthOf047.golden
│   │   │   │   │       ├── WidthOf048.golden
│   │   │   │   │       ├── WidthOf049.golden
│   │   │   │   │       ├── WidthOf050.golden
│   │   │   │   │       ├── WidthOf051.golden
│   │   │   │   │       ├── WidthOf052.golden
│   │   │   │   │       ├── WidthOf053.golden
│   │   │   │   │       ├── WidthOf054.golden
│   │   │   │   │       ├── WidthOf055.golden
│   │   │   │   │       ├── WidthOf056.golden
│   │   │   │   │       ├── WidthOf057.golden
│   │   │   │   │       ├── WidthOf058.golden
│   │   │   │   │       ├── WidthOf059.golden
│   │   │   │   │       └── WidthOf060.golden
│   │   │   │   ├── TestDiffViewXOffset/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── XOffsetOf00.golden
│   │   │   │   │   │   ├── XOffsetOf01.golden
│   │   │   │   │   │   ├── XOffsetOf02.golden
│   │   │   │   │   │   ├── XOffsetOf03.golden
│   │   │   │   │   │   ├── XOffsetOf04.golden
│   │   │   │   │   │   ├── XOffsetOf05.golden
│   │   │   │   │   │   ├── XOffsetOf06.golden
│   │   │   │   │   │   ├── XOffsetOf07.golden
│   │   │   │   │   │   ├── XOffsetOf08.golden
│   │   │   │   │   │   ├── XOffsetOf09.golden
│   │   │   │   │   │   ├── XOffsetOf10.golden
│   │   │   │   │   │   ├── XOffsetOf11.golden
│   │   │   │   │   │   ├── XOffsetOf12.golden
│   │   │   │   │   │   ├── XOffsetOf13.golden
│   │   │   │   │   │   ├── XOffsetOf14.golden
│   │   │   │   │   │   ├── XOffsetOf15.golden
│   │   │   │   │   │   ├── XOffsetOf16.golden
│   │   │   │   │   │   ├── XOffsetOf17.golden
│   │   │   │   │   │   ├── XOffsetOf18.golden
│   │   │   │   │   │   ├── XOffsetOf19.golden
│   │   │   │   │   │   └── XOffsetOf20.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── XOffsetOf00.golden
│   │   │   │   │       ├── XOffsetOf01.golden
│   │   │   │   │       ├── XOffsetOf02.golden
│   │   │   │   │       ├── XOffsetOf03.golden
│   │   │   │   │       ├── XOffsetOf04.golden
│   │   │   │   │       ├── XOffsetOf05.golden
│   │   │   │   │       ├── XOffsetOf06.golden
│   │   │   │   │       ├── XOffsetOf07.golden
│   │   │   │   │       ├── XOffsetOf08.golden
│   │   │   │   │       ├── XOffsetOf09.golden
│   │   │   │   │       ├── XOffsetOf10.golden
│   │   │   │   │       ├── XOffsetOf11.golden
│   │   │   │   │       ├── XOffsetOf12.golden
│   │   │   │   │       ├── XOffsetOf13.golden
│   │   │   │   │       ├── XOffsetOf14.golden
│   │   │   │   │       ├── XOffsetOf15.golden
│   │   │   │   │       ├── XOffsetOf16.golden
│   │   │   │   │       ├── XOffsetOf17.golden
│   │   │   │   │       ├── XOffsetOf18.golden
│   │   │   │   │       ├── XOffsetOf19.golden
│   │   │   │   │       └── XOffsetOf20.golden
│   │   │   │   ├── TestDiffViewYOffset/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── YOffsetOf00.golden
│   │   │   │   │   │   ├── YOffsetOf01.golden
│   │   │   │   │   │   ├── YOffsetOf02.golden
│   │   │   │   │   │   ├── YOffsetOf03.golden
│   │   │   │   │   │   ├── YOffsetOf04.golden
│   │   │   │   │   │   ├── YOffsetOf05.golden
│   │   │   │   │   │   ├── YOffsetOf06.golden
│   │   │   │   │   │   ├── YOffsetOf07.golden
│   │   │   │   │   │   ├── YOffsetOf08.golden
│   │   │   │   │   │   ├── YOffsetOf09.golden
│   │   │   │   │   │   ├── YOffsetOf10.golden
│   │   │   │   │   │   ├── YOffsetOf11.golden
│   │   │   │   │   │   ├── YOffsetOf12.golden
│   │   │   │   │   │   ├── YOffsetOf13.golden
│   │   │   │   │   │   ├── YOffsetOf14.golden
│   │   │   │   │   │   ├── YOffsetOf15.golden
│   │   │   │   │   │   └── YOffsetOf16.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── YOffsetOf00.golden
│   │   │   │   │       ├── YOffsetOf01.golden
│   │   │   │   │       ├── YOffsetOf02.golden
│   │   │   │   │       ├── YOffsetOf03.golden
│   │   │   │   │       ├── YOffsetOf04.golden
│   │   │   │   │       ├── YOffsetOf05.golden
│   │   │   │   │       ├── YOffsetOf06.golden
│   │   │   │   │       ├── YOffsetOf07.golden
│   │   │   │   │       ├── YOffsetOf08.golden
│   │   │   │   │       ├── YOffsetOf09.golden
│   │   │   │   │       ├── YOffsetOf10.golden
│   │   │   │   │       ├── YOffsetOf11.golden
│   │   │   │   │       ├── YOffsetOf12.golden
│   │   │   │   │       ├── YOffsetOf13.golden
│   │   │   │   │       ├── YOffsetOf14.golden
│   │   │   │   │       ├── YOffsetOf15.golden
│   │   │   │   │       └── YOffsetOf16.golden
│   │   │   │   ├── TestDiffViewYOffsetInfinite/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── YOffsetOf00.golden
│   │   │   │   │   │   ├── YOffsetOf01.golden
│   │   │   │   │   │   ├── YOffsetOf02.golden
│   │   │   │   │   │   ├── YOffsetOf03.golden
│   │   │   │   │   │   ├── YOffsetOf04.golden
│   │   │   │   │   │   ├── YOffsetOf05.golden
│   │   │   │   │   │   ├── YOffsetOf06.golden
│   │   │   │   │   │   ├── YOffsetOf07.golden
│   │   │   │   │   │   ├── YOffsetOf08.golden
│   │   │   │   │   │   ├── YOffsetOf09.golden
│   │   │   │   │   │   ├── YOffsetOf10.golden
│   │   │   │   │   │   ├── YOffsetOf11.golden
│   │   │   │   │   │   ├── YOffsetOf12.golden
│   │   │   │   │   │   ├── YOffsetOf13.golden
│   │   │   │   │   │   ├── YOffsetOf14.golden
│   │   │   │   │   │   ├── YOffsetOf15.golden
│   │   │   │   │   │   └── YOffsetOf16.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── YOffsetOf00.golden
│   │   │   │   │       ├── YOffsetOf01.golden
│   │   │   │   │       ├── YOffsetOf02.golden
│   │   │   │   │       ├── YOffsetOf03.golden
│   │   │   │   │       ├── YOffsetOf04.golden
│   │   │   │   │       ├── YOffsetOf05.golden
│   │   │   │   │       ├── YOffsetOf06.golden
│   │   │   │   │       ├── YOffsetOf07.golden
│   │   │   │   │       ├── YOffsetOf08.golden
│   │   │   │   │       ├── YOffsetOf09.golden
│   │   │   │   │       ├── YOffsetOf10.golden
│   │   │   │   │       ├── YOffsetOf11.golden
│   │   │   │   │       ├── YOffsetOf12.golden
│   │   │   │   │       ├── YOffsetOf13.golden
│   │   │   │   │       ├── YOffsetOf14.golden
│   │   │   │   │       ├── YOffsetOf15.golden
│   │   │   │   │       └── YOffsetOf16.golden
│   │   │   │   ├── TestLineBreakIssue.after
│   │   │   │   ├── TestLineBreakIssue.before
│   │   │   │   ├── TestMultipleHunks.after
│   │   │   │   ├── TestMultipleHunks.before
│   │   │   │   ├── TestNarrow.after
│   │   │   │   ├── TestNarrow.before
│   │   │   │   ├── TestTabs.after
│   │   │   │   ├── TestTabs.before
│   │   │   │   └── TestUdiff/
│   │   │   │       ├── ToUnifiedDiff/
│   │   │   │       │   ├── DefaultContextLines/
│   │   │   │       │   │   ├── Content.golden
│   │   │   │       │   │   └── JSON.golden
│   │   │   │       │   ├── DefaultContextLinesPlusOne/
│   │   │   │       │   │   ├── Content.golden
│   │   │   │       │   │   └── JSON.golden
│   │   │   │       │   └── DefaultContextLinesPlusTwo/
│   │   │   │       │       ├── Content.golden
│   │   │   │       │       └── JSON.golden
│   │   │   │       └── Unified.golden
│   │   │   ├── udiff_test.go
│   │   │   ├── util.go
│   │   │   └── util_test.go
│   │   ├── image/
│   │   │   ├── image.go
│   │   │   └── image_test.go
│   │   ├── list/
│   │   │   ├── filterable.go
│   │   │   ├── focus.go
│   │   │   ├── highlight.go
│   │   │   ├── item.go
│   │   │   └── list.go
│   │   ├── logo/
│   │   │   ├── logo.go
│   │   │   └── rand.go
│   │   ├── model/
│   │   │   ├── chat.go
│   │   │   ├── clipboard.go
│   │   │   ├── clipboard_not_supported.go
│   │   │   ├── clipboard_supported.go
│   │   │   ├── filter.go
│   │   │   ├── header.go
│   │   │   ├── history.go
│   │   │   ├── keys.go
│   │   │   ├── landing.go
│   │   │   ├── lsp.go
│   │   │   ├── mcp.go
│   │   │   ├── onboarding.go
│   │   │   ├── pills.go
│   │   │   ├── session.go
│   │   │   ├── sidebar.go
│   │   │   ├── status.go
│   │   │   └── ui.go
│   │   ├── notification/
│   │   │   ├── icon_darwin.go
│   │   │   ├── icon_other.go
│   │   │   ├── native.go
│   │   │   ├── noop.go
│   │   │   ├── notification.go
│   │   │   └── notification_test.go
│   │   ├── styles/
│   │   │   ├── grad.go
│   │   │   └── styles.go
│   │   └── util/
│   │       └── util.go
│   ├── update/
│   │   ├── update.go
│   │   └── update_test.go
│   └── version/
│       └── version.go
├── main.go
├── schema.json
├── scripts/
│   ├── check_log_capitalization.sh
│   └── run-labeler.sh
└── sqlc.yaml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
*.golden linguist-generated=true -text
.github/crush-schema.json linguist-generated=true
internal/agent/hyper/provider.json linguist-generated=true
internal/agent/testdata/**/*.yaml -diff linguist-generated=true


================================================
FILE: .github/CODEOWNERS
================================================
*.go @charmbracelet/everyone


================================================
FILE: .github/cla-signatures.json
================================================
{
  "signedContributors": [
    {
      "name": "caarlos0",
      "id": 245435,
      "comment_id": 3133376230,
      "created_at": "2025-07-29T17:11:51Z",
      "repoId": 987670088,
      "pullRequestNo": 333
    },
    {
      "name": "raphamorim",
      "id": 3630346,
      "comment_id": 3133374793,
      "created_at": "2025-07-29T17:11:19Z",
      "repoId": 987670088,
      "pullRequestNo": 230
    },
    {
      "name": "raphamorim",
      "id": 3630346,
      "comment_id": 3133379333,
      "created_at": "2025-07-29T17:13:00Z",
      "repoId": 987670088,
      "pullRequestNo": 230
    },
    {
      "name": "aymanbagabas",
      "id": 3187948,
      "comment_id": 3133374319,
      "created_at": "2025-07-29T17:11:08Z",
      "repoId": 987670088,
      "pullRequestNo": 224
    },
    {
      "name": "aymanbagabas",
      "id": 3187948,
      "comment_id": 3133398259,
      "created_at": "2025-07-29T17:19:30Z",
      "repoId": 987670088,
      "pullRequestNo": 224
    },
    {
      "name": "andreynering",
      "id": 7011819,
      "comment_id": 3133398174,
      "created_at": "2025-07-29T17:19:29Z",
      "repoId": 987670088,
      "pullRequestNo": 323
    },
    {
      "name": "ras0q",
      "id": 66677201,
      "comment_id": 3133486409,
      "created_at": "2025-07-29T17:51:25Z",
      "repoId": 987670088,
      "pullRequestNo": 335
    },
    {
      "name": "meowgorithm",
      "id": 25087,
      "comment_id": 3134117697,
      "created_at": "2025-07-29T21:23:05Z",
      "repoId": 987670088,
      "pullRequestNo": 343
    },
    {
      "name": "kujtimiihoxha",
      "id": 14311743,
      "comment_id": 3135739620,
      "created_at": "2025-07-30T10:35:23Z",
      "repoId": 987670088,
      "pullRequestNo": 352
    },
    {
      "name": "rio",
      "id": 883894,
      "comment_id": 3136448851,
      "created_at": "2025-07-30T13:51:45Z",
      "repoId": 987670088,
      "pullRequestNo": 358
    },
    {
      "name": "douglarek",
      "id": 1488134,
      "comment_id": 3136721507,
      "created_at": "2025-07-30T14:55:51Z",
      "repoId": 987670088,
      "pullRequestNo": 362
    },
    {
      "name": "taigrr",
      "id": 8261498,
      "comment_id": 3138718122,
      "created_at": "2025-07-31T06:31:11Z",
      "repoId": 987670088,
      "pullRequestNo": 391
    },
    {
      "name": "fluffypony",
      "id": 1944293,
      "comment_id": 3139828932,
      "created_at": "2025-07-31T12:45:05Z",
      "repoId": 987670088,
      "pullRequestNo": 400
    },
    {
      "name": "jedisct1",
      "id": 124872,
      "comment_id": 3140242221,
      "created_at": "2025-07-31T14:39:23Z",
      "repoId": 987670088,
      "pullRequestNo": 408
    },
    {
      "name": "Djiit",
      "id": 1169844,
      "comment_id": 3140319096,
      "created_at": "2025-07-31T15:01:49Z",
      "repoId": 987670088,
      "pullRequestNo": 409
    },
    {
      "name": "steipete",
      "id": 58493,
      "comment_id": 3140446226,
      "created_at": "2025-07-31T15:40:05Z",
      "repoId": 987670088,
      "pullRequestNo": 414
    },
    {
      "name": "lmn451",
      "id": 14910239,
      "comment_id": 3141170246,
      "created_at": "2025-07-31T19:54:14Z",
      "repoId": 987670088,
      "pullRequestNo": 429
    },
    {
      "name": "petersanchez",
      "id": 199166,
      "comment_id": 3141358800,
      "created_at": "2025-07-31T21:14:55Z",
      "repoId": 987670088,
      "pullRequestNo": 434
    },
    {
      "name": "alvaro17f",
      "id": 89421445,
      "comment_id": 3144148093,
      "created_at": "2025-08-01T10:50:27Z",
      "repoId": 987670088,
      "pullRequestNo": 451
    },
    {
      "name": "bbrodriges",
      "id": 871322,
      "comment_id": 3144263924,
      "created_at": "2025-08-01T11:33:11Z",
      "repoId": 987670088,
      "pullRequestNo": 454
    },
    {
      "name": "SyedaAnshrahGillani",
      "id": 90501474,
      "comment_id": 3144865858,
      "created_at": "2025-08-01T14:57:07Z",
      "repoId": 987670088,
      "pullRequestNo": 460
    },
    {
      "name": "spachava753",
      "id": 34797853,
      "comment_id": 3145329017,
      "created_at": "2025-08-01T17:49:37Z",
      "repoId": 987670088,
      "pullRequestNo": 469
    },
    {
      "name": "tabletcorry",
      "id": 456754,
      "comment_id": 3145908475,
      "created_at": "2025-08-01T22:18:28Z",
      "repoId": 987670088,
      "pullRequestNo": 480
    },
    {
      "name": "yumosx",
      "id": 141902143,
      "comment_id": 3146472558,
      "created_at": "2025-08-02T12:24:29Z",
      "repoId": 987670088,
      "pullRequestNo": 504
    },
    {
      "name": "bold84",
      "id": 21118257,
      "comment_id": 3146962342,
      "created_at": "2025-08-03T04:07:16Z",
      "repoId": 987670088,
      "pullRequestNo": 519
    },
    {
      "name": "jooray",
      "id": 1028688,
      "comment_id": 3148713433,
      "created_at": "2025-08-03T21:35:15Z",
      "repoId": 987670088,
      "pullRequestNo": 527
    },
    {
      "name": "Ed4ward",
      "id": 153800328,
      "comment_id": 3150375016,
      "created_at": "2025-08-04T12:16:16Z",
      "repoId": 987670088,
      "pullRequestNo": 539
    },
    {
      "name": "ngnhng",
      "id": 51743767,
      "comment_id": 3150846779,
      "created_at": "2025-08-04T14:01:30Z",
      "repoId": 987670088,
      "pullRequestNo": 546
    },
    {
      "name": "zloeber",
      "id": 4702624,
      "comment_id": 3152513500,
      "created_at": "2025-08-04T21:55:42Z",
      "repoId": 987670088,
      "pullRequestNo": 564
    },
    {
      "name": "nelsenm2",
      "id": 197524521,
      "comment_id": 3152872109,
      "created_at": "2025-08-05T00:24:50Z",
      "repoId": 987670088,
      "pullRequestNo": 569
    },
    {
      "name": "mohseenrm",
      "id": 10768371,
      "comment_id": 3153159347,
      "created_at": "2025-08-05T03:39:12Z",
      "repoId": 987670088,
      "pullRequestNo": 574
    },
    {
      "name": "0xWelt",
      "id": 49543594,
      "comment_id": 3157331134,
      "created_at": "2025-08-06T04:07:52Z",
      "repoId": 987670088,
      "pullRequestNo": 584
    },
    {
      "name": "kslamph",
      "id": 15257433,
      "comment_id": 3157402768,
      "created_at": "2025-08-06T04:56:35Z",
      "repoId": 987670088,
      "pullRequestNo": 585
    },
    {
      "name": "kslamph",
      "id": 15257433,
      "comment_id": 3157429309,
      "created_at": "2025-08-06T05:14:23Z",
      "repoId": 987670088,
      "pullRequestNo": 585
    },
    {
      "name": "Sunsvea",
      "id": 14066471,
      "comment_id": 3159014183,
      "created_at": "2025-08-06T10:04:39Z",
      "repoId": 987670088,
      "pullRequestNo": 593
    },
    {
      "name": "taciturnaxolotl",
      "id": 92754843,
      "comment_id": 3160702345,
      "created_at": "2025-08-06T15:48:47Z",
      "repoId": 987670088,
      "pullRequestNo": 606
    },
    {
      "name": "bashbunni",
      "id": 15822994,
      "comment_id": 3160746002,
      "created_at": "2025-08-06T16:02:06Z",
      "repoId": 987670088,
      "pullRequestNo": 187
    },
    {
      "name": "edafonseca",
      "id": 3027921,
      "comment_id": 3161714270,
      "created_at": "2025-08-06T21:41:34Z",
      "repoId": 987670088,
      "pullRequestNo": 618
    },
    {
      "name": "smores56",
      "id": 22140449,
      "comment_id": 3161853491,
      "created_at": "2025-08-06T22:51:42Z",
      "repoId": 987670088,
      "pullRequestNo": 620
    },
    {
      "name": "danielsz",
      "id": 859131,
      "comment_id": 3163327861,
      "created_at": "2025-08-07T09:39:26Z",
      "repoId": 987670088,
      "pullRequestNo": 628
    },
    {
      "name": "pavelzw",
      "id": 29506042,
      "comment_id": 3164728921,
      "created_at": "2025-08-07T15:33:23Z",
      "repoId": 987670088,
      "pullRequestNo": 631
    },
    {
      "name": "CyrusZei",
      "id": 5053903,
      "comment_id": 3165875211,
      "created_at": "2025-08-07T21:45:30Z",
      "repoId": 987670088,
      "pullRequestNo": 638
    },
    {
      "name": "maxjustus",
      "id": 24899,
      "comment_id": 3166599830,
      "created_at": "2025-08-08T05:12:37Z",
      "repoId": 987670088,
      "pullRequestNo": 645
    },
    {
      "name": "akaytatsu",
      "id": 2520440,
      "comment_id": 3167400968,
      "created_at": "2025-08-08T10:32:51Z",
      "repoId": 987670088,
      "pullRequestNo": 647
    },
    {
      "name": "theguy000",
      "id": 52881001,
      "comment_id": 3167442675,
      "created_at": "2025-08-08T10:46:15Z",
      "repoId": 987670088,
      "pullRequestNo": 648
    },
    {
      "name": "pwnintended",
      "id": 92651319,
      "comment_id": 3169309904,
      "created_at": "2025-08-08T21:08:45Z",
      "repoId": 987670088,
      "pullRequestNo": 668
    },
    {
      "name": "tazjin",
      "id": 1552853,
      "comment_id": 3169412729,
      "created_at": "2025-08-08T22:05:40Z",
      "repoId": 987670088,
      "pullRequestNo": 672
    },
    {
      "name": "liznear",
      "id": 160093988,
      "comment_id": 3170486027,
      "created_at": "2025-08-09T08:15:27Z",
      "repoId": 987670088,
      "pullRequestNo": 681
    },
    {
      "name": "jamestrew",
      "id": 66286082,
      "comment_id": 3171975481,
      "created_at": "2025-08-09T17:55:31Z",
      "repoId": 987670088,
      "pullRequestNo": 689
    },
    {
      "name": "wwwjfy",
      "id": 126527,
      "comment_id": 3172676799,
      "created_at": "2025-08-10T14:35:04Z",
      "repoId": 987670088,
      "pullRequestNo": 702
    },
    {
      "name": "orospakr",
      "id": 16714,
      "comment_id": 3181859171,
      "created_at": "2025-08-13T01:01:30Z",
      "repoId": 987670088,
      "pullRequestNo": 746
    },
    {
      "name": "samiulsami",
      "id": 33352407,
      "comment_id": 3189231059,
      "created_at": "2025-08-14T17:12:20Z",
      "repoId": 987670088,
      "pullRequestNo": 779
    },
    {
      "name": "neomantra",
      "id": 26842,
      "comment_id": 3189674073,
      "created_at": "2025-08-14T19:42:53Z",
      "repoId": 987670088,
      "pullRequestNo": 752
    },
    {
      "name": "uri",
      "id": 676443,
      "comment_id": 3190313833,
      "created_at": "2025-08-15T00:58:11Z",
      "repoId": 987670088,
      "pullRequestNo": 782
    },
    {
      "name": "lpmitchell",
      "id": 5081038,
      "comment_id": 3191789654,
      "created_at": "2025-08-15T15:23:59Z",
      "repoId": 987670088,
      "pullRequestNo": 790
    },
    {
      "name": "marcosktsz",
      "id": 58952492,
      "comment_id": 3193569650,
      "created_at": "2025-08-16T10:29:10Z",
      "repoId": 987670088,
      "pullRequestNo": 798
    },
    {
      "name": "sainadh-d",
      "id": 15155045,
      "comment_id": 3193680786,
      "created_at": "2025-08-16T13:49:03Z",
      "repoId": 987670088,
      "pullRequestNo": 803
    },
    {
      "name": "ericcoleta",
      "id": 42539971,
      "comment_id": 3201263288,
      "created_at": "2025-08-19T15:38:48Z",
      "repoId": 987670088,
      "pullRequestNo": 835
    },
    {
      "name": "linw1995",
      "id": 13523027,
      "comment_id": 3209540243,
      "created_at": "2025-08-21T08:29:20Z",
      "repoId": 987670088,
      "pullRequestNo": 850
    },
    {
      "name": "khareyash05",
      "id": 60147732,
      "comment_id": 3213528951,
      "created_at": "2025-08-22T08:26:23Z",
      "repoId": 987670088,
      "pullRequestNo": 860
    },
    {
      "name": "mpj",
      "id": 17815,
      "comment_id": 3214796891,
      "created_at": "2025-08-22T15:35:12Z",
      "repoId": 987670088,
      "pullRequestNo": 865
    },
    {
      "name": "xPrimeTime",
      "id": 101987372,
      "comment_id": 3217970106,
      "created_at": "2025-08-24T09:28:11Z",
      "repoId": 987670088,
      "pullRequestNo": 873
    },
    {
      "name": "mercmobily",
      "id": 2128734,
      "comment_id": 3219992206,
      "created_at": "2025-08-25T12:00:54Z",
      "repoId": 987670088,
      "pullRequestNo": 882
    },
    {
      "name": "xhos",
      "id": 60789741,
      "comment_id": 3221119175,
      "created_at": "2025-08-25T17:26:06Z",
      "repoId": 987670088,
      "pullRequestNo": 892
    },
    {
      "name": "henrebotha",
      "id": 5593874,
      "comment_id": 3223793535,
      "created_at": "2025-08-26T11:34:17Z",
      "repoId": 987670088,
      "pullRequestNo": 900
    },
    {
      "name": "negz",
      "id": 1049349,
      "comment_id": 3232462357,
      "created_at": "2025-08-28T08:23:46Z",
      "repoId": 987670088,
      "pullRequestNo": 914
    },
    {
      "name": "undo76",
      "id": 1415667,
      "comment_id": 3235052544,
      "created_at": "2025-08-28T21:53:00Z",
      "repoId": 987670088,
      "pullRequestNo": 921
    },
    {
      "name": "andersonjoseph",
      "id": 22438127,
      "comment_id": 3237655829,
      "created_at": "2025-08-29T16:54:00Z",
      "repoId": 987670088,
      "pullRequestNo": 926
    },
    {
      "name": "tisDDM",
      "id": 77615100,
      "comment_id": 3240239275,
      "created_at": "2025-08-31T15:58:52Z",
      "repoId": 987670088,
      "pullRequestNo": 944
    },
    {
      "name": "shaitanu",
      "id": 117723026,
      "comment_id": 3259367914,
      "created_at": "2025-09-05T18:29:58Z",
      "repoId": 987670088,
      "pullRequestNo": 968
    },
    {
      "name": "vadiminshakov",
      "id": 26391516,
      "comment_id": 3267808993,
      "created_at": "2025-09-08T20:13:33Z",
      "repoId": 987670088,
      "pullRequestNo": 998
    },
    {
      "name": "adriens",
      "id": 5235127,
      "comment_id": 3270041072,
      "created_at": "2025-09-09T10:30:49Z",
      "repoId": 987670088,
      "pullRequestNo": 1000
    },
    {
      "name": "SubodhSenpai",
      "id": 116248387,
      "comment_id": 3275351636,
      "created_at": "2025-09-10T14:55:25Z",
      "repoId": 987670088,
      "pullRequestNo": 1008
    },
    {
      "name": "tauraamui",
      "id": 3159648,
      "comment_id": 3279503814,
      "created_at": "2025-09-11T09:31:52Z",
      "repoId": 987670088,
      "pullRequestNo": 1016
    },
    {
      "name": "kim0",
      "id": 59667,
      "comment_id": 3282025022,
      "created_at": "2025-09-11T17:37:57Z",
      "repoId": 987670088,
      "pullRequestNo": 1017
    },
    {
      "name": "Amolith",
      "id": 29460675,
      "comment_id": 3285628360,
      "created_at": "2025-09-12T15:00:12Z",
      "repoId": 987670088,
      "pullRequestNo": 1025
    },
    {
      "name": "WhiskeyJack96",
      "id": 10688621,
      "comment_id": 3290164209,
      "created_at": "2025-09-15T01:16:08Z",
      "repoId": 987670088,
      "pullRequestNo": 1037
    },
    {
      "name": "Grin1024",
      "id": 34613592,
      "comment_id": 3290570050,
      "created_at": "2025-09-15T05:42:29Z",
      "repoId": 987670088,
      "pullRequestNo": 1042
    },
    {
      "name": "dvcrn",
      "id": 688326,
      "comment_id": 3296702457,
      "created_at": "2025-09-16T08:48:17Z",
      "repoId": 987670088,
      "pullRequestNo": 1056
    },
    {
      "name": "khushveer007",
      "id": 122660325,
      "comment_id": 3301369568,
      "created_at": "2025-09-17T05:32:53Z",
      "repoId": 987670088,
      "pullRequestNo": 1065
    },
    {
      "name": "msteinert",
      "id": 202852,
      "comment_id": 3312218015,
      "created_at": "2025-09-19T13:31:42Z",
      "repoId": 987670088,
      "pullRequestNo": 1084
    },
    {
      "name": "zoete",
      "id": 33318916,
      "comment_id": 3314945939,
      "created_at": "2025-09-20T12:37:42Z",
      "repoId": 987670088,
      "pullRequestNo": 1095
    },
    {
      "name": "Kaneki-x",
      "id": 6857108,
      "comment_id": 3338743039,
      "created_at": "2025-09-26T13:30:16Z",
      "repoId": 987670088,
      "pullRequestNo": 1135
    },
    {
      "name": "maxious",
      "id": 81432,
      "comment_id": 3341700737,
      "created_at": "2025-09-27T13:09:22Z",
      "repoId": 987670088,
      "pullRequestNo": 1141
    },
    {
      "name": "Wangch29",
      "id": 115294077,
      "comment_id": 3344526018,
      "created_at": "2025-09-29T01:19:40Z",
      "repoId": 987670088,
      "pullRequestNo": 1148
    },
    {
      "name": "kucukkanat",
      "id": 914316,
      "comment_id": 3369230313,
      "created_at": "2025-10-05T18:13:57Z",
      "repoId": 987670088,
      "pullRequestNo": 1195
    },
    {
      "name": "thuggys",
      "id": 150315417,
      "comment_id": 3369149503,
      "created_at": "2025-10-05T15:59:55Z",
      "repoId": 987670088,
      "pullRequestNo": 1194
    },
    {
      "name": "nikaro",
      "id": 3918653,
      "comment_id": 3373586148,
      "created_at": "2025-10-06T19:31:50Z",
      "repoId": 987670088,
      "pullRequestNo": 1200
    },
    {
      "name": "daps94",
      "id": 35882689,
      "comment_id": 3395964275,
      "created_at": "2025-10-13T05:56:20Z",
      "repoId": 987670088,
      "pullRequestNo": 1223
    },
    {
      "name": "BrunoKrugel",
      "id": 30608179,
      "comment_id": 3411978929,
      "created_at": "2025-10-16T17:30:07Z",
      "repoId": 987670088,
      "pullRequestNo": 1245
    },
    {
      "name": "dpolishuk",
      "id": 466424,
      "comment_id": 3418756045,
      "created_at": "2025-10-18T19:24:00Z",
      "repoId": 987670088,
      "pullRequestNo": 1254
    },
    {
      "name": "Jesssullivan",
      "id": 37297218,
      "comment_id": 3439361465,
      "created_at": "2025-10-23T21:50:17Z",
      "repoId": 987670088,
      "pullRequestNo": 1292
    },
    {
      "name": "mmangkad",
      "id": 176301910,
      "comment_id": 3440286180,
      "created_at": "2025-10-24T01:32:47Z",
      "repoId": 987670088,
      "pullRequestNo": 1294
    },
    {
      "name": "blouflab",
      "id": 227565774,
      "comment_id": 3444483981,
      "created_at": "2025-10-24T18:59:01Z",
      "repoId": 987670088,
      "pullRequestNo": 1296
    },
    {
      "name": "Supratim69",
      "id": 128067781,
      "comment_id": 3444891894,
      "created_at": "2025-10-24T20:58:01Z",
      "repoId": 987670088,
      "pullRequestNo": 1299
    },
    {
      "name": "plandem",
      "id": 1381366,
      "comment_id": 3446669312,
      "created_at": "2025-10-25T12:52:04Z",
      "repoId": 987670088,
      "pullRequestNo": 1302
    },
    {
      "name": "dawndiy",
      "id": 1512740,
      "comment_id": 3456210693,
      "created_at": "2025-10-28T12:24:21Z",
      "repoId": 987670088,
      "pullRequestNo": 1312
    },
    {
      "name": "bradflaugher",
      "id": 16511019,
      "comment_id": 3458922489,
      "created_at": "2025-10-28T23:13:15Z",
      "repoId": 987670088,
      "pullRequestNo": 1324
    },
    {
      "name": "teras",
      "id": 592568,
      "comment_id": 3465825058,
      "created_at": "2025-10-30T02:04:26Z",
      "repoId": 987670088,
      "pullRequestNo": 1335
    },
    {
      "name": "heynemann",
      "id": 60965,
      "comment_id": 3475594747,
      "created_at": "2025-11-01T03:21:03Z",
      "repoId": 987670088,
      "pullRequestNo": 1357
    },
    {
      "name": "niklasschaeffer",
      "id": 1948226,
      "comment_id": 3476119118,
      "created_at": "2025-11-01T10:06:05Z",
      "repoId": 987670088,
      "pullRequestNo": 1358
    },
    {
      "name": "LarsArtmann",
      "id": 23587853,
      "comment_id": 3488527230,
      "created_at": "2025-11-05T00:18:02Z",
      "repoId": 987670088,
      "pullRequestNo": 1384
    },
    {
      "name": "danielmerja",
      "id": 30878766,
      "comment_id": 3492618827,
      "created_at": "2025-11-05T17:59:51Z",
      "repoId": 987670088,
      "pullRequestNo": 1387
    },
    {
      "name": "nanvenomous",
      "id": 43622197,
      "comment_id": 3497693075,
      "created_at": "2025-11-06T15:05:00Z",
      "repoId": 987670088,
      "pullRequestNo": 1392
    },
    {
      "name": "novalis78",
      "id": 190390,
      "comment_id": 3506836115,
      "created_at": "2025-11-08T19:53:10Z",
      "repoId": 987670088,
      "pullRequestNo": 1408
    },
    {
      "name": "alewtschuk",
      "id": 19924911,
      "comment_id": 3520127241,
      "created_at": "2025-11-12T05:44:54Z",
      "repoId": 987670088,
      "pullRequestNo": 1429
    },
    {
      "name": "Iflgit",
      "id": 24231648,
      "comment_id": 3536325469,
      "created_at": "2025-11-15T10:46:24Z",
      "repoId": 987670088,
      "pullRequestNo": 1450
    },
    {
      "name": "iainlane",
      "id": 321014,
      "comment_id": 3539345738,
      "created_at": "2025-11-16T20:55:47Z",
      "repoId": 987670088,
      "pullRequestNo": 1457
    },
    {
      "name": "micahwalter",
      "id": 47419,
      "comment_id": 3553482361,
      "created_at": "2025-11-19T15:59:07Z",
      "repoId": 987670088,
      "pullRequestNo": 1478
    },
    {
      "name": "heimoshuiyu",
      "id": 22657774,
      "comment_id": 3565689668,
      "created_at": "2025-11-22T05:23:17Z",
      "repoId": 987670088,
      "pullRequestNo": 1496
    },
    {
      "name": "masroor-ahmad",
      "id": 75073229,
      "comment_id": 3592527587,
      "created_at": "2025-11-30T12:55:09Z",
      "repoId": 987670088,
      "pullRequestNo": 1532
    },
    {
      "name": "thezbm",
      "id": 24851999,
      "comment_id": 3595049411,
      "created_at": "2025-12-01T07:39:02Z",
      "repoId": 987670088,
      "pullRequestNo": 1534
    },
    {
      "name": "marifcelik",
      "id": 46600975,
      "comment_id": 3610641638,
      "created_at": "2025-12-04T07:17:10Z",
      "repoId": 987670088,
      "pullRequestNo": 1546
    },
    {
      "name": "mike1858",
      "id": 223734115,
      "comment_id": 3615055552,
      "created_at": "2025-12-05T02:26:29Z",
      "repoId": 987670088,
      "pullRequestNo": 1553
    },
    {
      "name": "Guxinpei",
      "id": 20122411,
      "comment_id": 3617461839,
      "created_at": "2025-12-05T15:51:04Z",
      "repoId": 987670088,
      "pullRequestNo": 1555
    },
    {
      "name": "mikluko",
      "id": 42915,
      "comment_id": 3620605876,
      "created_at": "2025-12-06T15:43:45Z",
      "repoId": 987670088,
      "pullRequestNo": 1558
    },
    {
      "name": "Gustave-241021",
      "id": 185743951,
      "comment_id": 3620851967,
      "created_at": "2025-12-06T18:13:11Z",
      "repoId": 987670088,
      "pullRequestNo": 1560
    },
    {
      "name": "mengwong",
      "id": 1480631,
      "comment_id": 3636765109,
      "created_at": "2025-12-10T12:04:50Z",
      "repoId": 987670088,
      "pullRequestNo": 1592
    },
    {
      "name": "nonsleepr",
      "id": 2337602,
      "comment_id": 3644171671,
      "created_at": "2025-12-11T23:09:21Z",
      "repoId": 987670088,
      "pullRequestNo": 1611
    },
    {
      "name": "strawberry-code",
      "id": 18684103,
      "comment_id": 3650628850,
      "created_at": "2025-12-14T09:41:12Z",
      "repoId": 987670088,
      "pullRequestNo": 1628
    },
    {
      "name": "flatsponge",
      "id": 104839509,
      "comment_id": 3673002560,
      "created_at": "2025-12-19T01:11:45Z",
      "repoId": 987670088,
      "pullRequestNo": 1668
    },
    {
      "name": "jonhoo",
      "id": 176295,
      "comment_id": 3674853134,
      "created_at": "2025-12-19T12:14:08Z",
      "repoId": 987670088,
      "pullRequestNo": 1675
    },
    {
      "name": "Mr777x-enf",
      "id": 248610315,
      "comment_id": 3682737876,
      "created_at": "2025-12-22T16:07:47Z",
      "repoId": 987670088,
      "pullRequestNo": 1694
    },
    {
      "name": "yuguorui",
      "id": 6182414,
      "comment_id": 3687495909,
      "created_at": "2025-12-23T17:59:11Z",
      "repoId": 987670088,
      "pullRequestNo": 1709
    },
    {
      "name": "aeroxy",
      "id": 2761307,
      "comment_id": 3693734613,
      "created_at": "2025-12-27T06:01:58Z",
      "repoId": 987670088,
      "pullRequestNo": 1723
    },
    {
      "name": "nikolayk812",
      "id": 23297850,
      "comment_id": 3704102069,
      "created_at": "2026-01-01T21:00:07Z",
      "repoId": 987670088,
      "pullRequestNo": 1748
    },
    {
      "name": "mohaanymo",
      "id": 244024658,
      "comment_id": 3725028621,
      "created_at": "2026-01-08T18:01:11Z",
      "repoId": 987670088,
      "pullRequestNo": 1799
    },
    {
      "name": "zyriab",
      "id": 2111910,
      "comment_id": 3725966281,
      "created_at": "2026-01-08T21:44:05Z",
      "repoId": 987670088,
      "pullRequestNo": 1801
    },
    {
      "name": "aleksclark",
      "id": 607132,
      "comment_id": 3729687747,
      "created_at": "2026-01-09T16:28:21Z",
      "repoId": 987670088,
      "pullRequestNo": 1811
    },
    {
      "name": "jeis4wpi",
      "id": 42679190,
      "comment_id": 3735501265,
      "created_at": "2026-01-11T19:19:03Z",
      "repoId": 987670088,
      "pullRequestNo": 1827
    },
    {
      "name": "uppet",
      "id": 110209,
      "comment_id": 3738688581,
      "created_at": "2026-01-12T13:58:05Z",
      "repoId": 987670088,
      "pullRequestNo": 1830
    },
    {
      "name": "andreasdotorg",
      "id": 153248,
      "comment_id": 3740767910,
      "created_at": "2026-01-12T22:16:05Z",
      "repoId": 987670088,
      "pullRequestNo": 1841
    },
    {
      "name": "kuxoapp",
      "id": 254052994,
      "comment_id": 3747622477,
      "created_at": "2026-01-14T04:18:44Z",
      "repoId": 987670088,
      "pullRequestNo": 1864
    },
    {
      "name": "mhpenta",
      "id": 183146177,
      "comment_id": 3749703014,
      "created_at": "2026-01-14T14:02:04Z",
      "repoId": 987670088,
      "pullRequestNo": 1870
    },
    {
      "name": "huaiyuWangh",
      "id": 34158348,
      "comment_id": 3785195950,
      "created_at": "2026-01-22T15:58:33Z",
      "repoId": 987670088,
      "pullRequestNo": 1943
    },
    {
      "name": "akitaonrails",
      "id": 2840,
      "comment_id": 3786408984,
      "created_at": "2026-01-22T19:57:59Z",
      "repoId": 987670088,
      "pullRequestNo": 1945
    },
    {
      "name": "mcowger",
      "id": 1929548,
      "comment_id": 3787591535,
      "created_at": "2026-01-23T00:44:49Z",
      "repoId": 987670088,
      "pullRequestNo": 1950
    },
    {
      "name": "jerilynzheng",
      "id": 15837981,
      "comment_id": 3788071777,
      "created_at": "2026-01-23T04:00:52Z",
      "repoId": 987670088,
      "pullRequestNo": 1951
    },
    {
      "name": "AnyCPU",
      "id": 2059051,
      "comment_id": 3791901071,
      "created_at": "2026-01-23T19:14:55Z",
      "repoId": 987670088,
      "pullRequestNo": 1967
    },
    {
      "name": "billycao",
      "id": 543122,
      "comment_id": 3793624061,
      "created_at": "2026-01-24T03:06:50Z",
      "repoId": 987670088,
      "pullRequestNo": 1971
    },
    {
      "name": "gdamjan",
      "id": 81654,
      "comment_id": 3795660594,
      "created_at": "2026-01-24T22:42:46Z",
      "repoId": 987670088,
      "pullRequestNo": 1978
    },
    {
      "name": "oug-t",
      "id": 252025851,
      "comment_id": 3811704206,
      "created_at": "2026-01-28T14:42:29Z",
      "repoId": 987670088,
      "pullRequestNo": 2022
    },
    {
      "name": "liannnix",
      "id": 779758,
      "comment_id": 3815867093,
      "created_at": "2026-01-29T07:05:12Z",
      "repoId": 987670088,
      "pullRequestNo": 2043
    },
    {
      "name": "bittoby",
      "id": 218712309,
      "comment_id": 3824931235,
      "created_at": "2026-01-30T17:52:15Z",
      "repoId": 987670088,
      "pullRequestNo": 2065
    },
    {
      "name": "ijt",
      "id": 15530,
      "comment_id": 3832667774,
      "created_at": "2026-02-02T03:06:23Z",
      "repoId": 987670088,
      "pullRequestNo": 2080
    },
    {
      "name": "khalilgharbaoui",
      "id": 8024057,
      "comment_id": 3832796060,
      "created_at": "2026-02-02T04:04:04Z",
      "repoId": 987670088,
      "pullRequestNo": 2081
    },
    {
      "name": "acmacalister",
      "id": 1024755,
      "comment_id": 3837172797,
      "created_at": "2026-02-02T19:27:08Z",
      "repoId": 987670088,
      "pullRequestNo": 2095
    },
    {
      "name": "zhiquanchi",
      "id": 29973289,
      "comment_id": 3845838711,
      "created_at": "2026-02-04T07:39:06Z",
      "repoId": 987670088,
      "pullRequestNo": 2112
    },
    {
      "name": "inquam",
      "id": 1265038,
      "comment_id": 3849304908,
      "created_at": "2026-02-04T19:22:33Z",
      "repoId": 987670088,
      "pullRequestNo": 2124
    },
    {
      "name": "nickgrim",
      "id": 8376,
      "comment_id": 3852565144,
      "created_at": "2026-02-05T10:17:46Z",
      "repoId": 987670088,
      "pullRequestNo": 2131
    },
    {
      "name": "francescoalemanno",
      "id": 50984334,
      "comment_id": 3858464719,
      "created_at": "2026-02-06T07:16:50Z",
      "repoId": 987670088,
      "pullRequestNo": 2142
    },
    {
      "name": "biisal",
      "id": 153633053,
      "comment_id": 3866503536,
      "created_at": "2026-02-08T08:15:11Z",
      "repoId": 987670088,
      "pullRequestNo": 2164
    },
    {
      "name": "mishudark",
      "id": 211144,
      "comment_id": 3866939317,
      "created_at": "2026-02-08T10:27:09Z",
      "repoId": 987670088,
      "pullRequestNo": 2165
    },
    {
      "name": "portertech",
      "id": 149630,
      "comment_id": 3878650318,
      "created_at": "2026-02-10T15:39:14Z",
      "repoId": 987670088,
      "pullRequestNo": 2183
    },
    {
      "name": "wallacegibbon",
      "id": 22029486,
      "comment_id": 3890517245,
      "created_at": "2026-02-12T11:58:04Z",
      "repoId": 987670088,
      "pullRequestNo": 2203
    },
    {
      "name": "PHPCraftdream",
      "id": 14233546,
      "comment_id": 3893502046,
      "created_at": "2026-02-12T21:34:20Z",
      "repoId": 987670088,
      "pullRequestNo": 2212
    },
    {
      "name": "maxbrunet",
      "id": 32458727,
      "comment_id": 3905030983,
      "created_at": "2026-02-15T19:14:26Z",
      "repoId": 987670088,
      "pullRequestNo": 2229
    },
    {
      "name": "0xarcher",
      "id": 18182408,
      "comment_id": 3907297580,
      "created_at": "2026-02-16T09:16:57Z",
      "repoId": 987670088,
      "pullRequestNo": 2236
    },
    {
      "name": "julienrbrt",
      "id": 29894366,
      "comment_id": 3920039276,
      "created_at": "2026-02-18T10:37:53Z",
      "repoId": 987670088,
      "pullRequestNo": 2246
    },
    {
      "name": "erikstmartin",
      "id": 50041,
      "comment_id": 3937646631,
      "created_at": "2026-02-20T23:35:55Z",
      "repoId": 987670088,
      "pullRequestNo": 2274
    },
    {
      "name": "Jaylonnet",
      "id": 101283545,
      "comment_id": 3944717192,
      "created_at": "2026-02-23T13:12:50Z",
      "repoId": 987670088,
      "pullRequestNo": 2293
    },
    {
      "name": "mavaa",
      "id": 1224973,
      "comment_id": 3966463081,
      "created_at": "2026-02-26T12:56:51Z",
      "repoId": 987670088,
      "pullRequestNo": 2314
    },
    {
      "name": "aisk",
      "id": 699636,
      "comment_id": 3968065934,
      "created_at": "2026-02-26T17:23:44Z",
      "repoId": 987670088,
      "pullRequestNo": 2315
    },
    {
      "name": "detro",
      "id": 114508,
      "comment_id": 3976601253,
      "created_at": "2026-02-28T07:36:40Z",
      "repoId": 987670088,
      "pullRequestNo": 2326
    },
    {
      "name": "taoeffect",
      "id": 138706,
      "comment_id": 3979067985,
      "created_at": "2026-03-01T04:22:00Z",
      "repoId": 987670088,
      "pullRequestNo": 2333
    },
    {
      "name": "vmfu",
      "id": 80844805,
      "comment_id": 3980616480,
      "created_at": "2026-03-01T17:51:04Z",
      "repoId": 987670088,
      "pullRequestNo": 2337
    },
    {
      "name": "ZeitbyteRepo",
      "id": 187110998,
      "comment_id": 4025287397,
      "created_at": "2026-03-09T17:00:06Z",
      "repoId": 987670088,
      "pullRequestNo": 2390
    },
    {
      "name": "seroperson",
      "id": 3791221,
      "comment_id": 4047392328,
      "created_at": "2026-03-12T14:53:20Z",
      "repoId": 987670088,
      "pullRequestNo": 2401
    },
    {
      "name": "xulongwu4",
      "id": 16892446,
      "comment_id": 4062024320,
      "created_at": "2026-03-15T02:30:55Z",
      "repoId": 987670088,
      "pullRequestNo": 2410
    },
    {
      "name": "nghiant03",
      "id": 102637959,
      "comment_id": 4077213520,
      "created_at": "2026-03-17T18:41:50Z",
      "repoId": 987670088,
      "pullRequestNo": 2421
    }
  ]
}

================================================
FILE: .github/dependabot.yml
================================================
version: 2

updates:
  - package-ecosystem: "gomod"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "05:00"
      timezone: "America/New_York"
    labels:
      - "area: dependencies"
    commit-message:
      prefix: "chore"
      include: "scope"
    groups:
      all:
        patterns:
          - "*"
    ignore:
      - dependency-name: github.com/charmbracelet/bubbletea/v2
        versions:
          - v2.0.0-beta1
      - dependency-name: github.com/charmbracelet/lipgloss/v2
        versions:
          - v2.0.0-beta1

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "05:00"
      timezone: "America/New_York"
    labels:
      - "area: dependencies"
    commit-message:
      prefix: "chore"
      include: "scope"
    groups:
      all:
        patterns:
          - "*"


================================================
FILE: .github/entitlements.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
  </dict>
</plist>


================================================
FILE: .github/labeler.yml
================================================
# NOTE(@andreynering): We should have a single entry per label, because if we
# have multiple the action would only apply the label if ALL of them match.

"area: ci":
  - "/^ci: /i"
"area: crush run":
  - "/crush run/i"
  - "/headless/i"
  - "/non-interactive/i"
"area: diff":
  - "/diff/i"
"area: docs":
  - "/(docs|documentation|readme)/i"
"area: images":
  - "/image/i"
"area: lsp":
  - "/lsp/i"
"area: mcp":
  - "/mcp/i"
"area: mouse":
  - "/(mouse|scroll)/i"
"area: onboarding":
  - "/(onboarding)/i"
"area: permissions":
  - "/permission/i"
"area: releasing":
  - "/(release|releasing|aur|brew|nix|npm|scoop|termux|winget)/i"
"area: session":
  - "/session/i"
"area: shell":
  - "/shell/i"
"area: themes":
  - "/theme/i"
"area: tools":
  - "/tool/i"
"os: android":
  - "/(android|termux)/i"
"os: linux":
  - "/(linux|fedora|debian|ubuntu)/i"
"os: macos":
  - "/(macos|osx|darwin)/i"
"os: windows":
  - "/(windows|win10|win11|win32|wsl|scoop|winget)/i"
"panic / crash":
  - "/(panic|crash|segfault)/i"
"provider: anthropic claude":
  - "/(anthropic|claude)/i"
"provider: aws bedrock":
  - "/(aws|bedrock)/i"
"provider: azure":
  - "/azure/i"
"provider: github copilot":
  - "/copilot/i"
"provider: google gemini":
  - "/gemini/i"
"provider: google vertex":
  - "/vertex/i"
"provider: hyper":
  - "/hyper/i"
"provider: kimi":
  - "/kimi/i"
"provider: minimax":
  - "/minimax/i"
"provider: ollama":
  - "/llama/i"
"provider: openai chatgpt":
  - "/(openai|gpt)/i"
"provider: openrouter":
  - "/openrouter/i"
"provider: qwen":
  - "/qwen/i"
"provider: vercel":
  - "/vercel/i"
"provider: xai grok":
  - "/(xai|x\\.ai|grok)/i"
"security":
  - "/(security|vulnerability|exploit)/i"


================================================
FILE: .github/workflows/build.yml
================================================
name: build
on: [push, pull_request]

permissions:
  contents: read

concurrency:
  group: build-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
        with:
          go-version-file: go.mod
      - run: go mod tidy
      - run: git diff --exit-code
      - run: go build -race ./...
      - run: go test -race -failfast ./...


================================================
FILE: .github/workflows/cla.yml
================================================
name: "CLA Assistant"

on:
  issue_comment:
    types: [created]
  pull_request_target:
    types: [opened, closed, synchronize]

permissions:
  actions: write
  contents: write
  pull-requests: write
  statuses: write

jobs:
  CLAAssistant:
    if: github.repository == 'charmbracelet/crush'
    runs-on: ubuntu-latest
    steps:
      - name: "CLA Assistant"
        if: |
          github.event.comment.body == 'recheck' ||
          github.event.comment.body == 'I have read the Contributor License Agreement (CLA) and hereby sign the CLA.' ||
          github.event_name == 'pull_request_target'
        uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
        env:
          GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
        with:
          path-to-signatures: ".github/cla-signatures.json"
          path-to-document: "https://github.com/charmbracelet/crush/blob/main/CLA.md"
          branch: "main"
          allowlist: charmcli,charmcrush,dependabot[bot],Copilot
          custom-pr-sign-comment: "I have read the Contributor License Agreement (CLA) and hereby sign the CLA."
          custom-notsigned-prcomment: "Thank you for your submission. We really appreciate it! Like many open-source projects, we ask that you sign our [Contributor License Agreement](https://github.com/charmbracelet/crush/blob/main/CLA.md) before we can accept your contribution. You can sign the CLA by just posting a Pull Request comment same as the below format."
          lock-pullrequest-aftermerge: false
          signed-commit-message: "chore(legal): @$contributorName has signed the CLA"


================================================
FILE: .github/workflows/labeler.yml
================================================
name: labeler

on:
  issues:
    types: [opened]
  pull_request_target:
    types: [opened]
  workflow_dispatch:
    inputs:
      issue-number:
        description: "Issue/PR #"
        required: true
        type: string

permissions:
  issues: write
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4
        with:
          configuration-path: .github/labeler.yml
          enable-versioned-regex: 0
          include-title: 1
          include-body: 0
          repo-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          issue-number: ${{ github.event.inputs.issue-number || github.event.issue.number || github.event.pull_request.number }}


================================================
FILE: .github/workflows/lint-sync.yml
================================================
name: lint-sync
on:
  # schedule:
  #   # every Sunday at midnight
  #   - cron: "0 0 * * 0"
  workflow_dispatch: # allows manual triggering

permissions:
  contents: write
  pull-requests: write

jobs:
  lint:
    uses: charmbracelet/meta/.github/workflows/lint-sync.yml@main


================================================
FILE: .github/workflows/lint.yml
================================================
name: lint
on:
  push:
  pull_request:

jobs:
  lint:
    uses: charmbracelet/meta/.github/workflows/lint.yml@main
    with:
      golangci_path: .golangci.yml
      golangci_version: v2.10
      timeout: 10m


================================================
FILE: .github/workflows/nightly.yml
================================================
name: nightly

on:
  schedule:
    - cron: "0 0 * * *" # every day at midnight
  workflow_dispatch: # allows manual triggering

jobs:
  check:
    runs-on: ubuntu-latest
    outputs:
      should_run: ${{ steps.check.outputs.should_run }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 1
      - id: check
        env:
          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
        run: |
          if gh run list --workflow nightly.yml -c $(git rev-parse HEAD) -s success | grep 'completed'; then
            echo "should_run=false" >> $GITHUB_OUTPUT
          else
            echo "should_run=true" >> $GITHUB_OUTPUT
          fi
  nightly:
    needs: check
    if: needs.check.outputs.should_run == 'true'
    uses: charmbracelet/meta/.github/workflows/nightly.yml@main
    secrets:
      goreleaser_key: ${{ secrets.GORELEASER_KEY }}


================================================
FILE: .github/workflows/release.yml
================================================
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json

name: goreleaser

on:
  push:
    tags:
      - v*.*.*

concurrency:
  group: goreleaser
  cancel-in-progress: true

jobs:
  goreleaser:
    uses: charmbracelet/meta/.github/workflows/goreleaser.yml@main
    with:
      go_version: "1.26"
      macos_sign_entitlements: "./.github/entitlements.plist"
      # XXX: remove it after goreleaser 2.14.
      goreleaser_version: nightly
    secrets:
      docker_username: ${{ secrets.DOCKERHUB_USERNAME }}
      docker_token: ${{ secrets.DOCKERHUB_TOKEN }}
      gh_pat: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
      goreleaser_key: ${{ secrets.GORELEASER_KEY }}
      fury_token: ${{ secrets.FURY_TOKEN }}
      nfpm_gpg_key: ${{ secrets.NFPM_GPG_KEY }}
      nfpm_passphrase: ${{ secrets.NFPM_PASSPHRASE }}
      snapcraft_token: ${{ secrets.SNAPCRAFT_TOKEN }}
      aur_key: ${{ secrets.AUR_KEY }}
      macos_sign_p12: ${{ secrets.MACOS_SIGN_P12 }}
      macos_sign_password: ${{ secrets.MACOS_SIGN_PASSWORD }}
      macos_notary_issuer_id: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
      macos_notary_key_id: ${{ secrets.MACOS_NOTARY_KEY_ID }}
      macos_notary_key: ${{ secrets.MACOS_NOTARY_KEY }}


================================================
FILE: .github/workflows/schema-update.yml
================================================
name: Update files

on:
  push:
    branches: [main]
    paths:
      - "internal/config/**"
      - "internal/agent/hyper/**"

jobs:
  update-schema:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
      - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
        with:
          go-version-file: go.mod
      - run: go run . schema > ./schema.json
      - run: go generate ./internal/agent/hyper/...
      - uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v5
        with:
          commit_message: "chore: auto-update files"
          branch: main
          commit_user_name: Charm
          commit_user_email: 124303983+charmcli@users.noreply.github.com
          commit_author: Charm <124303983+charmcli@users.noreply.github.com>


================================================
FILE: .github/workflows/security.yml
================================================
name: "security"

on:
  pull_request:
  push:
    branches: [main]
  schedule:
    - cron: "0 2 * * *"

permissions:
  contents: read

concurrency:
  group: security-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  codeql:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        language: ["go", "actions"]
    permissions:
      actions: read
      contents: read
      pull-requests: read
      security-events: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
        with:
          languages: ${{ matrix.language }}
      - uses: github/codeql-action/autobuild@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
      - uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0

  grype:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      actions: read
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: anchore/scan-action@7037fa011853d5a11690026fb85feee79f4c946c # v7.3.2
        id: scan
        with:
          path: "."
          fail-build: true
          severity-cutoff: critical
      - uses: github/codeql-action/upload-sarif@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
        with:
          sarif_file: ${{ steps.scan.outputs.sarif }}

  govulncheck:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
        with:
          go-version: 1.26.1
      - name: Install govulncheck
        run: go install golang.org/x/vuln/cmd/govulncheck@latest
      - name: Run govulncheck
        run: |
          govulncheck -C . -format sarif ./... > results.sarif
      - uses: github/codeql-action/upload-sarif@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
        with:
          sarif_file: results.sarif

  dependency-review:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
        with:
          fail-on-severity: critical
          allow-licenses: BSD-2-Clause, BSD-3-Clause, MIT, MIT-0, Apache-2.0, MPL-2.0, ISC, LicenseRef-scancode-google-patent-license-golang, Unlicense


================================================
FILE: .github/workflows/snapshot.yml
================================================
name: snapshot

on:
  push:
    branches:
      - main

permissions:
  contents: read

concurrency:
  group: snapshot-${{ github.ref }}
  cancel-in-progress: true

jobs:
  snapshot:
    runs-on:
      # Use our own large runners with more CPU and RAM for faster builds
      group: releasers
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
        with:
          go-version-file: go.mod
      - uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
        with:
          version: "nightly"
          distribution: goreleaser-pro
          args: build --snapshot --clean
        env:
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}


================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
go.work.sum

# IDE specific files
.idea/
.vscode/
*.swp
*.swo

# OS specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*.log

# Binary output directory
/bin/
/dist/

# Local environment variables
.env
.env.local

**/.crush/**

/crush
/tmp/

manpages/
completions/crush.*sh
.prettierignore
.task


================================================
FILE: .golangci.yml
================================================
version: "2"
linters:
  enable:
    - bodyclose
    # - exhaustive
    # - goconst
    # - godot
    # - godox
    # - gomoddirectives
    - goprintffuncname
    # - gosec
    - misspell
    # - nakedret
    # - nestif
    # - nilerr
    - noctx
    - nolintlint
    # - prealloc
    # - revive
    - rowserrcheck
    - sqlclosecheck
    - staticcheck
    - tparallel
    # - unconvert
    # - unparam
    - whitespace
    # - wrapcheck
  disable:
    - errcheck
    - ineffassign
    - unused
  exclusions:
    generated: lax
    presets:
      - common-false-positives
    rules:
      - text: '(slog|log)\.\w+'
        linters:
          - noctx
issues:
  max-issues-per-linter: 0
  max-same-issues: 0
formatters:
  enable:
    - gofumpt
    - goimports
  exclusions:
    generated: lax


================================================
FILE: .goreleaser.yml
================================================
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
# vim: set ts=2 sw=2 tw=0 fo=jcroql
version: 2

project_name: crush

includes:
  - from_url:
      url: charmbracelet/meta/main/notarize.yaml

metadata:
  mod_timestamp: "{{ .CommitTimestamp }}"
  license: "FSL-1.1-MIT"
  homepage: "https://charm.sh/crush"
  description: "A powerful terminal-based AI assistant for developers, providing intelligent coding assistance directly in your terminal."
  full_description: "A powerful terminal-based AI assistant for developers, providing intelligent coding assistance directly in your terminal."
  maintainers:
    - "kujtimiihoxha <kujtim@charm.sh>"
    - "caarlos0 <carlos@charm.sh>" # for aur

nightly:
  publish_release: true
  keep_single_release: true
  version_template: "{{ incminor .Version }}-nightly"

snapshot:
  version_template: "0.0.0-{{ .Timestamp }}"

before:
  hooks:
    - go mod tidy
    - rm -rf completions
    - mkdir completions
    - rm -rf manpages
    - mkdir manpages
    - sh -c 'go run . completion bash >./completions/crush.bash'
    - sh -c 'go run . completion zsh >./completions/crush.zsh'
    - sh -c 'go run . completion fish >./completions/crush.fish'
    - sh -c 'go run . man | gzip -c >./manpages/crush.1.gz'

# gomod:
#   proxy: true

builds:
  - env:
      - CGO_ENABLED=0
      - GOEXPERIMENT=greenteagc
    goos:
      - linux
      - darwin
      - windows
      - freebsd
      - openbsd
      - netbsd
      - android
    goarch:
      - amd64
      - arm64
      - "386"
      - arm
    goarm:
      - "7"
    ignore:
      - goos: android
        goarch: amd64
      - goos: android
        goarch: arm
      - goos: android
        goarch: "386"
      - goos: windows
        goarch: arm
    ldflags:
      - -s -w -X github.com/charmbracelet/crush/internal/version.Version={{.Version}}
    flags:
      - -trimpath

archives:
  - name_template: >-
      crush_
      {{- .Version }}_
      {{- title .Os }}_
      {{- if eq .Arch "amd64" }}x86_64
      {{- else if eq .Arch "386" }}i386
      {{- else }}{{ .Arch }}{{ end }}
      {{- with .Arm}}v{{ . }}{{ end }}
    wrap_in_directory: true
    files:
      - README*
      - LICENSE*
      - manpages/*
      - completions/*
    format_overrides:
      - goos: windows
        formats: [zip]

checksum:
  name_template: "checksums.txt"

aur_sources:
  - private_key: "{{ .Env.AUR_KEY }}"
    disable: "{{ with .Prerelease }}true{{ end }}"
    git_url: "ssh://aur@aur.archlinux.org/crush.git"
    commit_author:
      name: "Charm"
      email: "charmcli@users.noreply.github.com"
    makedepends:
      - go
      - git
    prepare: |-
      go mod download
    build: |-
      mkdir completions
      mkdir manpages
      export CGO_CPPFLAGS="${CPPFLAGS}"
      export CGO_CFLAGS="${CFLAGS}"
      export CGO_CXXFLAGS="${CXXFLAGS}"
      export CGO_LDFLAGS="${LDFLAGS}"
      export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw"
      go build -ldflags="-w -s -buildid='' -linkmode=external -X github.com/charmbracelet/crush/internal/version.Version=v${pkgver}" .
      ./crush completion bash >./completions/crush.bash
      ./crush completion zsh >./completions/crush.zsh
      ./crush completion fish >./completions/crush.fish
      ./crush man | gzip -c >./manpages/crush.1.gz
    package: |-
      # bin
      install -Dm755 "./crush" "${pkgdir}/usr/bin/crush"
      # license
      mkdir -p "${pkgdir}/usr/share/licenses/crush/"
      install -Dm644 ./LICENSE* "${pkgdir}/usr/share/licenses/crush/"
      # completions
      mkdir -p "${pkgdir}/usr/share/bash-completion/completions/"
      mkdir -p "${pkgdir}/usr/share/zsh/site-functions/"
      mkdir -p "${pkgdir}/usr/share/fish/vendor_completions.d/"
      install -Dm644 "./completions/crush.bash" "${pkgdir}/usr/share/bash-completion/completions/crush"
      install -Dm644 "./completions/crush.zsh" "${pkgdir}/usr/share/zsh/site-functions/_crush"
      install -Dm644 "./completions/crush.fish" "${pkgdir}/usr/share/fish/vendor_completions.d/crush.fish"
      # man pages
      install -Dm644 "./manpages/crush.1.gz" "${pkgdir}/usr/share/man/man1/crush.1.gz"
      # readme
      mkdir -pv "${pkgdir}/usr/share/doc/crush/"
      install -Dm644 README* "${pkgdir}/usr/share/doc/crush/"

aurs:
  - private_key: "{{ .Env.AUR_KEY }}"
    disable: "{{ with .Prerelease }}true{{ end }}"
    git_url: "ssh://aur@aur.archlinux.org/crush-bin.git"
    commit_author:
      name: "Charm"
      email: "charmcli@users.noreply.github.com"
    provides:
      - crush
    conflicts:
      - crush
    package: |-
      case "$CARCH" in
        aarch64)
          cd "${srcdir}/crush_${pkgver}_Linux_arm64"
          ;;
        *)
          cd "${srcdir}/crush_${pkgver}_Linux_${CARCH}"
          ;;
      esac
      # bin
      install -Dm755 "./crush" "${pkgdir}/usr/bin/crush"
      # license
      mkdir -p "${pkgdir}/usr/share/licenses/crush/"
      install -Dm644 ./LICENSE* "${pkgdir}/usr/share/licenses/crush/"
      # completions
      mkdir -p "${pkgdir}/usr/share/bash-completion/completions/"
      mkdir -p "${pkgdir}/usr/share/zsh/site-functions/"
      mkdir -p "${pkgdir}/usr/share/fish/vendor_completions.d/"
      install -Dm644 "./completions/crush.bash" "${pkgdir}/usr/share/bash-completion/completions/crush"
      install -Dm644 "./completions/crush.zsh" "${pkgdir}/usr/share/zsh/site-functions/_crush"
      install -Dm644 "./completions/crush.fish" "${pkgdir}/usr/share/fish/vendor_completions.d/crush.fish"
      # man pages
      install -Dm644 "./manpages/crush.1.gz" "${pkgdir}/usr/share/man/man1/crush.1.gz"
      # readme
      mkdir -pv "${pkgdir}/usr/share/doc/crush/"
      install -Dm644 README* "${pkgdir}/usr/share/doc/crush/"

furies:
  - disable: "{{ if (or .Prerelease .IsNightly) }}true{{ end }}"
    account: "{{ with .Env.FURY_TOKEN }}charmcli{{ else }}{{ end }}"
    secret_name: FURY_TOKEN

brews:
  - repository:
      owner: charmbracelet
      name: homebrew-tap
      token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
    skip_upload: "{{ with .Prerelease }}true{{ end }}"
    commit_author:
      name: "Charm"
      email: "charmcli@users.noreply.github.com"
    goarm: 7
    extra_install: |-
      bash_completion.install "completions/{{ .ProjectName }}.bash" => "{{ .ProjectName }}"
      zsh_completion.install "completions/{{ .ProjectName }}.zsh" => "_{{ .ProjectName }}"
      fish_completion.install "completions/{{ .ProjectName }}.fish"
      man1.install "manpages/{{ .ProjectName }}.1.gz"

scoops:
  - repository:
      owner: charmbracelet
      name: scoop-bucket
      token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
    skip_upload: "{{ with .Prerelease }}true{{ end }}"
    commit_author:
      name: "Charm"
      email: "charmcli@users.noreply.github.com"

npms:
  - name: "@charmland/crush"
    repository: "git+https://github.com/charmbracelet/crush.git"
    bugs: https://github.com/charmbracelet/crush/issues
    access: public
    disable: "{{ with .Prerelease }}true{{ end }}"

nfpms:
  - formats:
      - apk
      - deb
      - rpm
      - archlinux
      - termux.deb
    file_name_template: "{{ .ConventionalFileName }}"
    contents:
      - src: ./completions/crush.bash
        dst: '{{ if eq .Format "termux.deb" }}/data/data/com.termux/files/usr{{ end }}/etc/bash_completion.d/crush'
      - src: ./completions/crush.fish
        dst: '{{ if eq .Format "termux.deb" }}/data/data/com.termux/files{{ end }}/usr/share/fish/vendor_completions.d/crush.fish'
      - src: ./completions/crush.zsh
        dst: '{{ if eq .Format "termux.deb" }}/data/data/com.termux/files{{ end }}/usr/share/zsh/site-functions/_crush'
      - src: ./manpages/crush.1.gz
        dst: '{{ if eq .Format "termux.deb" }}/data/data/com.termux/files{{ end }}/usr/share/man/man1/crush.1.gz'
    rpm:
      signature:
        key_file: '{{ if ne (index .Env "GPG_KEY_PATH") "" }}{{ .Env.GPG_KEY_PATH }}{{ else }}{{ end }}'
    deb:
      signature:
        key_file: '{{ if ne (index .Env "GPG_KEY_PATH") "" }}{{ .Env.GPG_KEY_PATH }}{{ else }}{{ end }}'

signs:
  - cmd: cosign
    signature: "${artifact}.sigstore.json"
    args:
      - sign-blob
      - "--bundle=${signature}"
      - "${artifact}"
      - "--yes"
    artifacts: checksum
    output: true

source:
  enabled: true

sboms:
  - artifacts: archive
  - id: source
    artifacts: source

nix:
  - repository:
      owner: "charmbracelet"
      name: nur
      token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
    commit_author:
      name: "Charm"
      email: "charmcli@users.noreply.github.com"
    license: fsl11Mit
    formatter: nixfmt
    skip_upload: "{{ with .Prerelease }}true{{ end }}"
    extra_install: |-
      installManPage ./manpages/crush.1.gz
      installShellCompletion ./completions/*

winget:
  - publisher: charmbracelet
    copyright: Charmbracelet, Inc
    publisher_url: https://charm.land
    release_notes_url: "https://github.com/charmbracelet/crush/releases/tag/{{.Tag}}"
    license_url: https://github.com/charmbracelet/crush/blob/main/LICENSE.md
    skip_upload: "{{ with .Prerelease }}true{{ end }}"
    commit_author:
      name: "Charm"
      email: "charmcli@users.noreply.github.com"
    repository:
      owner: "charmbracelet"
      name: winget-pkgs
      token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
      branch: "crush-{{.Version}}"
      pull_request:
        enabled: true
        draft: false
        check_boxes: true
        base:
          owner: microsoft
          name: winget-pkgs
          branch: master
        body: |
          /cc @andreynering

changelog:
  sort: asc
  disable: "{{ .IsNightly }}"
  use: github
  filters:
    exclude:
      - "^(build|ci): "
      - "^chore: auto-update generated files$"
      - "^chore: docs$"
      - "^chore: schema update$"
      - "^chore: schema$"
      - "^chore: typo$"
      - "^chore: update schema$"
      - "^chore: update$"
      - "^chore\\(legal\\): "
      - "^chore\\(deps\\): "
      - "^docs: update$"
      - "^test:"
      - "^test\\("
      - "^v\\d.*"
      - "merge conflict"
      - "merge conflict"
      - Merge branch
      - Merge pull request
      - Merge remote-tracking branch
      - go mod tidy
      - "^wip "
      - "^wip:"
  groups:
    - title: "Deps"
      regexp: "^.*\\(deps\\)*:+.*$"
      order: 300
    - title: "New!"
      regexp: "^.*feat[(\\w)]*:+.*$"
      order: 100
    - title: "Fixed"
      regexp: "^.*fix[(\\w)]*:+.*$"
      order: 200
    - title: "Docs"
      regexp: "^.*docs[(\\w)]*:+.*$"
      order: 400
    - title: "Other stuff"
      order: 9999

release:
  prerelease: auto
  footer:
    from_url:
      url: https://raw.githubusercontent.com/charmbracelet/meta/main/footer.md


================================================
FILE: AGENTS.md
================================================
# Crush Development Guide

## Project Overview

Crush is a terminal-based AI coding assistant built in Go by
[Charm](https://charm.land). It connects to LLMs and gives them tools to read,
write, and execute code. It supports multiple providers (Anthropic, OpenAI,
Gemini, Bedrock, Copilot, Hyper, MiniMax, Vercel, and more), integrates with
LSPs for code intelligence, and supports extensibility via MCP servers and
agent skills.

The module path is `github.com/charmbracelet/crush`.

## Architecture

```
main.go                            CLI entry point (cobra via internal/cmd)
internal/
  app/app.go                       Top-level wiring: DB, config, agents, LSP, MCP, events
  cmd/                             CLI commands (root, run, login, models, stats, sessions)
  config/
    config.go                      Config struct, context file paths, agent definitions
    load.go                        crush.json loading and validation
    provider.go                    Provider configuration and model resolution
  agent/
    agent.go                       SessionAgent: runs LLM conversations per session
    coordinator.go                 Coordinator: manages named agents ("coder", "task")
    prompts.go                     Loads Go-template system prompts
    templates/                     System prompt templates (coder.md.tpl, task.md.tpl, etc.)
    tools/                         All built-in tools (bash, edit, view, grep, glob, etc.)
      mcp/                         MCP client integration
  session/session.go               Session CRUD backed by SQLite
  message/                         Message model and content types
  db/                              SQLite via sqlc, with migrations
    sql/                           Raw SQL queries (consumed by sqlc)
    migrations/                    Schema migrations
  lsp/                             LSP client manager, auto-discovery, on-demand startup
  ui/                              Bubble Tea v2 TUI (see internal/ui/AGENTS.md)
  permission/                      Tool permission checking and allow-lists
  skills/                          Skill file discovery and loading
  shell/                           Bash command execution with background job support
  event/                           Telemetry (PostHog)
  pubsub/                          Internal pub/sub for cross-component messaging
  filetracker/                     Tracks files touched per session
  history/                         Prompt history
```

### Key Dependency Roles

- **`charm.land/fantasy`**: LLM provider abstraction layer. Handles protocol
  differences between Anthropic, OpenAI, Gemini, etc. Used in `internal/app`
  and `internal/agent`.
- **`charm.land/bubbletea/v2`**: TUI framework powering the interactive UI.
- **`charm.land/lipgloss/v2`**: Terminal styling.
- **`charm.land/glamour/v2`**: Markdown rendering in the terminal.
- **`charm.land/catwalk`**: Snapshot/golden-file testing for TUI components.
- **`sqlc`**: Generates Go code from SQL queries in `internal/db/sql/`.

### Key Patterns

- **Config is a Service**: accessed via `config.Service`, not global state.
- **Tools are self-documenting**: each tool has a `.go` implementation and a
  `.md` description file in `internal/agent/tools/`.
- **System prompts are Go templates**: `internal/agent/templates/*.md.tpl`
  with runtime data injected.
- **Context files**: Crush reads AGENTS.md, CRUSH.md, CLAUDE.md, GEMINI.md
  (and `.local` variants) from the working directory for project-specific
  instructions.
- **Persistence**: SQLite + sqlc. All queries live in `internal/db/sql/`,
  generated code in `internal/db/`. Migrations in `internal/db/migrations/`.
- **Pub/sub**: `internal/pubsub` for decoupled communication between agent,
  UI, and services.
- **CGO disabled**: builds with `CGO_ENABLED=0` and
  `GOEXPERIMENT=greenteagc`.

## Build/Test/Lint Commands

- **Build**: `go build .` or `go run .`
- **Test**: `task test` or `go test ./...` (run single test:
  `go test ./internal/llm/prompt -run TestGetContextFromPaths`)
- **Update Golden Files**: `go test ./... -update` (regenerates `.golden`
  files when test output changes)
  - Update specific package:
    `go test ./internal/tui/components/core -update` (in this case,
    we're updating "core")
- **Lint**: `task lint:fix`
- **Format**: `task fmt` (`gofumpt -w .`)
- **Modernize**: `task modernize` (runs `modernize` which makes code
  simplifications)
- **Dev**: `task dev` (runs with profiling enabled)

## Code Style Guidelines

- **Imports**: Use `goimports` formatting, group stdlib, external, internal
  packages.
- **Formatting**: Use gofumpt (stricter than gofmt), enabled in
  golangci-lint.
- **Naming**: Standard Go conventions — PascalCase for exported, camelCase
  for unexported.
- **Types**: Prefer explicit types, use type aliases for clarity (e.g.,
  `type AgentName string`).
- **Error handling**: Return errors explicitly, use `fmt.Errorf` for
  wrapping.
- **Context**: Always pass `context.Context` as first parameter for
  operations.
- **Interfaces**: Define interfaces in consuming packages, keep them small
  and focused.
- **Structs**: Use struct embedding for composition, group related fields.
- **Constants**: Use typed constants with iota for enums, group in const
  blocks.
- **Testing**: Use testify's `require` package, parallel tests with
  `t.Parallel()`, `t.SetEnv()` to set environment variables. Always use
  `t.Tempdir()` when in need of a temporary directory. This directory does
  not need to be removed.
- **JSON tags**: Use snake_case for JSON field names.
- **File permissions**: Use octal notation (0o755, 0o644) for file
  permissions.
- **Log messages**: Log messages must start with a capital letter (e.g.,
  "Failed to save session" not "failed to save session").
  - This is enforced by `task lint:log` which runs as part of `task lint`.
- **Comments**: End comments in periods unless comments are at the end of the
  line.

## Testing with Mock Providers

When writing tests that involve provider configurations, use the mock
providers to avoid API calls:

```go
func TestYourFunction(t *testing.T) {
    // Enable mock providers for testing
    originalUseMock := config.UseMockProviders
    config.UseMockProviders = true
    defer func() {
        config.UseMockProviders = originalUseMock
        config.ResetProviders()
    }()

    // Reset providers to ensure fresh mock data
    config.ResetProviders()

    // Your test code here - providers will now return mock data
    providers := config.Providers()
    // ... test logic
}
```

## Formatting

- ALWAYS format any Go code you write.
  - First, try `gofumpt -w .`.
  - If `gofumpt` is not available, use `goimports`.
  - If `goimports` is not available, use `gofmt`.
  - You can also use `task fmt` to run `gofumpt -w .` on the entire project,
    as long as `gofumpt` is on the `PATH`.

## Comments

- Comments that live on their own lines should start with capital letters and
  end with periods. Wrap comments at 78 columns.

## Committing

- ALWAYS use semantic commits (`fix:`, `feat:`, `chore:`, `refactor:`,
  `docs:`, `sec:`, etc).
- Try to keep commits to one line, not including your attribution. Only use
  multi-line commits when additional context is truly necessary.

## Working on the TUI (UI)

Anytime you need to work on the TUI, read `internal/ui/AGENTS.md` before
starting work.


================================================
FILE: CLA.md
================================================
# Contributor License Agreement

Thank you for your interest in the open source project(s) managed by Charmbracelet, Inc. ("Company"). In order to clarify the intellectual property license granted with Contributions from any person or entity, Company must have a Contributor License Agreement ("CLA") on file that has been signed by each contributor, indicating agreement to the license terms below. This license is for your protection as a contributor as well as the protection of Company and its other contributors and users; it does not change your rights to use your own Contributions for any other purpose.
By submitting a contribution to this repository (e.g. opening a pull request) or otherwise agreeing in writing, You accept and agree to these terms and conditions for Your present and future Contributions submitted to Company. In return, Company shall consider Your Contributions for addition to the official Company open source project(s) for which they were submitted. Except for the license granted herein to Company and recipients of software distributed by Company, You reserve all right, title, and interest in and to Your Contributions.

1. Definitions.
   - "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is entering into this CLA with Company. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
   - "Contribution" shall mean any code, documentation or other original works of authorship, including any modifications or additions to an existing work, that are intentionally submitted by You to Company for inclusion in, or documentation of, any of the products owned or managed by Company (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to Company or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Company for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
2. Grant of Copyright License. Subject to the terms and conditions of this CLA, You hereby grant to Company and to recipients of software distributed by Company a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
3. Grant of Patent License. Subject to the terms and conditions of this CLA, You hereby grant to Company and to recipients of software distributed by Company a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) were submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that Your Contribution, or the Work to which You have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this CLA for that Contribution or Work shall terminate as of the date such litigation is filed.
4. You represent and warrant that You are legally entitled to grant the above license. If You are an individual and Your employer(s) has rights to intellectual property that You create that includes Your Contributions, You represent that You have received permission to make Contributions on behalf of that employer, that Your employer has waived such rights for Your Contributions to Company, or that Your employer has entered into a separate CLA with Company covering Your Contributions. If You are a company, You represent further that each employee making a Contribution to Company under the company’s name is authorized to submit Contributions on behalf of the company.
5. You represent and warrant that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent and warrant that, to Your knowledge, none of Your Contributions infringe, violate, or misappropriate any third party intellectual property or other proprietary rights.
6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, except for the warranties set forth above, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
7. Should You wish to submit work that is not Your original creation, You may submit it to Company separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which You are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
8. You agree to notify Company of any facts or circumstances of which You become aware that would make the above representations and warranties inaccurate in any respect.
9. If You are entering into this CLA as a company, You represent and warrant that the individual accepting this CLA is duly authorized to enter into this CLA on the company’s behalf.

For any copyright notices or other communications, please contact us at [vt100@charm.land](mailto:vt100@charm.land).


================================================
FILE: LICENSE.md
================================================
# Functional Source License, Version 1.1, MIT Future License

## Abbreviation

FSL-1.1-MIT

## Notice

Copyright 2025-2026 Charmbracelet, Inc.

## Terms and Conditions

### Licensor ("We")

The party offering the Software under these Terms and Conditions.

### The Software

The "Software" is each version of the software that we make available under
these Terms and Conditions, as indicated by our inclusion of these Terms and
Conditions with the Software.

### License Grant

Subject to your compliance with this License Grant and the Patents,
Redistribution and Trademark clauses below, we hereby grant you the right to
use, copy, modify, create derivative works, publicly perform, publicly display
and redistribute the Software for any Permitted Purpose identified below.

### Permitted Purpose

A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
means making the Software available to others in a commercial product or
service that:

1. substitutes for the Software;

2. substitutes for any other product or service we offer using the Software
   that exists as of the date we make the Software available; or

3. offers the same or substantially similar functionality as the Software.

Permitted Purposes specifically include using the Software:

1. for your internal use and access;

2. for non-commercial education;

3. for non-commercial research; and

4. in connection with professional services that you provide to a licensee
   using the Software in accordance with these Terms and Conditions.

### Patents

To the extent your use for a Permitted Purpose would necessarily infringe our
patents, the license grant above includes a license under our patents. If you
make a claim against any party that the Software infringes or contributes to
the infringement of any patent, then your patent license to the Software ends
immediately.

### Redistribution

The Terms and Conditions apply to all copies, modifications and derivatives of
the Software.

If you redistribute any copies, modifications or derivatives of the Software,
you must include a copy of or a link to these Terms and Conditions and not
remove any copyright notices provided in or with the Software.

### Disclaimer

THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.

IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.

### Trademarks

Except for displaying the License Details and identifying us as the origin of
the Software, you have no right under these Terms and Conditions to use our
trademarks, trade names, service marks or product names.

## Grant of Future License

We hereby irrevocably grant you an additional license to use the Software under
the MIT license that is effective on the second anniversary of the date we make
the Software available. On or after that date, you may use the Software under
the MIT license, in which case the following will apply:

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

MIT License

Copyright (c) 2025-03-21 - 2025-05-30 Kujtim Hoxha

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Crush

<p align="center">
    <a href="https://stuff.charm.sh/crush/charm-crush.png"><img width="450" alt="Charm Crush Logo" src="https://github.com/user-attachments/assets/cf8ca3ce-8b02-43f0-9d0f-5a331488da4b" /></a><br />
    <a href="https://github.com/charmbracelet/crush/releases"><img src="https://img.shields.io/github/release/charmbracelet/crush" alt="Latest Release"></a>
    <a href="https://github.com/charmbracelet/crush/actions"><img src="https://github.com/charmbracelet/crush/actions/workflows/build.yml/badge.svg" alt="Build Status"></a>
</p>

<p align="center">Your new coding bestie, now available in your favourite terminal.<br />Your tools, your code, and your workflows, wired into your LLM of choice.</p>
<p align="center">终端里的编程新搭档,<br />无缝接入你的工具、代码与工作流,全面兼容主流 LLM 模型。</p>

<p align="center"><img width="800" alt="Crush Demo" src="https://github.com/user-attachments/assets/58280caf-851b-470a-b6f7-d5c4ea8a1968" /></p>

## Features

- **Multi-Model:** choose from a wide range of LLMs or add your own via OpenAI- or Anthropic-compatible APIs
- **Flexible:** switch LLMs mid-session while preserving context
- **Session-Based:** maintain multiple work sessions and contexts per project
- **LSP-Enhanced:** Crush uses LSPs for additional context, just like you do
- **Extensible:** add capabilities via MCPs (`http`, `stdio`, and `sse`)
- **Works Everywhere:** first-class support in every terminal on macOS, Linux, Windows (PowerShell and WSL), Android, FreeBSD, OpenBSD, and NetBSD
- **Industrial Grade:** built on the Charm ecosystem, powering 25k+ applications, from leading open source projects to business-critical infrastructure

## Installation

Use a package manager:

```bash
# Homebrew
brew install charmbracelet/tap/crush

# NPM
npm install -g @charmland/crush

# Arch Linux (btw)
yay -S crush-bin

# Nix
nix run github:numtide/nix-ai-tools#crush

# FreeBSD
pkg install crush
```

Windows users:

```bash
# Winget
winget install charmbracelet.crush

# Scoop
scoop bucket add charm https://github.com/charmbracelet/scoop-bucket.git
scoop install crush
```

<details>
<summary><strong>Nix (NUR)</strong></summary>

Crush is available via the official Charm [NUR](https://github.com/nix-community/NUR) in `nur.repos.charmbracelet.crush`, which is the most up-to-date way to get Crush in Nix.

You can also try out Crush via the NUR with `nix-shell`:

```bash
# Add the NUR channel.
nix-channel --add https://github.com/nix-community/NUR/archive/main.tar.gz nur
nix-channel --update

# Get Crush in a Nix shell.
nix-shell -p '(import <nur> { pkgs = import <nixpkgs> {}; }).repos.charmbracelet.crush'
```

### NixOS & Home Manager Module Usage via NUR

Crush provides NixOS and Home Manager modules via NUR.
You can use these modules directly in your flake by importing them from NUR. Since it auto detects whether its a home manager or nixos context you can use the import the exact same way :)

```nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nur.url = "github:nix-community/NUR";
  };

  outputs = { self, nixpkgs, nur, ... }: {
    nixosConfigurations.your-hostname = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        nur.modules.nixos.default
        nur.repos.charmbracelet.modules.crush
        {
          programs.crush = {
            enable = true;
            settings = {
              providers = {
                openai = {
                  id = "openai";
                  name = "OpenAI";
                  base_url = "https://api.openai.com/v1";
                  type = "openai";
                  api_key = "sk-fake123456789abcdef...";
                  models = [
                    {
                      id = "gpt-4";
                      name = "GPT-4";
                    }
                  ];
                };
              };
              lsp = {
                go = { command = "gopls"; enabled = true; };
                nix = { command = "nil"; enabled = true; };
              };
              options = {
                context_paths = [ "/etc/nixos/configuration.nix" ];
                tui = { compact_mode = true; };
                debug = false;
              };
            };
          };
        }
      ];
    };
  };
}
```

</details>

<details>
<summary><strong>Debian/Ubuntu</strong></summary>

```bash
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg
echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list
sudo apt update && sudo apt install crush
```

</details>

<details>
<summary><strong>Fedora/RHEL</strong></summary>

```bash
echo '[charm]
name=Charm
baseurl=https://repo.charm.sh/yum/
enabled=1
gpgcheck=1
gpgkey=https://repo.charm.sh/yum/gpg.key' | sudo tee /etc/yum.repos.d/charm.repo
sudo yum install crush
```

</details>

Or, download it:

- [Packages][releases] are available in Debian and RPM formats
- [Binaries][releases] are available for Linux, macOS, Windows, FreeBSD, OpenBSD, and NetBSD

[releases]: https://github.com/charmbracelet/crush/releases

Or just install it with Go:

```
go install github.com/charmbracelet/crush@latest
```

> [!WARNING]
> Productivity may increase when using Crush and you may find yourself nerd
> sniped when first using the application. If the symptoms persist, join the
> [Discord][discord] and nerd snipe the rest of us.

## Getting Started

The quickest way to get started is to grab an API key for your preferred
provider such as Anthropic, OpenAI, Groq, OpenRouter, or Vercel AI Gateway and just start
Crush. You'll be prompted to enter your API key.

That said, you can also set environment variables for preferred providers.

| Environment Variable        | Provider                                           |
| --------------------------- | -------------------------------------------------- |
| `ANTHROPIC_API_KEY`         | Anthropic                                          |
| `OPENAI_API_KEY`            | OpenAI                                             |
| `VERCEL_API_KEY`            | Vercel AI Gateway                                  |
| `GEMINI_API_KEY`            | Google Gemini                                      |
| `SYNTHETIC_API_KEY`         | Synthetic                                          |
| `ZAI_API_KEY`               | Z.ai                                               |
| `MINIMAX_API_KEY`           | MiniMax                                            |
| `HF_TOKEN`                  | Hugging Face Inference                             |
| `CEREBRAS_API_KEY`          | Cerebras                                           |
| `OPENROUTER_API_KEY`        | OpenRouter                                         |
| `IONET_API_KEY`             | io.net                                             |
| `GROQ_API_KEY`              | Groq                                               |
| `VERTEXAI_PROJECT`          | Google Cloud VertexAI (Gemini)                     |
| `VERTEXAI_LOCATION`         | Google Cloud VertexAI (Gemini)                     |
| `AWS_ACCESS_KEY_ID`         | Amazon Bedrock (Claude)                            |
| `AWS_SECRET_ACCESS_KEY`     | Amazon Bedrock (Claude)                            |
| `AWS_REGION`                | Amazon Bedrock (Claude)                            |
| `AWS_PROFILE`               | Amazon Bedrock (Custom Profile)                    |
| `AWS_BEARER_TOKEN_BEDROCK`  | Amazon Bedrock                                     |
| `AZURE_OPENAI_API_ENDPOINT` | Azure OpenAI models                                |
| `AZURE_OPENAI_API_KEY`      | Azure OpenAI models (optional when using Entra ID) |
| `AZURE_OPENAI_API_VERSION`  | Azure OpenAI models                                |

### Subscriptions

If you prefer subscription-based usage, here are some plans that work well in
Crush:

- [Synthetic](https://synthetic.new/pricing)
- [GLM Coding Plan](https://z.ai/subscribe)
- [Kimi Code](https://www.kimi.com/membership/pricing)
- [MiniMax Coding Plan](https://platform.minimax.io/subscribe/coding-plan)

### By the Way

Is there a provider you’d like to see in Crush? Is there an existing model that needs an update?

Crush’s default model listing is managed in [Catwalk](https://github.com/charmbracelet/catwalk), a community-supported, open source repository of Crush-compatible models, and you’re welcome to contribute.

<a href="https://github.com/charmbracelet/catwalk"><img width="174" height="174" alt="Catwalk Badge" src="https://github.com/user-attachments/assets/95b49515-fe82-4409-b10d-5beb0873787d" /></a>

## Configuration

Crush runs great with no configuration. That said, if you do need or want to
customize Crush, configuration can be added either local to the project itself,
or globally, with the following priority:

1. `.crush.json`
2. `crush.json`
3. `$HOME/.config/crush/crush.json`

Configuration itself is stored as a JSON object:

```json
{
  "this-setting": { "this": "that" },
  "that-setting": ["ceci", "cela"]
}
```

As an additional note, Crush also stores ephemeral data, such as application state, in one additional location:

```bash
# Unix
$HOME/.local/share/crush/crush.json

# Windows
%LOCALAPPDATA%\crush\crush.json
```

> [!TIP]
> You can override the user and data config locations by setting:
> * `CRUSH_GLOBAL_CONFIG`
> * `CRUSH_GLOBAL_DATA`

### LSPs

Crush can use LSPs for additional context to help inform its decisions, just
like you would. LSPs can be added manually like so:

```json
{
  "$schema": "https://charm.land/crush.json",
  "lsp": {
    "go": {
      "command": "gopls",
      "env": {
        "GOTOOLCHAIN": "go1.24.5"
      }
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    },
    "nix": {
      "command": "nil"
    }
  }
}
```

### MCPs

Crush also supports Model Context Protocol (MCP) servers through three
transport types: `stdio` for command-line servers, `http` for HTTP endpoints,
and `sse` for Server-Sent Events. Environment variable expansion is supported
using `$(echo $VAR)` syntax.

```json
{
  "$schema": "https://charm.land/crush.json",
  "mcp": {
    "filesystem": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/mcp-server.js"],
      "timeout": 120,
      "disabled": false,
      "disabled_tools": ["some-tool-name"],
      "env": {
        "NODE_ENV": "production"
      }
    },
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "timeout": 120,
      "disabled": false,
      "disabled_tools": ["create_issue", "create_pull_request"],
      "headers": {
        "Authorization": "Bearer $GH_PAT"
      }
    },
    "streaming-service": {
      "type": "sse",
      "url": "https://example.com/mcp/sse",
      "timeout": 120,
      "disabled": false,
      "headers": {
        "API-Key": "$(echo $API_KEY)"
      }
    }
  }
}
```

### Ignoring Files

Crush respects `.gitignore` files by default, but you can also create a
`.crushignore` file to specify additional files and directories that Crush
should ignore. This is useful for excluding files that you want in version
control but don't want Crush to consider when providing context.

The `.crushignore` file uses the same syntax as `.gitignore` and can be placed
in the root of your project or in subdirectories.

### Allowing Tools

By default, Crush will ask you for permission before running tool calls. If
you'd like, you can allow tools to be executed without prompting you for
permissions. Use this with care.

```json
{
  "$schema": "https://charm.land/crush.json",
  "permissions": {
    "allowed_tools": [
      "view",
      "ls",
      "grep",
      "edit",
      "mcp_context7_get-library-doc"
    ]
  }
}
```

You can also skip all permission prompts entirely by running Crush with the
`--yolo` flag. Be very, very careful with this feature.

### Disabling Built-In Tools

If you'd like to prevent Crush from using certain built-in tools entirely, you
can disable them via the `options.disabled_tools` list. Disabled tools are
completely hidden from the agent.

```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disabled_tools": [
      "bash",
      "sourcegraph"
    ]
  }
}
```

To disable tools from MCP servers, see the [MCP config section](#mcps).

### Agent Skills

Crush supports the [Agent Skills](https://agentskills.io) open standard for
extending agent capabilities with reusable skill packages. Skills are folders
containing a `SKILL.md` file with instructions that Crush can discover and
activate on demand.

Skills are discovered from:

- `~/.config/crush/skills/` on Unix (default, can be overridden with `CRUSH_SKILLS_DIR`)
- `%LOCALAPPDATA%\crush\skills\` on Windows (default, can be overridden with `CRUSH_SKILLS_DIR`)
- Additional paths configured via `options.skills_paths`

```jsonc
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "skills_paths": [
      "~/.config/crush/skills", // Windows: "%LOCALAPPDATA%\\crush\\skills",
      "./project-skills"
    ]
  }
}
```

You can get started with example skills from [anthropics/skills](https://github.com/anthropics/skills):

```bash
# Unix
mkdir -p ~/.config/crush/skills
cd ~/.config/crush/skills
git clone https://github.com/anthropics/skills.git _temp
mv _temp/skills/* . && rm -rf _temp
```

```powershell
# Windows (PowerShell)
mkdir -Force "$env:LOCALAPPDATA\crush\skills"
cd "$env:LOCALAPPDATA\crush\skills"
git clone https://github.com/anthropics/skills.git _temp
mv _temp/skills/* . ; rm -r -force _temp
```

### Desktop notifications

Crush sends desktop notifications when a tool call requires permission and when
the agent finishes its turn. They're only sent when the terminal window isn't
focused _and_ your terminal supports reporting the focus state.

```jsonc
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disable_notifications": false // default
  }
}
```

To disable desktop notifications, set `disable_notifications` to `true` in your
configuration. On macOS, notifications currently lack icons due to platform
limitations.

### Initialization

When you initialize a project, Crush analyzes your codebase and creates
a context file that helps it work more effectively in future sessions.
By default, this file is named `AGENTS.md`, but you can customize the
name and location with the `initialize_as` option:

```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "initialize_as": "AGENTS.md"
  }
}
```

This is useful if you prefer a different naming convention or want to
place the file in a specific directory (e.g., `CRUSH.md` or
`docs/LLMs.md`). Crush will fill the file with project-specific context
like build commands, code patterns, and conventions it discovered during
initialization.

### Attribution Settings

By default, Crush adds attribution information to Git commits and pull requests
it creates. You can customize this behavior with the `attribution` option:

```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "attribution": {
      "trailer_style": "co-authored-by",
      "generated_with": true
    }
  }
}
```

- `trailer_style`: Controls the attribution trailer added to commit messages
  (default: `assisted-by`)
	- `assisted-by`: Adds `Assisted-by: [Model Name] via Crush <crush@charm.land>`
	  (includes the model name)
	- `co-authored-by`: Adds `Co-Authored-By: Crush <crush@charm.land>`
	- `none`: No attribution trailer
- `generated_with`: When true (default), adds `💘 Generated with Crush` line to
  commit messages and PR descriptions

### Custom Providers

Crush supports custom provider configurations for both OpenAI-compatible and
Anthropic-compatible APIs.

> [!NOTE]
> Note that we support two "types" for OpenAI. Make sure to choose the right one
> to ensure the best experience!
> * `openai` should be used when proxying or routing requests through OpenAI.
> * `openai-compat` should be used when using non-OpenAI providers that have OpenAI-compatible APIs.

#### OpenAI-Compatible APIs

Here’s an example configuration for Deepseek, which uses an OpenAI-compatible
API. Don't forget to set `DEEPSEEK_API_KEY` in your environment.

```json
{
  "$schema": "https://charm.land/crush.json",
  "providers": {
    "deepseek": {
      "type": "openai-compat",
      "base_url": "https://api.deepseek.com/v1",
      "api_key": "$DEEPSEEK_API_KEY",
      "models": [
        {
          "id": "deepseek-chat",
          "name": "Deepseek V3",
          "cost_per_1m_in": 0.27,
          "cost_per_1m_out": 1.1,
          "cost_per_1m_in_cached": 0.07,
          "cost_per_1m_out_cached": 1.1,
          "context_window": 64000,
          "default_max_tokens": 5000
        }
      ]
    }
  }
}
```

#### Anthropic-Compatible APIs

Custom Anthropic-compatible providers follow this format:

```json
{
  "$schema": "https://charm.land/crush.json",
  "providers": {
    "custom-anthropic": {
      "type": "anthropic",
      "base_url": "https://api.anthropic.com/v1",
      "api_key": "$ANTHROPIC_API_KEY",
      "extra_headers": {
        "anthropic-version": "2023-06-01"
      },
      "models": [
        {
          "id": "claude-sonnet-4-20250514",
          "name": "Claude Sonnet 4",
          "cost_per_1m_in": 3,
          "cost_per_1m_out": 15,
          "cost_per_1m_in_cached": 3.75,
          "cost_per_1m_out_cached": 0.3,
          "context_window": 200000,
          "default_max_tokens": 50000,
          "can_reason": true,
          "supports_attachments": true
        }
      ]
    }
  }
}
```

### Amazon Bedrock

Crush currently supports running Anthropic models through Bedrock, with caching disabled.

- A Bedrock provider will appear once you have AWS configured, i.e. `aws configure`
- Crush also expects the `AWS_REGION` or `AWS_DEFAULT_REGION` to be set
- To use a specific AWS profile set `AWS_PROFILE` in your environment, i.e. `AWS_PROFILE=myprofile crush`
- Alternatively to `aws configure`, you can also just set `AWS_BEARER_TOKEN_BEDROCK`

### Vertex AI Platform

Vertex AI will appear in the list of available providers when `VERTEXAI_PROJECT` and `VERTEXAI_LOCATION` are set. You will also need to be authenticated:

```bash
gcloud auth application-default login
```

To add specific models to the configuration, configure as such:

```json
{
  "$schema": "https://charm.land/crush.json",
  "providers": {
    "vertexai": {
      "models": [
        {
          "id": "claude-sonnet-4@20250514",
          "name": "VertexAI Sonnet 4",
          "cost_per_1m_in": 3,
          "cost_per_1m_out": 15,
          "cost_per_1m_in_cached": 3.75,
          "cost_per_1m_out_cached": 0.3,
          "context_window": 200000,
          "default_max_tokens": 50000,
          "can_reason": true,
          "supports_attachments": true
        }
      ]
    }
  }
}
```

### Local Models

Local models can also be configured via OpenAI-compatible API. Here are two common examples:

#### Ollama

```json
{
  "providers": {
    "ollama": {
      "name": "Ollama",
      "base_url": "http://localhost:11434/v1/",
      "type": "openai-compat",
      "models": [
        {
          "name": "Qwen 3 30B",
          "id": "qwen3:30b",
          "context_window": 256000,
          "default_max_tokens": 20000
        }
      ]
    }
  }
}
```

#### LM Studio

```json
{
  "providers": {
    "lmstudio": {
      "name": "LM Studio",
      "base_url": "http://localhost:1234/v1/",
      "type": "openai-compat",
      "models": [
        {
          "name": "Qwen 3 30B",
          "id": "qwen/qwen3-30b-a3b-2507",
          "context_window": 256000,
          "default_max_tokens": 20000
        }
      ]
    }
  }
}
```

## Logging

Sometimes you need to look at logs. Luckily, Crush logs all sorts of
stuff. Logs are stored in `./.crush/logs/crush.log` relative to the project.

The CLI also contains some helper commands to make perusing recent logs easier:

```bash
# Print the last 1000 lines
crush logs

# Print the last 500 lines
crush logs --tail 500

# Follow logs in real time
crush logs --follow
```

Want more logging? Run `crush` with the `--debug` flag, or enable it in the
config:

```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "debug": true,
    "debug_lsp": true
  }
}
```

## Provider Auto-Updates

By default, Crush automatically checks for the latest and greatest list of
providers and models from [Catwalk](https://github.com/charmbracelet/catwalk),
the open source Crush provider database. This means that when new providers and
models are available, or when model metadata changes, Crush automatically
updates your local configuration.

### Disabling automatic provider updates

For those with restricted internet access, or those who prefer to work in
air-gapped environments, this might not be want you want, and this feature can
be disabled.

To disable automatic provider updates, set `disable_provider_auto_update` into
your `crush.json` config:

```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "disable_provider_auto_update": true
  }
}
```

Or set the `CRUSH_DISABLE_PROVIDER_AUTO_UPDATE` environment variable:

```bash
export CRUSH_DISABLE_PROVIDER_AUTO_UPDATE=1
```

### Manually updating providers

Manually updating providers is possible with the `crush update-providers`
command:

```bash
# Update providers remotely from Catwalk.
crush update-providers

# Update providers from a custom Catwalk base URL.
crush update-providers https://example.com/

# Update providers from a local file.
crush update-providers /path/to/local-providers.json

# Reset providers to the embedded version, embedded at crush at build time.
crush update-providers embedded

# For more info:
crush update-providers --help
```

## Metrics

Crush records pseudonymous usage metrics (tied to a device-specific hash),
which maintainers rely on to inform development and support priorities. The
metrics include solely usage metadata; prompts and responses are NEVER
collected.

Details on exactly what’s collected are in the source code ([here](https://github.com/charmbracelet/crush/tree/main/internal/event)
and [here](https://github.com/charmbracelet/crush/blob/main/internal/llm/agent/event.go)).

You can opt out of metrics collection at any time by setting the environment
variable by setting the following in your environment:

```bash
export CRUSH_DISABLE_METRICS=1
```

Or by setting the following in your config:

```json
{
  "options": {
    "disable_metrics": true
  }
}
```

Crush also respects the `DO_NOT_TRACK` convention which can be enabled via
`export DO_NOT_TRACK=1`.

## Contributing

See the [contributing guide](https://github.com/charmbracelet/crush?tab=contributing-ov-file#contributing).

## Whatcha think?

We’d love to hear your thoughts on this project. Need help? We gotchu. You can find us on:

- [Twitter](https://twitter.com/charmcli)
- [Slack](https://charm.land/slack)
- [Discord][discord]
- [The Fediverse](https://mastodon.social/@charmcli)
- [Bluesky](https://bsky.app/profile/charm.land)

[discord]: https://charm.land/discord

## License

[FSL-1.1-MIT](https://github.com/charmbracelet/crush/raw/main/LICENSE.md)

---

Part of [Charm](https://charm.land).

<a href="https://charm.land/"><img alt="The Charm logo" width="400" src="https://stuff.charm.sh/charm-banner-next.jpg" /></a>

<!--prettier-ignore-->
Charm热爱开源 • Charm loves open source


================================================
FILE: Taskfile.yaml
================================================
# https://taskfile.dev

version: "3"

vars:
  VERSION:
    sh: git describe --long 2>/dev/null || echo ""
  RACE:
    sh: test -f race.log && echo "1" || echo ""

env:
  CGO_ENABLED: 0
  GOEXPERIMENT: greenteagc

tasks:
  lint:install:
    desc: Install golangci-lint
    cmds:
      - go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
    env:
      GOTOOLCHAIN: go1.25.0

  lint:
    desc: Run base linters
    cmds:
      - task: lint:log
      - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m
    env:
      GOEXPERIMENT: null

  lint:log:
    desc: Check that log messages start with capital letters
    cmds:
      - ./scripts/check_log_capitalization.sh

  lint:fix:
    desc: Run base linters and fix issues
    cmds:
      - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m --fix
    env:
      GOEXPERIMENT: null

  build:
    desc: Run build
    vars:
      LDFLAGS: '{{if .VERSION}}-ldflags="-X github.com/charmbracelet/crush/internal/version.Version={{.VERSION}}"{{end}}'
    cmds:
      - "go build -v {{if .RACE}}-race{{end}} {{.LDFLAGS}} ."
    sources:
      - ./**/*.go
      - go.mod
    generates:
      - crush{{exeExt}}

  run:
    desc: Run build
    cmds:
      - task: build
      - "./crush{{exeExt}} {{.CLI_ARGS}} {{if .RACE}}2>race.log{{end}}"

  run:catwalk:
    desc: Run build with local Catwalk
    env:
      CATWALK_URL: http://localhost:8080
    cmds:
      - task: build
      - ./crush{{exeExt}} {{.CLI_ARGS}}

  run:onboarding:
    desc: Run build with custom config to test onboarding
    env:
      CRUSH_GLOBAL_DATA: tmp/onboarding/data
      CRUSH_GLOBAL_CONFIG: tmp/onboarding/config
    cmds:
      - task: build
      - rm -rf tmp/onboarding
      - ./crush{exeExt} {{.CLI_ARGS}}

  test:
    desc: Run tests
    cmds:
      - go test -race -failfast ./... {{.CLI_ARGS}}

  test:record:
    desc: Run tests and record all VCR cassettes again
    aliases: [record]
    cmds:
      - rm -r internal/agent/testdata
      - go test -v -count=1 -timeout=1h ./internal/agent

  fmt:
    desc: Run gofumpt
    cmds:
      - gofumpt -w .

  fmt:html:
    desc: Run prettier on HTML/CSS/JS files
    cmds:
      - prettier --write internal/cmd/stats/index.html internal/cmd/stats/index.css internal/cmd/stats/index.js

  modernize:
    desc: Run modernize
    cmds:
      - go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix -test ./...

  dev:
    desc: Run with profiling enabled
    env:
      CRUSH_PROFILE: true
    cmds:
      - go run .

  install:
    desc: Install the application
    vars:
      LDFLAGS: '{{if .VERSION}}-ldflags="-X github.com/charmbracelet/crush/internal/version.Version={{.VERSION}}"{{end}}'
    cmds:
      - task: fetch-tags
      - go install {{.LDFLAGS}} -v .
    sources:
      - ./**/*.go
      - go.mod

  profile:cpu:
    desc: 10s CPU profile
    cmds:
      - go tool pprof -http :6061 'http://localhost:6060/debug/pprof/profile?seconds=10'

  profile:heap:
    desc: Heap profile
    cmds:
      - go tool pprof -http :6061 'http://localhost:6060/debug/pprof/heap'

  profile:allocs:
    desc: Allocations profile
    cmds:
      - go tool pprof -http :6061 'http://localhost:6060/debug/pprof/allocs'

  schema:
    desc: Generate JSON schema for configuration
    cmds:
      - go run main.go schema > schema.json
      - echo "Generated schema.json"
    generates:
      - schema.json

  hyper:
    desc: Update Hyper embedded provider.json
    cmds:
      - go generate ./internal/agent/hyper/...
    generates:
      - ./internal/agent/hyper/provider.json

  release:
    desc: Create and push a new tag following semver
    vars:
      NEXT:
        sh: svu next --always || go run github.com/caarlos0/svu/v3@latest next --always
    prompt: "This will release {{.NEXT}}. Continue?"
    preconditions:
      - sh: '[ $(git symbolic-ref --short HEAD) = "main" ]'
        msg: Not on main branch
      - sh: "[ $(git status --porcelain=2 | wc -l) = 0 ]"
        msg: "Git is dirty"
      - sh: 'gh run list --workflow build.yml --commit $(git rev-parse HEAD) --status success --json conclusion -q ".[0].conclusion" | grep -q success'
        msg: "Test build for this commit failed or not present"
      - sh: 'gh run list --workflow snapshot.yml --commit $(git rev-parse HEAD) --status success --json conclusion -q ".[0].conclusion" | grep -q success'
        msg: "Snapshot build for this commit failed or not present"
    cmds:
      - task: fetch-tags
      - git commit --allow-empty -m "{{.NEXT}}"
      - git tag --annotate --sign -m "{{.NEXT}}" {{.NEXT}} {{.CLI_ARGS}}
      - echo "Pushing {{.NEXT}}..."
      - git push origin main --follow-tags

  fetch-tags:
    cmds:
      - git tag -d nightly || true
      - git fetch --tags

  deps:
    desc: Update Fantasy and Catwalk
    env:
      # The Go proxy takes a bit of time to see the latest release. Setting
      # these bypass it to ensure we can update to a release from a minute ago.
      GOPROXY: direct
      GONOSUMDB: charm.land/*
    cmds:
      - go get charm.land/fantasy@latest
      - go get charm.land/catwalk@latest
      - go mod tidy

  sqlc:
    desc: Generate code using SQLC
    cmds:
      - sqlc generate


================================================
FILE: crush.json
================================================
{
  "$schema": "https://charm.land/crush.json",
  "lsp": {
    "gopls": {
      "options": {
        "gofumpt": true,
        "codelenses": {
          "gc_details": true,
          "generate": true,
          "run_govulncheck": true,
          "test": true,
          "tidy": true,
          "upgrade_dependency": true
        },
        "hints": {
          "assignVariableTypes": true,
          "compositeLiteralFields": true,
          "compositeLiteralTypes": true,
          "constantValues": true,
          "functionTypeParameters": true,
          "parameterNames": true,
          "rangeVariableTypes": true
        },
        "analyses": {
          "nilness": true,
          "unusedparams": true,
          "unusedvariable": true,
          "unusedwrite": true,
          "useany": true
        },
        "staticcheck": true,
        "directoryFilters": [
          "-.git",
          "-node_modules"
        ],
        "semanticTokens": true
      }
    }
  }
}


================================================
FILE: go.mod
================================================
module github.com/charmbracelet/crush

go 1.26.1

require (
	charm.land/bubbles/v2 v2.0.0
	charm.land/bubbletea/v2 v2.0.2
	charm.land/catwalk v0.30.8
	charm.land/fang/v2 v2.0.1
	charm.land/fantasy v0.15.1
	charm.land/glamour/v2 v2.0.0
	charm.land/lipgloss/v2 v2.0.2
	charm.land/log/v2 v2.0.0
	charm.land/x/vcr v0.1.1
	github.com/JohannesKaufmann/html-to-markdown v1.6.0
	github.com/MakeNowJust/heredoc v1.0.0
	github.com/PuerkitoBio/goquery v1.12.0
	github.com/alecthomas/chroma/v2 v2.23.1
	github.com/atotto/clipboard v0.1.4
	github.com/aymanbagabas/go-nativeclipboard v0.1.3
	github.com/aymanbagabas/go-udiff v0.4.1
	github.com/bmatcuk/doublestar/v4 v4.10.0
	github.com/charlievieth/fastwalk v1.0.14
	github.com/charmbracelet/colorprofile v0.4.3
	github.com/charmbracelet/openai-go v0.0.0-20260319145158-d0740cc34266
	github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8
	github.com/charmbracelet/x/ansi v0.11.6
	github.com/charmbracelet/x/editor v0.2.0
	github.com/charmbracelet/x/etag v0.2.0
	github.com/charmbracelet/x/exp/charmtone v0.0.0-20260109001716-2fbdffcb221f
	github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f
	github.com/charmbracelet/x/exp/ordered v0.1.0
	github.com/charmbracelet/x/exp/slice v0.0.0-20260209194814-eeb2896ac759
	github.com/charmbracelet/x/exp/strings v0.1.0
	github.com/charmbracelet/x/powernap v0.1.3
	github.com/charmbracelet/x/term v0.2.2
	github.com/clipperhouse/displaywidth v0.11.0
	github.com/clipperhouse/uax29/v2 v2.7.0
	github.com/denisbrodbeck/machineid v1.0.1
	github.com/disintegration/imaging v1.6.2
	github.com/dustin/go-humanize v1.0.1
	github.com/gen2brain/beeep v0.11.2
	github.com/go-git/go-git/v5 v5.17.0
	github.com/google/uuid v1.6.0
	github.com/invopop/jsonschema v0.13.0
	github.com/joho/godotenv v1.5.1
	github.com/jordanella/go-ansi-paintbrush v0.0.0-20240728195301-b7ad996ecf3d
	github.com/lucasb-eyer/go-colorful v1.3.0
	github.com/mattn/go-isatty v0.0.20
	github.com/modelcontextprotocol/go-sdk v1.4.1
	github.com/ncruces/go-sqlite3 v0.32.0
	github.com/nxadm/tail v1.4.11
	github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
	github.com/posthog/posthog-go v1.11.1
	github.com/pressly/goose/v3 v3.27.0
	github.com/qjebbs/go-jsons v1.0.0-alpha.4
	github.com/rivo/uniseg v0.4.7
	github.com/sahilm/fuzzy v0.1.1
	github.com/sourcegraph/jsonrpc2 v0.2.1
	github.com/spf13/cobra v1.10.2
	github.com/stretchr/testify v1.11.1
	github.com/tidwall/gjson v1.18.0
	github.com/tidwall/sjson v1.2.5
	github.com/zeebo/xxh3 v1.1.0
	go.uber.org/goleak v1.3.0
	golang.org/x/net v0.52.0
	golang.org/x/sync v0.20.0
	golang.org/x/text v0.35.0
	gopkg.in/natefinch/lumberjack.v2 v2.2.1
	gopkg.in/yaml.v3 v3.0.1
	modernc.org/sqlite v1.46.1
	mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5
	mvdan.cc/sh/v3 v3.13.0
)

require (
	cloud.google.com/go v0.123.0 // indirect
	cloud.google.com/go/auth v0.18.2 // indirect
	cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
	cloud.google.com/go/compute/metadata v0.9.0 // indirect
	git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect
	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
	github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
	github.com/andybalholm/cascadia v1.3.3 // indirect
	github.com/aws/aws-sdk-go-v2 v1.41.4 // indirect
	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6 // indirect
	github.com/aws/aws-sdk-go-v2/config v1.32.12 // indirect
	github.com/aws/aws-sdk-go-v2/credentials v1.19.12 // indirect
	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect
	github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect
	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect
	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect
	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect
	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 // indirect
	github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect
	github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect
	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect
	github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect
	github.com/aws/smithy-go v1.24.2 // indirect
	github.com/aymerick/douceur v0.2.0 // indirect
	github.com/bahlo/generic-list-go v0.2.0 // indirect
	github.com/buger/jsonparser v1.1.1 // indirect
	github.com/cespare/xxhash/v2 v2.3.0 // indirect
	github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab // indirect
	github.com/charmbracelet/x/json v0.2.0 // indirect
	github.com/charmbracelet/x/termios v0.1.1 // indirect
	github.com/charmbracelet/x/windows v0.2.2 // indirect
	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
	github.com/dlclark/regexp2 v1.11.5 // indirect
	github.com/ebitengine/purego v0.10.0 // indirect
	github.com/esiqveland/notify v0.13.3 // indirect
	github.com/felixge/httpsnoop v1.0.4 // indirect
	github.com/fsnotify/fsnotify v1.9.0 // indirect
	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
	github.com/go-git/go-billy/v5 v5.8.0 // indirect
	github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
	github.com/go-logfmt/logfmt v0.6.0 // indirect
	github.com/go-logr/logr v1.4.3 // indirect
	github.com/go-logr/stdr v1.2.2 // indirect
	github.com/go-ole/go-ole v1.3.0 // indirect
	github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
	github.com/goccy/go-json v0.10.5 // indirect
	github.com/goccy/go-yaml v1.19.2 // indirect
	github.com/godbus/dbus/v5 v5.2.2 // indirect
	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
	github.com/google/go-cmp v0.7.0 // indirect
	github.com/google/jsonschema-go v0.4.2 // indirect
	github.com/google/s2a-go v0.1.9 // indirect
	github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
	github.com/googleapis/gax-go/v2 v2.17.0 // indirect
	github.com/gorilla/css v1.0.1 // indirect
	github.com/gorilla/websocket v1.5.3 // indirect
	github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
	github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
	github.com/kaptinlin/go-i18n v0.2.12 // indirect
	github.com/kaptinlin/jsonpointer v0.4.17 // indirect
	github.com/kaptinlin/jsonschema v0.7.5 // indirect
	github.com/kaptinlin/messageformat-go v0.4.18 // indirect
	github.com/klauspost/compress v1.18.4 // indirect
	github.com/klauspost/cpuid/v2 v2.2.10 // indirect
	github.com/klauspost/pgzip v1.2.6 // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/mattn/go-runewidth v0.0.20 // indirect
	github.com/mfridman/interpolate v0.0.2 // indirect
	github.com/microcosm-cc/bluemonday v1.0.27 // indirect
	github.com/mitchellh/mapstructure v1.5.0 // indirect
	github.com/muesli/cancelreader v0.2.2 // indirect
	github.com/muesli/mango v0.1.0 // indirect
	github.com/muesli/mango-cobra v1.2.0 // indirect
	github.com/muesli/mango-pflag v0.1.0 // indirect
	github.com/muesli/roff v0.1.0 // indirect
	github.com/ncruces/go-strftime v1.0.0 // indirect
	github.com/ncruces/julianday v1.0.0 // indirect
	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
	github.com/pierrec/lz4/v4 v4.1.25 // indirect
	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
	github.com/segmentio/asm v1.2.1 // indirect
	github.com/segmentio/encoding v0.5.4 // indirect
	github.com/sergeymakinen/go-bmp v1.0.0 // indirect
	github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect
	github.com/sethvargo/go-retry v0.3.0 // indirect
	github.com/spf13/pflag v1.0.9 // indirect
	github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
	github.com/tetratelabs/wazero v1.11.0 // indirect
	github.com/tidwall/match v1.1.1 // indirect
	github.com/tidwall/pretty v1.2.1 // indirect
	github.com/u-root/u-root v0.14.1-0.20250807200646-5e7721023dc7 // indirect
	github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
	github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
	github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
	github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
	github.com/yuin/goldmark v1.7.8 // indirect
	github.com/yuin/goldmark-emoji v1.0.5 // indirect
	go.opentelemetry.io/auto/sdk v1.2.1 // indirect
	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect
	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
	go.opentelemetry.io/otel v1.42.0 // indirect
	go.opentelemetry.io/otel/metric v1.42.0 // indirect
	go.opentelemetry.io/otel/trace v1.42.0 // indirect
	go.uber.org/multierr v1.11.0 // indirect
	go.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect
	golang.org/x/crypto v0.49.0 // indirect
	golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
	golang.org/x/image v0.36.0 // indirect
	golang.org/x/oauth2 v0.36.0 // indirect
	golang.org/x/sys v0.42.0 // indirect
	golang.org/x/term v0.41.0 // indirect
	golang.org/x/time v0.15.0 // indirect
	google.golang.org/api v0.270.0 // indirect
	google.golang.org/genai v1.50.0 // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
	google.golang.org/grpc v1.79.2 // indirect
	google.golang.org/protobuf v1.36.11 // indirect
	gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290 // indirect
	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
	gopkg.in/warnings.v0 v0.1.2 // indirect
	modernc.org/libc v1.68.0 // indirect
	modernc.org/mathutil v1.7.1 // indirect
	modernc.org/memory v1.11.0 // indirect
)


================================================
FILE: go.sum
================================================
charm.land/bubbles/v2 v2.0.0 h1:tE3eK/pHjmtrDiRdoC9uGNLgpopOd8fjhEe31B/ai5s=
charm.land/bubbles/v2 v2.0.0/go.mod h1:rCHoleP2XhU8um45NTuOWBPNVHxnkXKTiZqcclL/qOI=
charm.land/bubbletea/v2 v2.0.2 h1:4CRtRnuZOdFDTWSff9r8QFt/9+z6Emubz3aDMnf/dx0=
charm.land/bubbletea/v2 v2.0.2/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ=
charm.land/catwalk v0.30.8 h1:Y5FYPY8iHoejXKxyp2Akbn+3SBb0zocY7aetjHxGs70=
charm.land/catwalk v0.30.8/go.mod h1:+fqw/6YGNtvapvPy9vhwA/fAMxVjD2K8hVIKYov8Vhg=
charm.land/fang/v2 v2.0.1 h1:zQCM8JQJ1JnQX/66B5jlCYBUxL2as5JXQZ2KJ6EL0mY=
charm.land/fang/v2 v2.0.1/go.mod h1:S1GmkpcvK+OB5w9caywUnJcsMew45Ot8FXqoz8ALrII=
charm.land/fantasy v0.15.1 h1:eojrAXd2hvq5vuLO5Rcobv5P/xgen0YAngDquUawFvo=
charm.land/fantasy v0.15.1/go.mod h1:VZjpXVh7IgeiIzGQybEnKzd68ofDsRj94+kzH1ZCAfQ=
charm.land/glamour/v2 v2.0.0 h1:IDBoqLEy7Hdpb9VOXN+khLP/XSxtJy1VsHuW/yF87+U=
charm.land/glamour/v2 v2.0.0/go.mod h1:kjq9WB0s8vuUYZNYey2jp4Lgd9f4cKdzAw88FZtpj/w=
charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs=
charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM=
charm.land/log/v2 v2.0.0 h1:SY3Cey7ipx86/MBXQHwsguOT6X1exT94mmJRdzTNs+s=
charm.land/log/v2 v2.0.0/go.mod h1:c3cZSRqm20qUVVAR1WmS/7ab8bgha3C6G7DjPcaVZz0=
charm.land/x/vcr v0.1.1 h1:PXCFMUG0rPtyk35rhfzYCJEduOzWXCIbrXTFq4OF/9Q=
charm.land/x/vcr v0.1.1/go.mod h1:eByq2gqzWvcct/8XE2XO5KznoWEBiXH56+y2gphbltM=
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
git.sr.ht/~jackmordaunt/go-toast v1.1.2 h1:/yrfI55LRt1M7H1vkaw+NaH1+L1CDxrqDltwm5euVuE=
git.sr.ht/~jackmordaunt/go-toast v1.1.2/go.mod h1:jA4OqHKTQ4AFBdwrSnwnskUIIS3HYzlJSgdzCKqfavo=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/JohannesKaufmann/html-to-markdown v1.6.0 h1:04VXMiE50YYfCfLboJCLcgqF5x+rHJnb1ssNmqpLH/k=
github.com/JohannesKaufmann/html-to-markdown v1.6.0/go.mod h1:NUI78lGg/a7vpEJTz/0uOcYMaibytE4BUOQS8k78yPQ=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo=
github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k=
github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6 h1:N4lRUXZpZ1KVEUn6hxtco/1d2lgYhNn1fHkkl8WhlyQ=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.6/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=
github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0=
github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g=
github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8=
github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 h1:2HvVAIq+YqgGotK6EkMf+KIEqTISmTYh5zLpYyeTo1Y=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk=
github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/aymanbagabas/go-nativeclipboard v0.1.3 h1:FmAWHPTwneAixu7uGDn3cL42xPlUCdNp2J8egMn3P1k=
github.com/aymanbagabas/go-nativeclipboard v0.1.3/go.mod h1:2o7MyZwwi4pmXXpOpvOS5FwaHyoCIUks0ktjUvB0EoE=
github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charlievieth/fastwalk v1.0.14 h1:3Eh5uaFGwHZd8EGwTjJnSpBkfwfsak9h6ICgnWlhAyg=
github.com/charlievieth/fastwalk v1.0.14/go.mod h1:diVcUreiU1aQ4/Wu3NbxxH4/KYdKpLDojrQ1Bb2KgNY=
github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab h1:J7XQLgl9sefgTnTGrmX3xqvp5o6MCiBzEjGv5igAlc4=
github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab/go.mod h1:hqlYqR7uPKOKfnNeicUbZp0Ps0GeYFlKYtwh5HGDCx8=
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
github.com/charmbracelet/openai-go v0.0.0-20260319145158-d0740cc34266 h1:BW/sZtyd1JyYy0h5adMm3tzpNyL857LWjuTRET6OhpY=
github.com/charmbracelet/openai-go v0.0.0-20260319145158-d0740cc34266/go.mod h1:1DahUaExbUZx/jD+FNT2PKP4L9rLE5+ZBRuI8mZjd/E=
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA=
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/editor v0.2.0 h1:7XLUKtaRaB8jN7bWU2p2UChiySyaAuIfYiIRg8gGWwk=
github.com/charmbracelet/x/editor v0.2.0/go.mod h1:p3oQ28TSL3YPd+GKJ1fHWcp+7bVGpedHpXmo0D6t1dY=
github.com/charmbracelet/x/etag v0.2.0 h1:Euj1VkheoHfTYA9y+TCwkeXF/hN8Fb9l4LqZl79pt04=
github.com/charmbracelet/x/etag v0.2.0/go.mod h1:C1B7/bsgvzzxpfu0Rabbd+rTHJa5TmC/qgTseCf6DF0=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20260109001716-2fbdffcb221f h1:OKFNbG2sSmgpQW9EC3gYNG+QrcQ4+wWYjzfmJvWkkDo=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20260109001716-2fbdffcb221f/go.mod h1:nsExn0DGyX0lh9LwLHTn2Gg+hafdzfSXnC+QmEJTZFY=
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA=
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
github.com/charmbracelet/x/exp/ordered v0.1.0 h1:55/qLwjIh0gL0Vni+QAWk7T/qRVP6sBf+2agPBgnOFE=
github.com/charmbracelet/x/exp/ordered v0.1.0/go.mod h1:5UHwmG+is5THxMyCJHNPCn2/ecI07aKNrW+LcResjJ8=
github.com/charmbracelet/x/exp/slice v0.0.0-20260209194814-eeb2896ac759 h1:96wFGlst+IDv3dIf5q29nw470wJYB3YAgemiciLZcG0=
github.com/charmbracelet/x/exp/slice v0.0.0-20260209194814-eeb2896ac759/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA=
github.com/charmbracelet/x/exp/strings v0.1.0 h1:i69S2XI7uG1u4NLGeJPSYU++Nmjvpo9nwd6aoEm7gkA=
github.com/charmbracelet/x/exp/strings v0.1.0/go.mod h1:/ehtMPNh9K4odGFkqYJKpIYyePhdp1hLBRvyY4bWkH8=
github.com/charmbracelet/x/json v0.2.0 h1:DqB+ZGx2h+Z+1s98HOuOyli+i97wsFQIxP2ZQANTPrQ=
github.com/charmbracelet/x/json v0.2.0/go.mod h1:opFIflx2YgXgi49xVUu8gEQ21teFAxyMwvOiZhIvWNM=
github.com/charmbracelet/x/powernap v0.1.3 h1:rmxdQelSPB1QAgLRNMLOrgCTq3q2RXoLOJ2ZTwKG17g=
github.com/charmbracelet/x/powernap v0.1.3/go.mod h1:cmdl5zlP5mR8TF2Y68UKc7hdGUDiSJ2+4hk0h04Hsx4=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ=
github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
github.com/esiqveland/notify v0.13.3 h1:QCMw6o1n+6rl+oLUfg8P1IIDSFsDEb2WlXvVvIJbI/o=
github.com/esiqveland/notify v0.13.3/go.mod h1:hesw/IRYTO0x99u1JPweAl4+5mwXJibQVUcP0Iu5ORE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gen2brain/beeep v0.11.2 h1:+KfiKQBbQCuhfJFPANZuJ+oxsSKAYNe88hIpJuyKWDA=
github.com/gen2brain/beeep v0.11.2/go.mod h1:jQVvuwnLuwOcdctHn/uyh8horSBNJ8uGb9Cn2W4tvoc=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
github.com/go-git/go-git/v5 v5.17.0 h1:AbyI4xf+7DsjINHMu35quAh4wJygKBKBuXVjV/pxesM=
github.com/go-git/go-git/v5 v5.17.0/go.mod h1:f82C4YiLx+Lhi8eHxltLeGC5uBTXSFa6PC5WW9o4SjI=
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 h1:vymEbVwYFP/L05h5TKQxvkXoKxNvTpjxYKdF1Nlwuao=
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8=
github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc=
github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/jackmordaunt/icns/v3 v3.0.1 h1:xxot6aNuGrU+lNgxz5I5H0qSeCjNKp8uTXB1j8D4S3o=
github.com/jackmordaunt/icns/v3 v3.0.1/go.mod h1:5sHL59nqTd2ynTnowxB/MDQFhKNqkK8X687uKNygaSQ=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jordanella/go-ansi-paintbrush v0.0.0-20240728195301-b7ad996ecf3d h1:on25kP+Sx7sxUMRQiA8gdcToAGet4DK/EIA30mXre+4=
github.com/jordanella/go-ansi-paintbrush v0.0.0-20240728195301-b7ad996ecf3d/go.mod h1:SV0W0APWP9MZ1/gfDQ/NzzTlWdIgYZ/ZbpN4d/UXRYw=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kaptinlin/go-i18n v0.2.12 h1:ywDsvb4KDFddMC2dpI/rrIzGU2mWUSvHmWUm9BMsdl4=
github.com/kaptinlin/go-i18n v0.2.12/go.mod h1:pVcu9qsW5pOIOoZFJXesRYmLos1vMQrby70JPAoWmJU=
github.com/kaptinlin/jsonpointer v0.4.17 h1:mY9k8ciWncxbsECyaxKnR0MdmxamNdp2tLQkAKVrtSk=
github.com/kaptinlin/jsonpointer v0.4.17/go.mod h1:SsfsjqnHG5zuKo1DTBzk1VknaHlL4osHw+X9kZKukpU=
github.com/kaptinlin/jsonschema v0.7.5 h1:jkK4a3NyzNoGlvu12CsL3IcqNMVa5sL51HPVa0nWcPY=
github.com/kaptinlin/jsonschema v0.7.5/go.mod h1:3gIWnptl+SWMyfMR2r4TXXd0xsQZ1m50AKrwmcUONSg=
github.com/kaptinlin/messageformat-go v0.4.18 h1:RBlHVWgZyoxTcUgGWBsl2AcyScq/urqbLZvzgryTmSI=
github.com/kaptinlin/messageformat-go v0.4.18/go.mod h1:ntI3154RnqJgr7GaC+vZBnIExl2V3sv9selvRNNEM24=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ=
github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modelcontextprotocol/go-sdk v1.4.1 h1:M4x9GyIPj+HoIlHNGpK2hq5o3BFhC+78PkEaldQRphc=
github.com/modelcontextprotocol/go-sdk v1.4.1/go.mod h1:Bo/mS87hPQqHSRkMv4dQq1XCu6zv4INdXnFZabkNU6s=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=
github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg=
github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA=
github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg=
github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=
github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
github.com/ncruces/go-sqlite3 v0.32.0 h1:hNBUXp88LrfQCsuyXLqWTbTUG35sUuktDsqhhgHvU20=
github.com/ncruces/go-sqlite3 v0.32.0/go.mod h1:MIWTK60ONDl0oVY073zYvJP21C3Dly6P9bxVpgkLwdQ=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pierrec/lz4/v4 v4.1.25 h1:kocOqRffaIbU5djlIBr7Wh+cx82C0vtFb0fOurZHqD0=
github.com/pierrec/lz4/v4 v4.1.25/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posthog/posthog-go v1.11.1 h1:P0MHlerMW9rNpjW+1szNsJ5HbdYJUv/9lF2DWZCHztE=
github.com/posthog/posthog-go v1.11.1/go.mod h1:wB3/9Q7d9gGb1P/yf/Wri9VBlbP8oA8z++prRzL5OcY=
github.com/pressly/goose/v3 v3.27.0 h1:/D30gVTuQhu0WsNZYbJi4DMOsx1lNq+6SkLe+Wp59BM=
github.com/pressly/goose/v3 v3.27.0/go.mod h1:3ZBeCXqzkgIRvrEMDkYh1guvtoJTU5oMMuDdkutoM78=
github.com/qjebbs/go-jsons v1.0.0-alpha.4 h1:Qsb4ohRUHQODIUAsJKdKJ/SIDbsO7oGOzsfy+h1yQZs=
github.com/qjebbs/go-jsons v1.0.0-alpha.4/go.mod h1:wNJrtinHyC3YSf6giEh4FJN8+yZV7nXBjvmfjhBIcw4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0=
github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=
github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M=
github.com/sergeymakinen/go-bmp v1.0.0/go.mod h1:/mxlAQZRLxSvJFNIEGGLBE/m40f3ZnUifpgVDlcUIEY=
github.com/sergeymakinen/go-ico v1.0.0-beta.0 h1:m5qKH7uPKLdrygMWxbamVn+tl2HfiA3K6MFJw4GfZvQ=
github.com/sergeymakinen/go-ico v1.0.0-beta.0/go.mod h1:wQ47mTczswBO5F0NoDt7O0IXgnV4Xy3ojrroMQzyhUk=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
github.com/sourcegraph/jsonrpc2 v0.2.1 h1:2GtljixMQYUYCmIg7W9aF2dFmniq/mOr2T9tFRh6zSQ=
github.com/sourcegraph/jsonrpc2 v0.2.1/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/u-root/u-root v0.14.1-0.20250807200646-5e7721023dc7 h1:ax+jBy7xFhh+Ka0IGLmH5mft+YDuqvzEjSgWuAP0nsM=
github.com/u-root/u-root v0.14.1-0.20250807200646-5e7721023dc7/go.mod h1:/0Qr7qJeDwWxoKku2xKQ4Szc+SwBE3g9VE8jNiamsmc=
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk=
github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho=
go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc=
go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4=
go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI=
go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo=
go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts=
go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA=
go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc=
go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY=
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.270.0 h1:4rJZbIuWSTohczG9mG2ukSDdt9qKx4sSSHIydTN26L4=
google.golang.org/api v0.270.0/go.mod h1:5+H3/8DlXpQWrSz4RjGGwz5HfJAQSEI8Bc6JqQNH77U=
google.golang.org/genai v1.50.0 h1:yHKV/vjoeN9PJ3iF0ur4cBZco4N3Kl7j09rMq7XSoWk=
google.golang.org/genai v1.50.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290 h1:g3ah7zaWmw41EtOgBNXpx8zk4HYuH3OMwB+qh1Dt834=
gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290/go.mod h1:sbq5oMEcM4PXngbcNbHhzfCP9OdZodLhrbRYoyg09HY=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.30.2 h1:4yPaaq9dXYXZ2V8s1UgrC3KIj580l2N4ClrLwnbv2so=
modernc.org/ccgo/v4 v4.30.2/go.mod h1:yZMnhWEdW0qw3EtCndG1+ldRrVGS+bIwyWmAWzS0XEw=
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.68.0 h1:PJ5ikFOV5pwpW+VqCK1hKJuEWsonkIJhhIXyuF/91pQ=
modernc.org/libc v1.68.0/go.mod h1:NnKCYeoYgsEqnY3PgvNgAeaJnso968ygU8Z0DxjoEc0=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5 h1:mO2lyKtGwu4mGQ+Qqjx0+fd5UU5BXhX/rslFmxd5aco=
mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5/go.mod h1:Of9PCedbLDYT8b3EyiYG64rNnx5nOp27OLCVdDrjJyo=
mvdan.cc/sh/v3 v3.13.0 h1:dSfq/MVsY4w0Vsi6Lbs0IcQquMVqLdKLESAOZjuHdLg=
mvdan.cc/sh/v3 v3.13.0/go.mod h1:KV1GByGPc/Ho0X1E6Uz9euhsIQEj4hwyKnodLlFLoDM=


================================================
FILE: internal/agent/agent.go
================================================
// Package agent is the core orchestration layer for Crush AI agents.
//
// It provides session-based AI agent functionality for managing
// conversations, tool execution, and message handling. It coordinates
// interactions between language models, messages, sessions, and tools while
// handling features like automatic summarization, queuing, and token
// management.
package agent

import (
	"cmp"
	"context"
	_ "embed"
	"encoding/base64"
	"errors"
	"fmt"
	"log/slog"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"charm.land/catwalk/pkg/catwalk"
	"charm.land/fantasy"
	"charm.land/fantasy/providers/anthropic"
	"charm.land/fantasy/providers/bedrock"
	"charm.land/fantasy/providers/google"
	"charm.land/fantasy/providers/openai"
	"charm.land/fantasy/providers/openrouter"
	"charm.land/fantasy/providers/vercel"
	"charm.land/lipgloss/v2"
	"github.com/charmbracelet/crush/internal/agent/hyper"
	"github.com/charmbracelet/crush/internal/agent/notify"
	"github.com/charmbracelet/crush/internal/agent/tools"
	"github.com/charmbracelet/crush/internal/agent/tools/mcp"
	"github.com/charmbracelet/crush/internal/config"
	"github.com/charmbracelet/crush/internal/csync"
	"github.com/charmbracelet/crush/internal/message"
	"github.com/charmbracelet/crush/internal/permission"
	"github.com/charmbracelet/crush/internal/pubsub"
	"github.com/charmbracelet/crush/internal/session"
	"github.com/charmbracelet/crush/internal/stringext"
	"github.com/charmbracelet/crush/internal/version"
	"github.com/charmbracelet/x/exp/charmtone"
)

const (
	DefaultSessionName = "Untitled Session"

	// Constants for auto-summarization thresholds
	largeContextWindowThreshold = 200_000
	largeContextWindowBuffer    = 20_000
	smallContextWindowRatio     = 0.2
)

var userAgent = fmt.Sprintf("Charm-Crush/%s (https://charm.land/crush)", version.Version)

//go:embed templates/title.md
var titlePrompt []byte

//go:embed templates/summary.md
var summaryPrompt []byte

// Used to remove <think> tags from generated titles.
var thinkTagRegex = regexp.MustCompile(`<think>.*?</think>`)

type SessionAgentCall struct {
	SessionID        string
	Prompt           string
	ProviderOptions  fantasy.ProviderOptions
	Attachments      []message.Attachment
	MaxOutputTokens  int64
	Temperature      *float64
	TopP             *float64
	TopK             *int64
	FrequencyPenalty *float64
	PresencePenalty  *float64
	NonInteractive   bool
}

type SessionAgent interface {
	Run(context.Context, SessionAgentCall) (*fantasy.AgentResult, error)
	SetModels(large Model, small Model)
	SetTools(tools []fantasy.AgentTool)
	SetSystemPrompt(systemPrompt string)
	Cancel(sessionID string)
	CancelAll()
	IsSessionBusy(sessionID string) bool
	IsBusy() bool
	QueuedPrompts(sessionID string) int
	QueuedPromptsList(sessionID string) []string
	ClearQueue(sessionID string)
	Summarize(context.Context, string, fantasy.ProviderOptions) error
	Model() Model
}

type Model struct {
	Model      fantasy.LanguageModel
	CatwalkCfg catwalk.Model
	ModelCfg   config.SelectedModel
}

type sessionAgent struct {
	largeModel         *csync.Value[Model]
	smallModel         *csync.Value[Model]
	systemPromptPrefix *csync.Value[string]
	systemPrompt       *csync.Value[string]
	tools              *csync.Slice[fantasy.AgentTool]

	isSubAgent           bool
	sessions             session.Service
	messages             message.Service
	disableAutoSummarize bool
	isYolo               bool
	notify               pubsub.Publisher[notify.Notification]

	messageQueue   *csync.Map[string, []SessionAgentCall]
	activeRequests *csync.Map[string, context.CancelFunc]
}

type SessionAgentOptions struct {
	LargeModel           Model
	SmallModel           Model
	SystemPromptPrefix   string
	SystemPrompt         string
	IsSubAgent           bool
	DisableAutoSummarize bool
	IsYolo               bool
	Sessions             session.Service
	Messages             message.Service
	Tools                []fantasy.AgentTool
	Notify               pubsub.Publisher[notify.Notification]
}

func NewSessionAgent(
	opts SessionAgentOptions,
) SessionAgent {
	return &sessionAgent{
		largeModel:           csync.NewValue(opts.LargeModel),
		smallModel:           csync.NewValue(opts.SmallModel),
		systemPromptPrefix:   csync.NewValue(opts.SystemPromptPrefix),
		systemPrompt:         csync.NewValue(opts.SystemPrompt),
		isSubAgent:           opts.IsSubAgent,
		sessions:             opts.Sessions,
		messages:             opts.Messages,
		disableAutoSummarize: opts.DisableAutoSummarize,
		tools:                csync.NewSliceFrom(opts.Tools),
		isYolo:               opts.IsYolo,
		notify:               opts.Notify,
		messageQueue:         csync.NewMap[string, []SessionAgentCall](),
		activeRequests:       csync.NewMap[string, context.CancelFunc](),
	}
}

func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy.AgentResult, error) {
	if call.Prompt == "" && !message.ContainsTextAttachment(call.Attachments) {
		return nil, ErrEmptyPrompt
	}
	if call.SessionID == "" {
		return nil, ErrSessionMissing
	}

	// Queue the message if busy
	if a.IsSessionBusy(call.SessionID) {
		existing, ok := a.messageQueue.Get(call.SessionID)
		if !ok {
			existing = []SessionAgentCall{}
		}
		existing = append(existing, call)
		a.messageQueue.Set(call.SessionID, existing)
		return nil, nil
	}

	// Copy mutable fields under lock to avoid races with SetTools/SetModels.
	agentTools := a.tools.Copy()
	largeModel := a.largeModel.Get()
	systemPrompt := a.systemPrompt.Get()
	promptPrefix := a.systemPromptPrefix.Get()
	var instructions strings.Builder

	for _, server := range mcp.GetStates() {
		if server.State != mcp.StateConnected {
			continue
		}
		if s := server.Client.InitializeResult().Instructions; s != "" {
			instructions.WriteString(s)
			instructions.WriteString("\n\n")
		}
	}

	if s := instructions.String(); s != "" {
		systemPrompt += "\n\n<mcp-instructions>\n" + s + "\n</mcp-instructions>"
	}

	if len(agentTools) > 0 {
		// Add Anthropic caching to the last tool.
		agentTools[len(agentTools)-1].SetProviderOptions(a.getCacheControlOptions())
	}

	agent := fantasy.NewAgent(
		largeModel.Model,
		fantasy.WithSystemPrompt(systemPrompt),
		fantasy.WithTools(agentTools...),
		fantasy.WithUserAgent(userAgent),
	)

	sessionLock := sync.Mutex{}
	currentSession, err := a.sessions.Get(ctx, call.SessionID)
	if err != nil {
		return nil, fmt.Errorf("failed to get session: %w", err)
	}

	msgs, err := a.getSessionMessages(ctx, currentSession)
	if err != nil {
		return nil, fmt.Errorf("failed to get session messages: %w", err)
	}

	var wg sync.WaitGroup
	// Generate title if first message.
	if len(msgs) == 0 {
		titleCtx := ctx // Copy to avoid race with ctx reassignment below.
		wg.Go(func() {
			a.generateTitle(titleCtx, call.SessionID, call.Prompt)
		})
	}
	defer wg.Wait()

	// Add the user message to the session.
	_, err = a.createUserMessage(ctx, call)
	if err != nil {
		return nil, err
	}

	// Add the session to the context.
	ctx = context.WithValue(ctx, tools.SessionIDContextKey, call.SessionID)

	genCtx, cancel := context.WithCancel(ctx)
	a.activeRequests.Set(call.SessionID, cancel)

	defer cancel()
	defer a.activeRequests.Del(call.SessionID)

	history, files := a.preparePrompt(msgs, call.Attachments...)

	startTime := time.Now()
	a.eventPromptSent(call.SessionID)

	var currentAssistant *message.Message
	var shouldSummarize bool
	result, err := agent.Stream(genCtx, fantasy.AgentStreamCall{
		Prompt:           message.PromptWithTextAttachments(call.Prompt, call.Attachments),
		Files:            files,
		Messages:         history,
		ProviderOptions:  call.ProviderOptions,
		MaxOutputTokens:  &call.MaxOutputTokens,
		TopP:             call.TopP,
		Temperature:      call.Temperature,
		PresencePenalty:  call.PresencePenalty,
		TopK:             call.TopK,
		FrequencyPenalty: call.FrequencyPenalty,
		PrepareStep: func(callContext context.Context, options fantasy.PrepareStepFunctionOptions) (_ context.Context, prepared fantasy.PrepareStepResult, err error) {
			prepared.Messages = options.Messages
			for i := range prepared.Messages {
				prepared.Messages[i].ProviderOptions = nil
			}

			// Use latest tools (updated by SetTools when MCP tools change).
			prepared.Tools = a.tools.Copy()

			queuedCalls, _ := a.messageQueue.Get(call.SessionID)
			a.messageQueue.Del(call.SessionID)
			for _, queued := range queuedCalls {
				userMessage, createErr := a.createUserMessage(callContext, queued)
				if createErr != nil {
					return callContext, prepared, createErr
				}
				prepared.Messages = append(prepared.Messages, userMessage.ToAIMessage()...)
			}

			prepared.Messages = a.workaroundProviderMediaLimitations(prepared.Messages, largeModel)

			lastSystemRoleInx := 0
			systemMessageUpdated := false
			for i, msg := range prepared.Messages {
				// Only add cache control to the last message.
				if msg.Role == fantasy.MessageRoleSystem {
					lastSystemRoleInx = i
				} else if !systemMessageUpdated {
					prepared.Messages[lastSystemRoleInx].ProviderOptions = a.getCacheControlOptions()
					systemMessageUpdated = true
				}
				// Than add cache control to the last 2 messages.
				if i > len(prepared.Messages)-3 {
					prepared.Messages[i].ProviderOptions = a.getCacheControlOptions()
				}
			}

			if promptPrefix != "" {
				prepared.Messages = append([]fantasy.Message{fantasy.NewSystemMessage(promptPrefix)}, prepared.Messages...)
			}

			var assistantMsg message.Message
			assistantMsg, err = a.messages.Create(callContext, call.SessionID, message.CreateMessageParams{
				Role:     message.Assistant,
				Parts:    []message.ContentPart{},
				Model:    largeModel.ModelCfg.Model,
				Provider: largeModel.ModelCfg.Provider,
			})
			if err != nil {
				return callContext, prepared, err
			}
			callContext = context.WithValue(callContext, tools.MessageIDContextKey, assistantMsg.ID)
			callContext = context.WithValue(callContext, tools.SupportsImagesContextKey, largeModel.CatwalkCfg.SupportsImages)
			callContext = context.WithValue(callContext, tools.ModelNameContextKey, largeModel.CatwalkCfg.Name)
			currentAssistant = &assistantMsg
			return callContext, prepared, err
		},
		OnReasoningStart: func(id string, reasoning fantasy.ReasoningContent) error {
			currentAssistant.AppendReasoningContent(reasoning.Text)
			return a.messages.Update(genCtx, *currentAssistant)
		},
		OnReasoningDelta: func(id string, text string) error {
			currentAssistant.AppendReasoningContent(text)
			return a.messages.Update(genCtx, *currentAssistant)
		},
		OnReasoningEnd: func(id string, reasoning fantasy.ReasoningContent) error {
			// handle anthropic signature
			if anthropicData, ok := reasoning.ProviderMetadata[anthropic.Name]; ok {
				if reasoning, ok := anthropicData.(*anthropic.ReasoningOptionMetadata); ok {
					currentAssistant.AppendReasoningSignature(reasoning.Signature)
				}
			}
			if googleData, ok := reasoning.ProviderMetadata[google.Name]; ok {
				if reasoning, ok := googleData.(*google.ReasoningMetadata); ok {
					currentAssistant.AppendThoughtSignature(reasoning.Signature, reasoning.ToolID)
				}
			}
			if openaiData, ok := reasoning.ProviderMetadata[openai.Name]; ok {
				if reasoning, ok := openaiData.(*openai.ResponsesReasoningMetadata); ok {
					currentAssistant.SetReasoningResponsesData(reasoning)
				}
			}
			currentAssistant.FinishThinking()
			return a.messages.Update(genCtx, *currentAssistant)
		},
		OnTextDelta: func(id string, text string) error {
			// Strip leading newline from initial text content. This is is
			// particularly important in non-interactive mode where leading
			// newlines are very visible.
			if len(currentAssistant.Parts) == 0 {
				text = strings.TrimPrefix(text, "\n")
			}

			currentAssistant.AppendContent(text)
			return a.messages.Update(genCtx, *currentAssistant)
		},
		OnToolInputStart: func(id string, toolName string) error {
			toolCall := message.ToolCall{
				ID:               id,
				Name:             toolName,
				ProviderExecuted: false,
				Finished:         false,
			}
			currentAssistant.AddToolCall(toolCall)
			return a.messages.Update(genCtx, *currentAssistant)
		},
		OnRetry: func(err *fantasy.ProviderError, delay time.Duration) {
			// TODO: implement
		},
		OnToolCall: func(tc fantasy.ToolCallContent) error {
			toolCall := message.ToolCall{
				ID:               tc.ToolCallID,
				Name:             tc.ToolName,
				Input:            tc.Input,
				ProviderExecuted: false,
				Finished:         true,
			}
			currentAssistant.AddToolCall(toolCall)
			return a.messages.Update(genCtx, *currentAssistant)
		},
		OnToolResult: func(result fantasy.ToolResultContent) error {
			toolResult := a.convertToToolResult(result)
			_, createMsgErr := a.messages.Create(genCtx, currentAssistant.SessionID, message.CreateMessageParams{
				Role: message.Tool,
				Parts: []message.ContentPart{
					toolResult,
				},
			})
			return createMsgErr
		},
		OnStepFinish: func(stepResult fantasy.StepResult) error {
			finishReason := message.FinishReasonUnknown
			switch stepResult.FinishReason {
			case fantasy.FinishReasonLength:
				finishReason = message.FinishReasonMaxTokens
			case fantasy.FinishReasonStop:
				finishReason = message.FinishReasonEndTurn
			case fantasy.FinishReasonToolCalls:
				finishReason = message.FinishReasonToolUse
			}
			currentAssistant.AddFinish(finishReason, "", "")
			sessionLock.Lock()
			defer sessionLock.Unlock()

			updatedSession, getSessionErr := a.sessions.Get(ctx, call.SessionID)
			if getSessionErr != nil {
				return getSessionErr
			}
			a.updateSessionUsage(largeModel, &updatedSession, stepResult.Usage, a.openrouterCost(stepResult.ProviderMetadata))
			_, sessionErr := a.sessions.Save(ctx, updatedSession)
			if sessionErr != nil {
				return sessionErr
			}
			currentSession = updatedSession
			return a.messages.Update(genCtx, *currentAssistant)
		},
		StopWhen: []fantasy.StopCondition{
			func(_ []fantasy.StepResult) bool {
				cw := int64(largeModel.CatwalkCfg.ContextWindow)
				tokens := currentSession.CompletionTokens + currentSession.PromptTokens
				remaining := cw - tokens
				var threshold int64
				if cw > largeContextWindowThreshold {
					threshold = largeContextWindowBuffer
				} else {
					threshold = int64(float64(cw) * smallContextWindowRatio)
				}
				if (remaining <= threshold) && !a.disableAutoSummarize {
					shouldSummarize = true
					return true
				}
				return false
			},
			func(steps []fantasy.StepResult) bool {
				return hasRepeatedToolCalls(steps, loopDetectionWindowSize, loopDetectionMaxRepeats)
			},
		},
	})

	a.eventPromptResponded(call.SessionID, time.Since(startTime).Truncate(time.Second))

	if err != nil {
		isCancelErr := errors.Is(err, context.Canceled)
		isPermissionErr := errors.Is(err, permission.ErrorPermissionDenied)
		if currentAssistant == nil {
			return result, err
		}
		// Ensure we finish thinking on error to close the reasoning state.
		currentAssistant.FinishThinking()
		toolCalls := currentAssistant.ToolCalls()
		// INFO: we use the parent context here because the genCtx has been cancelled.
		msgs, createErr := a.messages.List(ctx, currentAssistant.SessionID)
		if createErr != nil {
			return nil, createErr
		}
		for _, tc := range toolCalls {
			if !tc.Finished {
				tc.Finished = true
				tc.Input = "{}"
				currentAssistant.AddToolCall(tc)
				updateErr := a.messages.Update(ctx, *currentAssistant)
				if updateErr != nil {
					return nil, updateErr
				}
			}

			found := false
			for _, msg := range msgs {
				if msg.Role == message.Tool {
					for _, tr := range msg.ToolResults() {
						if tr.ToolCallID == tc.ID {
							found = true
							break
						}
					}
				}
				if found {
					break
				}
			}
			if found {
				continue
			}
			content := "There was an error while executing the tool"
			if isCancelErr {
				content = "Tool execution canceled by user"
			} else if isPermissionErr {
				content = "User denied permission"
			}
			toolResult := message.ToolResult{
				ToolCallID: tc.ID,
				Name:       tc.Name,
				Content:    content,
				IsError:    true,
			}
			_, createErr = a.messages.Create(ctx, currentAssistant.SessionID, message.CreateMessageParams{
				Role: message.Tool,
				Parts: []message.ContentPart{
					toolResult,
				},
			})
			if createErr != nil {
				return nil, createErr
			}
		}
		var fantasyErr *fantasy.Error
		var providerErr *fantasy.ProviderError
		const defaultTitle = "Provider Error"
		linkStyle := lipgloss.NewStyle().Foreground(charmtone.Guac).Underline(true)
		if isCancelErr {
			currentAssistant.AddFinish(message.FinishReasonCanceled, "User canceled request", "")
		} else if isPermissionErr {
			currentAssistant.AddFinish(message.FinishReasonPermissionDenied, "User denied permission", "")
		} else if errors.Is(err, hyper.ErrNoCredits) {
			url := hyper.BaseURL()
			link := linkStyle.Hyperlink(url, "id=hyper").Render(url)
			currentAssistant.AddFinish(message.FinishReasonError, "No credits", "You're out of credits. Add more at "+link)
		} else if errors.As(err, &providerErr) {
			if providerErr.Message == "The requested model is not supported." {
				url := "https://github.com/settings/copilot/features"
				link := linkStyle.Hyperlink(url, "id=copilot").Render(url)
				currentAssistant.AddFinish(
					message.FinishReasonError,
					"Copilot model not enabled",
					fmt.Sprintf("%q is not enabled in Copilot. Go to the following page to enable it. Then, wait 5 minutes before trying again. %s", largeModel.CatwalkCfg.Name, link),
				)
			} else {
				currentAssistant.AddFinish(message.FinishReasonError, cmp.Or(stringext.Capitalize(providerErr.Title), defaultTitle), providerErr.Message)
			}
		} else if errors.As(err, &fantasyErr) {
			currentAssistant.AddFinish(message.FinishReasonError, cmp.Or(stringext.Capitalize(fantasyErr.Title), defaultTitle), fantasyErr.Message)
		} else {
			currentAssistant.AddFinish(message.FinishReasonError, defaultTitle, err.Error())
		}
		// Note: we use the parent context here because the genCtx has been
		// cancelled.
		updateErr := a.messages.Update(ctx, *currentAssistant)
		if updateErr != nil {
			return nil, updateErr
		}
		return nil, err
	}

	// Send notification that agent has finished its turn (skip for
	// nested/non-interactive sessions).
	if !call.NonInteractive && a.notify != nil {
		a.notify.Publish(pubsub.CreatedEvent, notify.Notification{
			SessionID:    call.SessionID,
			SessionTitle: currentSession.Title,
			Type:         notify.TypeAgentFinished,
		})
	}

	if shouldSummarize {
		a.activeRequests.Del(call.SessionID)
		if summarizeErr := a.Summarize(genCtx, call.SessionID, call.ProviderOptions); summarizeErr != nil {
			return nil, summarizeErr
		}
		// If the agent wasn't done...
		if len(currentAssistant.ToolCalls()) > 0 {
			existing, ok := a.messageQueue.Get(call.SessionID)
			if !ok {
				existing = []SessionAgentCall{}
			}
			call.Prompt = fmt.Sprintf("The previous session was interrupted because it got too long, the initial user request was: `%s`", call.Prompt)
			existing = append(existing, call)
			a.messageQueue.Set(call.SessionID, existing)
		}
	}

	// Release active request before processing queued messages.
	a.activeRequests.Del(call.SessionID)
	cancel()

	queuedMessages, ok := a.messageQueue.Get(call.SessionID)
	if !ok || len(queuedMessages) == 0 {
		return result, err
	}
	// There are queued messages restart the loop.
	firstQueuedMessage := queuedMessages[0]
	a.messageQueue.Set(call.SessionID, queuedMessages[1:])
	return a.Run(ctx, firstQueuedMessage)
}

func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fantasy.ProviderOptions) error {
	if a.IsSessionBusy(sessionID) {
		return ErrSessionBusy
	}

	// Copy mutable fields under lock to avoid races with SetModels.
	largeModel := a.largeModel.Get()
	systemPromptPrefix := a.systemPromptPrefix.Get()

	currentSession, err := a.sessions.Get(ctx, sessionID)
	if err != nil {
		return fmt.Errorf("failed to get session: %w", err)
	}
	msgs, err := a.getSessionMessages(ctx, currentSession)
	if err != nil {
		return err
	}
	if len(msgs) == 0 {
		// Nothing to summarize.
		return nil
	}

	aiMsgs, _ := a.preparePrompt(msgs)

	genCtx, cancel := context.WithCancel(ctx)
	a.activeRequests.Set(sessionID, cancel)
	defer a.activeRequests.Del(sessionID)
	defer cancel()

	agent := fantasy.NewAgent(largeModel.Model,
		fantasy.WithSystemPrompt(string(summaryPrompt)),
		fantasy.WithUserAgent(userAgent),
	)
	summaryMessage, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{
		Role:             message.Assistant,
		Model:            largeModel.Model.Model(),
		Provider:         largeModel.Model.Provider(),
		IsSummaryMessage: true,
	})
	if err != nil {
		return err
	}

	summaryPromptText := buildSummaryPrompt(currentSession.Todos)

	resp, err := agent.Stream(genCtx, fantasy.AgentStreamCall{
		Prompt:          summaryPromptText,
		Messages:        aiMsgs,
		ProviderOptions: opts,
		PrepareStep: func(callContext context.Context, options fantasy.PrepareStepFunctionOptions) (_ context.Context, prepared fantasy.PrepareStepResult, err error) {
			prepared.Messages = options.Messages
			if systemPromptPrefix != "" {
				prepared.Messages = append([]fantasy.Message{fantasy.NewSystemMessage(systemPromptPrefix)}, prepared.Messages...)
			}
			return callContext, prepared, nil
		},
		OnReasoningDelta: func(id string, text string) error {
			summaryMessage.AppendReasoningContent(text)
			return a.messages.Update(genCtx, summaryMessage)
		},
		OnReasoningEnd: func(id string, reasoning fantasy.ReasoningContent) error {
			// Handle anthropic signature.
			if anthropicData, ok := reasoning.ProviderMetadata["anthropic"]; ok {
				if signature, ok := anthropicData.(*anthropic.ReasoningOptionMetadata); ok && signature.Signature != "" {
					summaryMessage.AppendReasoningSignature(signature.Signature)
				}
			}
			summaryMessage.FinishThinking()
			return a.messages.Update(genCtx, summaryMessage)
		},
		OnTextDelta: func(id, text string) error {
			summaryMessage.AppendContent(text)
			return a.messages.Update(genCtx, summaryMessage)
		},
	})
	if err != nil {
		isCancelErr := errors.Is(err, context.Canceled)
		if isCancelErr {
			// User cancelled summarize we need to remove the summary message.
			deleteErr := a.messages.Delete(ctx, summaryMessage.ID)
			return deleteErr
		}
		return err
	}

	summaryMessage.AddFinish(message.FinishReasonEndTurn, "", "")
	err = a.messages.Update(genCtx, summaryMessage)
	if err != nil {
		return err
	}

	var openrouterCost *float64
	for _, step := range resp.Steps {
		stepCost := a.openrouterCost(step.ProviderMetadata)
		if stepCost != nil {
			newCost := *stepCost
			if openrouterCost != nil {
				newCost += *openrouterCost
			}
			openrouterCost = &newCost
		}
	}

	a.updateSessionUsage(largeModel, &currentSession, resp.TotalUsage, openrouterCost)

	// Just in case, get just the last usage info.
	usage := resp.Response.Usage
	currentSession.SummaryMessageID = summaryMessage.ID
	currentSession.CompletionTokens = usage.OutputTokens
	currentSession.PromptTokens = 0
	_, err = a.sessions.Save(genCtx, currentSession)
	return err
}

func (a *sessionAgent) getCacheControlOptions() fantasy.ProviderOptions {
	if t, _ := strconv.ParseBool(os.Getenv("CRUSH_DISABLE_ANTHROPIC_CACHE")); t {
		return fantasy.ProviderOptions{}
	}
	return fantasy.ProviderOptions{
		anthropic.Name: &anthropic.ProviderCacheControlOptions{
			CacheControl: anthropic.CacheControl{Type: "ephemeral"},
		},
		bedrock.Name: &anthropic.ProviderCacheControlOptions{
			CacheControl: anthropic.CacheControl{Type: "ephemeral"},
		},
		vercel.Name: &anthropic.ProviderCacheControlOptions{
			CacheControl: anthropic.CacheControl{Type: "ephemeral"},
		},
	}
}

func (a *sessionAgent) createUserMessage(ctx context.Context, call SessionAgentCall) (message.Message, error) {
	parts := []message.ContentPart{message.TextContent{Text: call.Prompt}}
	var attachmentParts []message.ContentPart
	for _, attachment := range call.Attachments {
		attachmentParts = append(attachmentParts, message.BinaryContent{Path: attachment.FilePath, MIMEType: attachment.MimeType, Data: attachment.Content})
	}
	parts = append(parts, attachmentParts...)
	msg, err := a.messages.Create(ctx, call.SessionID, message.CreateMessageParams{
		Role:  message.User,
		Parts: parts,
	})
	if err != nil {
		return message.Message{}, fmt.Errorf("failed to create user message: %w", err)
	}
	return msg, nil
}

func (a *sessionAgent) preparePrompt(msgs []message.Message, attachments ...message.Attachment) ([]fantasy.Message, []fantasy.FilePart) {
	var history []fantasy.Message
	if !a.isSubAgent {
		history = append(history, fantasy.NewUserMessage(
			fmt.Sprintf("<system_reminder>%s</system_reminder>",
				`This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.
If you are working on tasks that would benefit from a todo list please use the "todos" tool to create one.
If not, please feel free to ignore. Again do not mention this message to the user.`,
			),
		))
	}
	for _, m := range msgs {
		if len(m.Parts) == 0 {
			continue
		}
		// Assistant message without content or tool calls (cancelled before it
		// returned anything).
		if m.Role == message.Assistant && len(m.ToolCalls()) == 0 && m.Content().Text == "" && m.ReasoningContent().String() == "" {
			continue
		}
		history = append(history, m.ToAIMessage()...)
	}

	var files []fantasy.FilePart
	for _, attachment := range attachments {
		if attachment.IsText() {
			continue
		}
		files = append(files, fantasy.FilePart{
			Filename:  attachment.FileName,
			Data:      attachment.Content,
			MediaType: attachment.MimeType,
		})
	}

	return history, files
}

func (a *sessionAgent) getSessionMessages(ctx context.Context, session session.Session) ([]message.Message, error) {
	msgs, err := a.messages.List(ctx, session.ID)
	if err != nil {
		return nil, fmt.Errorf("failed to list messages: %w", err)
	}

	if session.SummaryMessageID != "" {
		summaryMsgIndex := -1
		for i, msg := r
Download .txt
gitextract_j0rg_ehg/

├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── cla-signatures.json
│   ├── dependabot.yml
│   ├── entitlements.plist
│   ├── labeler.yml
│   └── workflows/
│       ├── build.yml
│       ├── cla.yml
│       ├── labeler.yml
│       ├── lint-sync.yml
│       ├── lint.yml
│       ├── nightly.yml
│       ├── release.yml
│       ├── schema-update.yml
│       ├── security.yml
│       └── snapshot.yml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yml
├── AGENTS.md
├── CLA.md
├── LICENSE.md
├── README.md
├── Taskfile.yaml
├── crush.json
├── go.mod
├── go.sum
├── internal/
│   ├── agent/
│   │   ├── agent.go
│   │   ├── agent_test.go
│   │   ├── agent_tool.go
│   │   ├── agentic_fetch_tool.go
│   │   ├── common_test.go
│   │   ├── coordinator.go
│   │   ├── coordinator_test.go
│   │   ├── errors.go
│   │   ├── event.go
│   │   ├── hyper/
│   │   │   ├── provider.go
│   │   │   └── provider.json
│   │   ├── loop_detection.go
│   │   ├── loop_detection_test.go
│   │   ├── notify/
│   │   │   └── notify.go
│   │   ├── prompt/
│   │   │   └── prompt.go
│   │   ├── prompts.go
│   │   ├── templates/
│   │   │   ├── agent_tool.md
│   │   │   ├── agentic_fetch.md
│   │   │   ├── agentic_fetch_prompt.md.tpl
│   │   │   ├── coder.md.tpl
│   │   │   ├── initialize.md.tpl
│   │   │   ├── summary.md
│   │   │   ├── task.md.tpl
│   │   │   └── title.md
│   │   ├── testdata/
│   │   │   └── TestCoderAgent/
│   │   │       ├── anthropic-sonnet/
│   │   │       │   ├── bash_tool.yaml
│   │   │       │   ├── download_tool.yaml
│   │   │       │   ├── fetch_tool.yaml
│   │   │       │   ├── glob_tool.yaml
│   │   │       │   ├── grep_tool.yaml
│   │   │       │   ├── ls_tool.yaml
│   │   │       │   ├── multiedit_tool.yaml
│   │   │       │   ├── parallel_tool_calls.yaml
│   │   │       │   ├── read_a_file.yaml
│   │   │       │   ├── simple_test.yaml
│   │   │       │   ├── sourcegraph_tool.yaml
│   │   │       │   ├── update_a_file.yaml
│   │   │       │   └── write_tool.yaml
│   │   │       ├── openai-gpt-5/
│   │   │       │   ├── bash_tool.yaml
│   │   │       │   ├── download_tool.yaml
│   │   │       │   ├── fetch_tool.yaml
│   │   │       │   ├── glob_tool.yaml
│   │   │       │   ├── grep_tool.yaml
│   │   │       │   ├── ls_tool.yaml
│   │   │       │   ├── multiedit_tool.yaml
│   │   │       │   ├── parallel_tool_calls.yaml
│   │   │       │   ├── read_a_file.yaml
│   │   │       │   ├── simple_test.yaml
│   │   │       │   ├── sourcegraph_tool.yaml
│   │   │       │   ├── update_a_file.yaml
│   │   │       │   └── write_tool.yaml
│   │   │       ├── openrouter-kimi-k2/
│   │   │       │   ├── bash_tool.yaml
│   │   │       │   ├── download_tool.yaml
│   │   │       │   ├── fetch_tool.yaml
│   │   │       │   ├── glob_tool.yaml
│   │   │       │   ├── grep_tool.yaml
│   │   │       │   ├── ls_tool.yaml
│   │   │       │   ├── multiedit_tool.yaml
│   │   │       │   ├── parallel_tool_calls.yaml
│   │   │       │   ├── read_a_file.yaml
│   │   │       │   ├── simple_test.yaml
│   │   │       │   ├── sourcegraph_tool.yaml
│   │   │       │   ├── update_a_file.yaml
│   │   │       │   └── write_tool.yaml
│   │   │       └── zai-glm4.6/
│   │   │           ├── bash_tool.yaml
│   │   │           ├── download_tool.yaml
│   │   │           ├── fetch_tool.yaml
│   │   │           ├── glob_tool.yaml
│   │   │           ├── grep_tool.yaml
│   │   │           ├── ls_tool.yaml
│   │   │           ├── multiedit_tool.yaml
│   │   │           ├── parallel_tool_calls.yaml
│   │   │           ├── read_a_file.yaml
│   │   │           ├── simple_test.yaml
│   │   │           ├── sourcegraph_tool.yaml
│   │   │           ├── update_a_file.yaml
│   │   │           └── write_tool.yaml
│   │   └── tools/
│   │       ├── bash.go
│   │       ├── bash.tpl
│   │       ├── bash_test.go
│   │       ├── context_test.go
│   │       ├── diagnostics.go
│   │       ├── diagnostics.md
│   │       ├── download.go
│   │       ├── download.md
│   │       ├── edit.go
│   │       ├── edit.md
│   │       ├── fetch.go
│   │       ├── fetch.md
│   │       ├── fetch_helpers.go
│   │       ├── fetch_types.go
│   │       ├── glob.go
│   │       ├── glob.md
│   │       ├── grep.go
│   │       ├── grep.md
│   │       ├── grep_test.go
│   │       ├── job_kill.go
│   │       ├── job_kill.md
│   │       ├── job_output.go
│   │       ├── job_output.md
│   │       ├── job_test.go
│   │       ├── list_mcp_resources.go
│   │       ├── list_mcp_resources.md
│   │       ├── ls.go
│   │       ├── ls.md
│   │       ├── lsp_restart.go
│   │       ├── lsp_restart.md
│   │       ├── mcp/
│   │       │   ├── init.go
│   │       │   ├── init_test.go
│   │       │   ├── prompts.go
│   │       │   ├── resources.go
│   │       │   ├── tools.go
│   │       │   └── tools_test.go
│   │       ├── mcp-tools.go
│   │       ├── multiedit.go
│   │       ├── multiedit.md
│   │       ├── multiedit_test.go
│   │       ├── read_mcp_resource.go
│   │       ├── read_mcp_resource.md
│   │       ├── references.go
│   │       ├── references.md
│   │       ├── rg.go
│   │       ├── safe.go
│   │       ├── search.go
│   │       ├── sourcegraph.go
│   │       ├── sourcegraph.md
│   │       ├── testdata/
│   │       │   └── grep.txt
│   │       ├── todos.go
│   │       ├── todos.md
│   │       ├── tools.go
│   │       ├── view.go
│   │       ├── view.md
│   │       ├── view_test.go
│   │       ├── web_fetch.go
│   │       ├── web_fetch.md
│   │       ├── web_search.go
│   │       ├── web_search.md
│   │       ├── write.go
│   │       └── write.md
│   ├── ansiext/
│   │   └── ansi.go
│   ├── app/
│   │   ├── app.go
│   │   ├── app_test.go
│   │   ├── lsp_events.go
│   │   ├── provider.go
│   │   ├── provider_test.go
│   │   └── resolve_session_test.go
│   ├── cmd/
│   │   ├── dirs.go
│   │   ├── dirs_test.go
│   │   ├── login.go
│   │   ├── logs.go
│   │   ├── models.go
│   │   ├── projects.go
│   │   ├── projects_test.go
│   │   ├── root.go
│   │   ├── run.go
│   │   ├── schema.go
│   │   ├── session.go
│   │   ├── stats/
│   │   │   ├── AGENTS.md
│   │   │   ├── index.css
│   │   │   ├── index.html
│   │   │   └── index.js
│   │   ├── stats.go
│   │   └── update_providers.go
│   ├── commands/
│   │   └── commands.go
│   ├── config/
│   │   ├── agent_id_test.go
│   │   ├── attribution_migration_test.go
│   │   ├── catwalk.go
│   │   ├── catwalk_test.go
│   │   ├── config.go
│   │   ├── copilot.go
│   │   ├── docker_mcp.go
│   │   ├── docker_mcp_test.go
│   │   ├── hyper.go
│   │   ├── hyper_test.go
│   │   ├── init.go
│   │   ├── load.go
│   │   ├── load_bench_test.go
│   │   ├── load_test.go
│   │   ├── lsp_defaults_test.go
│   │   ├── provider.go
│   │   ├── provider_empty_test.go
│   │   ├── provider_test.go
│   │   ├── recent_models_test.go
│   │   ├── resolve.go
│   │   ├── resolve_test.go
│   │   ├── scope.go
│   │   └── store.go
│   ├── csync/
│   │   ├── doc.go
│   │   ├── maps.go
│   │   ├── maps_test.go
│   │   ├── slices.go
│   │   ├── slices_test.go
│   │   ├── value.go
│   │   ├── value_test.go
│   │   ├── versionedmap.go
│   │   └── versionedmap_test.go
│   ├── db/
│   │   ├── connect.go
│   │   ├── connect_modernc.go
│   │   ├── connect_ncruces.go
│   │   ├── db.go
│   │   ├── embed.go
│   │   ├── files.sql.go
│   │   ├── messages.sql.go
│   │   ├── migrations/
│   │   │   ├── 20250424200609_initial.sql
│   │   │   ├── 20250515105448_add_summary_message_id.sql
│   │   │   ├── 20250624000000_add_created_at_indexes.sql
│   │   │   ├── 20250627000000_add_provider_to_messages.sql
│   │   │   ├── 20250810000000_add_is_summary_message.sql
│   │   │   ├── 20250812000000_add_todos_to_sessions.sql
│   │   │   └── 20260127000000_add_read_files_table.sql
│   │   ├── models.go
│   │   ├── querier.go
│   │   ├── read_files.sql.go
│   │   ├── sessions.sql.go
│   │   ├── sql/
│   │   │   ├── files.sql
│   │   │   ├── messages.sql
│   │   │   ├── read_files.sql
│   │   │   ├── sessions.sql
│   │   │   └── stats.sql
│   │   └── stats.sql.go
│   ├── diff/
│   │   └── diff.go
│   ├── env/
│   │   ├── env.go
│   │   └── env_test.go
│   ├── event/
│   │   ├── all.go
│   │   ├── event.go
│   │   ├── event_test.go
│   │   ├── identifier.go
│   │   └── logger.go
│   ├── filepathext/
│   │   └── filepath.go
│   ├── filetracker/
│   │   ├── service.go
│   │   └── service_test.go
│   ├── format/
│   │   └── spinner.go
│   ├── fsext/
│   │   ├── drive_other.go
│   │   ├── drive_windows.go
│   │   ├── expand.go
│   │   ├── fileutil.go
│   │   ├── fileutil_test.go
│   │   ├── ignore_test.go
│   │   ├── lookup.go
│   │   ├── lookup_test.go
│   │   ├── ls.go
│   │   ├── ls_test.go
│   │   ├── owner_others.go
│   │   ├── owner_windows.go
│   │   ├── paste.go
│   │   └── paste_test.go
│   ├── history/
│   │   └── file.go
│   ├── home/
│   │   ├── home.go
│   │   └── home_test.go
│   ├── log/
│   │   ├── http.go
│   │   ├── http_test.go
│   │   └── log.go
│   ├── lsp/
│   │   ├── client.go
│   │   ├── client_test.go
│   │   ├── handlers.go
│   │   ├── manager.go
│   │   └── util/
│   │       ├── edit.go
│   │       └── edit_test.go
│   ├── message/
│   │   ├── attachment.go
│   │   ├── content.go
│   │   ├── content_test.go
│   │   └── message.go
│   ├── oauth/
│   │   ├── copilot/
│   │   │   ├── client.go
│   │   │   ├── disk.go
│   │   │   ├── http.go
│   │   │   ├── oauth.go
│   │   │   └── urls.go
│   │   ├── hyper/
│   │   │   └── device.go
│   │   └── token.go
│   ├── permission/
│   │   ├── permission.go
│   │   └── permission_test.go
│   ├── projects/
│   │   ├── projects.go
│   │   └── projects_test.go
│   ├── pubsub/
│   │   ├── broker.go
│   │   └── events.go
│   ├── session/
│   │   └── session.go
│   ├── shell/
│   │   ├── background.go
│   │   ├── background_test.go
│   │   ├── command_block_test.go
│   │   ├── comparison_test.go
│   │   ├── coreutils.go
│   │   ├── doc.go
│   │   ├── shell.go
│   │   └── shell_test.go
│   ├── skills/
│   │   ├── skills.go
│   │   └── skills_test.go
│   ├── stringext/
│   │   └── string.go
│   ├── ui/
│   │   ├── AGENTS.md
│   │   ├── anim/
│   │   │   └── anim.go
│   │   ├── attachments/
│   │   │   └── attachments.go
│   │   ├── chat/
│   │   │   ├── agent.go
│   │   │   ├── assistant.go
│   │   │   ├── bash.go
│   │   │   ├── diagnostics.go
│   │   │   ├── docker_mcp.go
│   │   │   ├── fetch.go
│   │   │   ├── file.go
│   │   │   ├── generic.go
│   │   │   ├── lsp_restart.go
│   │   │   ├── mcp.go
│   │   │   ├── messages.go
│   │   │   ├── references.go
│   │   │   ├── search.go
│   │   │   ├── todos.go
│   │   │   ├── tools.go
│   │   │   └── user.go
│   │   ├── common/
│   │   │   ├── button.go
│   │   │   ├── capabilities.go
│   │   │   ├── common.go
│   │   │   ├── diff.go
│   │   │   ├── elements.go
│   │   │   ├── highlight.go
│   │   │   ├── interface.go
│   │   │   ├── markdown.go
│   │   │   └── scrollbar.go
│   │   ├── completions/
│   │   │   ├── completions.go
│   │   │   ├── item.go
│   │   │   └── keys.go
│   │   ├── dialog/
│   │   │   ├── actions.go
│   │   │   ├── api_key_input.go
│   │   │   ├── arguments.go
│   │   │   ├── commands.go
│   │   │   ├── commands_item.go
│   │   │   ├── common.go
│   │   │   ├── dialog.go
│   │   │   ├── filepicker.go
│   │   │   ├── models.go
│   │   │   ├── models_item.go
│   │   │   ├── models_list.go
│   │   │   ├── oauth.go
│   │   │   ├── oauth_copilot.go
│   │   │   ├── oauth_hyper.go
│   │   │   ├── permissions.go
│   │   │   ├── quit.go
│   │   │   ├── reasoning.go
│   │   │   ├── sessions.go
│   │   │   └── sessions_item.go
│   │   ├── diffview/
│   │   │   ├── Taskfile.yaml
│   │   │   ├── chroma.go
│   │   │   ├── diffview.go
│   │   │   ├── diffview_test.go
│   │   │   ├── split.go
│   │   │   ├── style.go
│   │   │   ├── testdata/
│   │   │   │   ├── TestDefault.after
│   │   │   │   ├── TestDefault.before
│   │   │   │   ├── TestDiffView/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── CustomContextLines/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── Default/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── LargeWidth/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── MultipleHunks/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── Narrow/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── NoLineNumbers/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   ├── NoSyntaxHighlight/
│   │   │   │   │   │   │   ├── DarkMode.golden
│   │   │   │   │   │   │   └── LightMode.golden
│   │   │   │   │   │   └── SmallWidth/
│   │   │   │   │   │       ├── DarkMode.golden
│   │   │   │   │   │       └── LightMode.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── CustomContextLines/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── Default/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── LargeWidth/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── MultipleHunks/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── Narrow/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── NoLineNumbers/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       ├── NoSyntaxHighlight/
│   │   │   │   │       │   ├── DarkMode.golden
│   │   │   │   │       │   └── LightMode.golden
│   │   │   │   │       └── SmallWidth/
│   │   │   │   │           ├── DarkMode.golden
│   │   │   │   │           └── LightMode.golden
│   │   │   │   ├── TestDiffViewHeight/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── HeightOf001.golden
│   │   │   │   │   │   ├── HeightOf002.golden
│   │   │   │   │   │   ├── HeightOf003.golden
│   │   │   │   │   │   ├── HeightOf004.golden
│   │   │   │   │   │   ├── HeightOf005.golden
│   │   │   │   │   │   ├── HeightOf006.golden
│   │   │   │   │   │   ├── HeightOf007.golden
│   │   │   │   │   │   ├── HeightOf008.golden
│   │   │   │   │   │   ├── HeightOf009.golden
│   │   │   │   │   │   ├── HeightOf010.golden
│   │   │   │   │   │   ├── HeightOf011.golden
│   │   │   │   │   │   ├── HeightOf012.golden
│   │   │   │   │   │   ├── HeightOf013.golden
│   │   │   │   │   │   ├── HeightOf014.golden
│   │   │   │   │   │   ├── HeightOf015.golden
│   │   │   │   │   │   ├── HeightOf016.golden
│   │   │   │   │   │   ├── HeightOf017.golden
│   │   │   │   │   │   ├── HeightOf018.golden
│   │   │   │   │   │   ├── HeightOf019.golden
│   │   │   │   │   │   └── HeightOf020.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── HeightOf001.golden
│   │   │   │   │       ├── HeightOf002.golden
│   │   │   │   │       ├── HeightOf003.golden
│   │   │   │   │       ├── HeightOf004.golden
│   │   │   │   │       ├── HeightOf005.golden
│   │   │   │   │       ├── HeightOf006.golden
│   │   │   │   │       ├── HeightOf007.golden
│   │   │   │   │       ├── HeightOf008.golden
│   │   │   │   │       ├── HeightOf009.golden
│   │   │   │   │       ├── HeightOf010.golden
│   │   │   │   │       ├── HeightOf011.golden
│   │   │   │   │       ├── HeightOf012.golden
│   │   │   │   │       ├── HeightOf013.golden
│   │   │   │   │       ├── HeightOf014.golden
│   │   │   │   │       ├── HeightOf015.golden
│   │   │   │   │       ├── HeightOf016.golden
│   │   │   │   │       ├── HeightOf017.golden
│   │   │   │   │       ├── HeightOf018.golden
│   │   │   │   │       ├── HeightOf019.golden
│   │   │   │   │       └── HeightOf020.golden
│   │   │   │   ├── TestDiffViewLineBreakIssue/
│   │   │   │   │   ├── Split.golden
│   │   │   │   │   └── Unified.golden
│   │   │   │   ├── TestDiffViewTabs/
│   │   │   │   │   ├── Split.golden
│   │   │   │   │   └── Unified.golden
│   │   │   │   ├── TestDiffViewWidth/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── WidthOf001.golden
│   │   │   │   │   │   ├── WidthOf002.golden
│   │   │   │   │   │   ├── WidthOf003.golden
│   │   │   │   │   │   ├── WidthOf004.golden
│   │   │   │   │   │   ├── WidthOf005.golden
│   │   │   │   │   │   ├── WidthOf006.golden
│   │   │   │   │   │   ├── WidthOf007.golden
│   │   │   │   │   │   ├── WidthOf008.golden
│   │   │   │   │   │   ├── WidthOf009.golden
│   │   │   │   │   │   ├── WidthOf010.golden
│   │   │   │   │   │   ├── WidthOf011.golden
│   │   │   │   │   │   ├── WidthOf012.golden
│   │   │   │   │   │   ├── WidthOf013.golden
│   │   │   │   │   │   ├── WidthOf014.golden
│   │   │   │   │   │   ├── WidthOf015.golden
│   │   │   │   │   │   ├── WidthOf016.golden
│   │   │   │   │   │   ├── WidthOf017.golden
│   │   │   │   │   │   ├── WidthOf018.golden
│   │   │   │   │   │   ├── WidthOf019.golden
│   │   │   │   │   │   ├── WidthOf020.golden
│   │   │   │   │   │   ├── WidthOf021.golden
│   │   │   │   │   │   ├── WidthOf022.golden
│   │   │   │   │   │   ├── WidthOf023.golden
│   │   │   │   │   │   ├── WidthOf024.golden
│   │   │   │   │   │   ├── WidthOf025.golden
│   │   │   │   │   │   ├── WidthOf026.golden
│   │   │   │   │   │   ├── WidthOf027.golden
│   │   │   │   │   │   ├── WidthOf028.golden
│   │   │   │   │   │   ├── WidthOf029.golden
│   │   │   │   │   │   ├── WidthOf030.golden
│   │   │   │   │   │   ├── WidthOf031.golden
│   │   │   │   │   │   ├── WidthOf032.golden
│   │   │   │   │   │   ├── WidthOf033.golden
│   │   │   │   │   │   ├── WidthOf034.golden
│   │   │   │   │   │   ├── WidthOf035.golden
│   │   │   │   │   │   ├── WidthOf036.golden
│   │   │   │   │   │   ├── WidthOf037.golden
│   │   │   │   │   │   ├── WidthOf038.golden
│   │   │   │   │   │   ├── WidthOf039.golden
│   │   │   │   │   │   ├── WidthOf040.golden
│   │   │   │   │   │   ├── WidthOf041.golden
│   │   │   │   │   │   ├── WidthOf042.golden
│   │   │   │   │   │   ├── WidthOf043.golden
│   │   │   │   │   │   ├── WidthOf044.golden
│   │   │   │   │   │   ├── WidthOf045.golden
│   │   │   │   │   │   ├── WidthOf046.golden
│   │   │   │   │   │   ├── WidthOf047.golden
│   │   │   │   │   │   ├── WidthOf048.golden
│   │   │   │   │   │   ├── WidthOf049.golden
│   │   │   │   │   │   ├── WidthOf050.golden
│   │   │   │   │   │   ├── WidthOf051.golden
│   │   │   │   │   │   ├── WidthOf052.golden
│   │   │   │   │   │   ├── WidthOf053.golden
│   │   │   │   │   │   ├── WidthOf054.golden
│   │   │   │   │   │   ├── WidthOf055.golden
│   │   │   │   │   │   ├── WidthOf056.golden
│   │   │   │   │   │   ├── WidthOf057.golden
│   │   │   │   │   │   ├── WidthOf058.golden
│   │   │   │   │   │   ├── WidthOf059.golden
│   │   │   │   │   │   ├── WidthOf060.golden
│   │   │   │   │   │   ├── WidthOf061.golden
│   │   │   │   │   │   ├── WidthOf062.golden
│   │   │   │   │   │   ├── WidthOf063.golden
│   │   │   │   │   │   ├── WidthOf064.golden
│   │   │   │   │   │   ├── WidthOf065.golden
│   │   │   │   │   │   ├── WidthOf066.golden
│   │   │   │   │   │   ├── WidthOf067.golden
│   │   │   │   │   │   ├── WidthOf068.golden
│   │   │   │   │   │   ├── WidthOf069.golden
│   │   │   │   │   │   ├── WidthOf070.golden
│   │   │   │   │   │   ├── WidthOf071.golden
│   │   │   │   │   │   ├── WidthOf072.golden
│   │   │   │   │   │   ├── WidthOf073.golden
│   │   │   │   │   │   ├── WidthOf074.golden
│   │   │   │   │   │   ├── WidthOf075.golden
│   │   │   │   │   │   ├── WidthOf076.golden
│   │   │   │   │   │   ├── WidthOf077.golden
│   │   │   │   │   │   ├── WidthOf078.golden
│   │   │   │   │   │   ├── WidthOf079.golden
│   │   │   │   │   │   ├── WidthOf080.golden
│   │   │   │   │   │   ├── WidthOf081.golden
│   │   │   │   │   │   ├── WidthOf082.golden
│   │   │   │   │   │   ├── WidthOf083.golden
│   │   │   │   │   │   ├── WidthOf084.golden
│   │   │   │   │   │   ├── WidthOf085.golden
│   │   │   │   │   │   ├── WidthOf086.golden
│   │   │   │   │   │   ├── WidthOf087.golden
│   │   │   │   │   │   ├── WidthOf088.golden
│   │   │   │   │   │   ├── WidthOf089.golden
│   │   │   │   │   │   ├── WidthOf090.golden
│   │   │   │   │   │   ├── WidthOf091.golden
│   │   │   │   │   │   ├── WidthOf092.golden
│   │   │   │   │   │   ├── WidthOf093.golden
│   │   │   │   │   │   ├── WidthOf094.golden
│   │   │   │   │   │   ├── WidthOf095.golden
│   │   │   │   │   │   ├── WidthOf096.golden
│   │   │   │   │   │   ├── WidthOf097.golden
│   │   │   │   │   │   ├── WidthOf098.golden
│   │   │   │   │   │   ├── WidthOf099.golden
│   │   │   │   │   │   ├── WidthOf100.golden
│   │   │   │   │   │   ├── WidthOf101.golden
│   │   │   │   │   │   ├── WidthOf102.golden
│   │   │   │   │   │   ├── WidthOf103.golden
│   │   │   │   │   │   ├── WidthOf104.golden
│   │   │   │   │   │   ├── WidthOf105.golden
│   │   │   │   │   │   ├── WidthOf106.golden
│   │   │   │   │   │   ├── WidthOf107.golden
│   │   │   │   │   │   ├── WidthOf108.golden
│   │   │   │   │   │   ├── WidthOf109.golden
│   │   │   │   │   │   └── WidthOf110.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── WidthOf001.golden
│   │   │   │   │       ├── WidthOf002.golden
│   │   │   │   │       ├── WidthOf003.golden
│   │   │   │   │       ├── WidthOf004.golden
│   │   │   │   │       ├── WidthOf005.golden
│   │   │   │   │       ├── WidthOf006.golden
│   │   │   │   │       ├── WidthOf007.golden
│   │   │   │   │       ├── WidthOf008.golden
│   │   │   │   │       ├── WidthOf009.golden
│   │   │   │   │       ├── WidthOf010.golden
│   │   │   │   │       ├── WidthOf011.golden
│   │   │   │   │       ├── WidthOf012.golden
│   │   │   │   │       ├── WidthOf013.golden
│   │   │   │   │       ├── WidthOf014.golden
│   │   │   │   │       ├── WidthOf015.golden
│   │   │   │   │       ├── WidthOf016.golden
│   │   │   │   │       ├── WidthOf017.golden
│   │   │   │   │       ├── WidthOf018.golden
│   │   │   │   │       ├── WidthOf019.golden
│   │   │   │   │       ├── WidthOf020.golden
│   │   │   │   │       ├── WidthOf021.golden
│   │   │   │   │       ├── WidthOf022.golden
│   │   │   │   │       ├── WidthOf023.golden
│   │   │   │   │       ├── WidthOf024.golden
│   │   │   │   │       ├── WidthOf025.golden
│   │   │   │   │       ├── WidthOf026.golden
│   │   │   │   │       ├── WidthOf027.golden
│   │   │   │   │       ├── WidthOf028.golden
│   │   │   │   │       ├── WidthOf029.golden
│   │   │   │   │       ├── WidthOf030.golden
│   │   │   │   │       ├── WidthOf031.golden
│   │   │   │   │       ├── WidthOf032.golden
│   │   │   │   │       ├── WidthOf033.golden
│   │   │   │   │       ├── WidthOf034.golden
│   │   │   │   │       ├── WidthOf035.golden
│   │   │   │   │       ├── WidthOf036.golden
│   │   │   │   │       ├── WidthOf037.golden
│   │   │   │   │       ├── WidthOf038.golden
│   │   │   │   │       ├── WidthOf039.golden
│   │   │   │   │       ├── WidthOf040.golden
│   │   │   │   │       ├── WidthOf041.golden
│   │   │   │   │       ├── WidthOf042.golden
│   │   │   │   │       ├── WidthOf043.golden
│   │   │   │   │       ├── WidthOf044.golden
│   │   │   │   │       ├── WidthOf045.golden
│   │   │   │   │       ├── WidthOf046.golden
│   │   │   │   │       ├── WidthOf047.golden
│   │   │   │   │       ├── WidthOf048.golden
│   │   │   │   │       ├── WidthOf049.golden
│   │   │   │   │       ├── WidthOf050.golden
│   │   │   │   │       ├── WidthOf051.golden
│   │   │   │   │       ├── WidthOf052.golden
│   │   │   │   │       ├── WidthOf053.golden
│   │   │   │   │       ├── WidthOf054.golden
│   │   │   │   │       ├── WidthOf055.golden
│   │   │   │   │       ├── WidthOf056.golden
│   │   │   │   │       ├── WidthOf057.golden
│   │   │   │   │       ├── WidthOf058.golden
│   │   │   │   │       ├── WidthOf059.golden
│   │   │   │   │       └── WidthOf060.golden
│   │   │   │   ├── TestDiffViewXOffset/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── XOffsetOf00.golden
│   │   │   │   │   │   ├── XOffsetOf01.golden
│   │   │   │   │   │   ├── XOffsetOf02.golden
│   │   │   │   │   │   ├── XOffsetOf03.golden
│   │   │   │   │   │   ├── XOffsetOf04.golden
│   │   │   │   │   │   ├── XOffsetOf05.golden
│   │   │   │   │   │   ├── XOffsetOf06.golden
│   │   │   │   │   │   ├── XOffsetOf07.golden
│   │   │   │   │   │   ├── XOffsetOf08.golden
│   │   │   │   │   │   ├── XOffsetOf09.golden
│   │   │   │   │   │   ├── XOffsetOf10.golden
│   │   │   │   │   │   ├── XOffsetOf11.golden
│   │   │   │   │   │   ├── XOffsetOf12.golden
│   │   │   │   │   │   ├── XOffsetOf13.golden
│   │   │   │   │   │   ├── XOffsetOf14.golden
│   │   │   │   │   │   ├── XOffsetOf15.golden
│   │   │   │   │   │   ├── XOffsetOf16.golden
│   │   │   │   │   │   ├── XOffsetOf17.golden
│   │   │   │   │   │   ├── XOffsetOf18.golden
│   │   │   │   │   │   ├── XOffsetOf19.golden
│   │   │   │   │   │   └── XOffsetOf20.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── XOffsetOf00.golden
│   │   │   │   │       ├── XOffsetOf01.golden
│   │   │   │   │       ├── XOffsetOf02.golden
│   │   │   │   │       ├── XOffsetOf03.golden
│   │   │   │   │       ├── XOffsetOf04.golden
│   │   │   │   │       ├── XOffsetOf05.golden
│   │   │   │   │       ├── XOffsetOf06.golden
│   │   │   │   │       ├── XOffsetOf07.golden
│   │   │   │   │       ├── XOffsetOf08.golden
│   │   │   │   │       ├── XOffsetOf09.golden
│   │   │   │   │       ├── XOffsetOf10.golden
│   │   │   │   │       ├── XOffsetOf11.golden
│   │   │   │   │       ├── XOffsetOf12.golden
│   │   │   │   │       ├── XOffsetOf13.golden
│   │   │   │   │       ├── XOffsetOf14.golden
│   │   │   │   │       ├── XOffsetOf15.golden
│   │   │   │   │       ├── XOffsetOf16.golden
│   │   │   │   │       ├── XOffsetOf17.golden
│   │   │   │   │       ├── XOffsetOf18.golden
│   │   │   │   │       ├── XOffsetOf19.golden
│   │   │   │   │       └── XOffsetOf20.golden
│   │   │   │   ├── TestDiffViewYOffset/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── YOffsetOf00.golden
│   │   │   │   │   │   ├── YOffsetOf01.golden
│   │   │   │   │   │   ├── YOffsetOf02.golden
│   │   │   │   │   │   ├── YOffsetOf03.golden
│   │   │   │   │   │   ├── YOffsetOf04.golden
│   │   │   │   │   │   ├── YOffsetOf05.golden
│   │   │   │   │   │   ├── YOffsetOf06.golden
│   │   │   │   │   │   ├── YOffsetOf07.golden
│   │   │   │   │   │   ├── YOffsetOf08.golden
│   │   │   │   │   │   ├── YOffsetOf09.golden
│   │   │   │   │   │   ├── YOffsetOf10.golden
│   │   │   │   │   │   ├── YOffsetOf11.golden
│   │   │   │   │   │   ├── YOffsetOf12.golden
│   │   │   │   │   │   ├── YOffsetOf13.golden
│   │   │   │   │   │   ├── YOffsetOf14.golden
│   │   │   │   │   │   ├── YOffsetOf15.golden
│   │   │   │   │   │   └── YOffsetOf16.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── YOffsetOf00.golden
│   │   │   │   │       ├── YOffsetOf01.golden
│   │   │   │   │       ├── YOffsetOf02.golden
│   │   │   │   │       ├── YOffsetOf03.golden
│   │   │   │   │       ├── YOffsetOf04.golden
│   │   │   │   │       ├── YOffsetOf05.golden
│   │   │   │   │       ├── YOffsetOf06.golden
│   │   │   │   │       ├── YOffsetOf07.golden
│   │   │   │   │       ├── YOffsetOf08.golden
│   │   │   │   │       ├── YOffsetOf09.golden
│   │   │   │   │       ├── YOffsetOf10.golden
│   │   │   │   │       ├── YOffsetOf11.golden
│   │   │   │   │       ├── YOffsetOf12.golden
│   │   │   │   │       ├── YOffsetOf13.golden
│   │   │   │   │       ├── YOffsetOf14.golden
│   │   │   │   │       ├── YOffsetOf15.golden
│   │   │   │   │       └── YOffsetOf16.golden
│   │   │   │   ├── TestDiffViewYOffsetInfinite/
│   │   │   │   │   ├── Split/
│   │   │   │   │   │   ├── YOffsetOf00.golden
│   │   │   │   │   │   ├── YOffsetOf01.golden
│   │   │   │   │   │   ├── YOffsetOf02.golden
│   │   │   │   │   │   ├── YOffsetOf03.golden
│   │   │   │   │   │   ├── YOffsetOf04.golden
│   │   │   │   │   │   ├── YOffsetOf05.golden
│   │   │   │   │   │   ├── YOffsetOf06.golden
│   │   │   │   │   │   ├── YOffsetOf07.golden
│   │   │   │   │   │   ├── YOffsetOf08.golden
│   │   │   │   │   │   ├── YOffsetOf09.golden
│   │   │   │   │   │   ├── YOffsetOf10.golden
│   │   │   │   │   │   ├── YOffsetOf11.golden
│   │   │   │   │   │   ├── YOffsetOf12.golden
│   │   │   │   │   │   ├── YOffsetOf13.golden
│   │   │   │   │   │   ├── YOffsetOf14.golden
│   │   │   │   │   │   ├── YOffsetOf15.golden
│   │   │   │   │   │   └── YOffsetOf16.golden
│   │   │   │   │   └── Unified/
│   │   │   │   │       ├── YOffsetOf00.golden
│   │   │   │   │       ├── YOffsetOf01.golden
│   │   │   │   │       ├── YOffsetOf02.golden
│   │   │   │   │       ├── YOffsetOf03.golden
│   │   │   │   │       ├── YOffsetOf04.golden
│   │   │   │   │       ├── YOffsetOf05.golden
│   │   │   │   │       ├── YOffsetOf06.golden
│   │   │   │   │       ├── YOffsetOf07.golden
│   │   │   │   │       ├── YOffsetOf08.golden
│   │   │   │   │       ├── YOffsetOf09.golden
│   │   │   │   │       ├── YOffsetOf10.golden
│   │   │   │   │       ├── YOffsetOf11.golden
│   │   │   │   │       ├── YOffsetOf12.golden
│   │   │   │   │       ├── YOffsetOf13.golden
│   │   │   │   │       ├── YOffsetOf14.golden
│   │   │   │   │       ├── YOffsetOf15.golden
│   │   │   │   │       └── YOffsetOf16.golden
│   │   │   │   ├── TestLineBreakIssue.after
│   │   │   │   ├── TestLineBreakIssue.before
│   │   │   │   ├── TestMultipleHunks.after
│   │   │   │   ├── TestMultipleHunks.before
│   │   │   │   ├── TestNarrow.after
│   │   │   │   ├── TestNarrow.before
│   │   │   │   ├── TestTabs.after
│   │   │   │   ├── TestTabs.before
│   │   │   │   └── TestUdiff/
│   │   │   │       ├── ToUnifiedDiff/
│   │   │   │       │   ├── DefaultContextLines/
│   │   │   │       │   │   ├── Content.golden
│   │   │   │       │   │   └── JSON.golden
│   │   │   │       │   ├── DefaultContextLinesPlusOne/
│   │   │   │       │   │   ├── Content.golden
│   │   │   │       │   │   └── JSON.golden
│   │   │   │       │   └── DefaultContextLinesPlusTwo/
│   │   │   │       │       ├── Content.golden
│   │   │   │       │       └── JSON.golden
│   │   │   │       └── Unified.golden
│   │   │   ├── udiff_test.go
│   │   │   ├── util.go
│   │   │   └── util_test.go
│   │   ├── image/
│   │   │   ├── image.go
│   │   │   └── image_test.go
│   │   ├── list/
│   │   │   ├── filterable.go
│   │   │   ├── focus.go
│   │   │   ├── highlight.go
│   │   │   ├── item.go
│   │   │   └── list.go
│   │   ├── logo/
│   │   │   ├── logo.go
│   │   │   └── rand.go
│   │   ├── model/
│   │   │   ├── chat.go
│   │   │   ├── clipboard.go
│   │   │   ├── clipboard_not_supported.go
│   │   │   ├── clipboard_supported.go
│   │   │   ├── filter.go
│   │   │   ├── header.go
│   │   │   ├── history.go
│   │   │   ├── keys.go
│   │   │   ├── landing.go
│   │   │   ├── lsp.go
│   │   │   ├── mcp.go
│   │   │   ├── onboarding.go
│   │   │   ├── pills.go
│   │   │   ├── session.go
│   │   │   ├── sidebar.go
│   │   │   ├── status.go
│   │   │   └── ui.go
│   │   ├── notification/
│   │   │   ├── icon_darwin.go
│   │   │   ├── icon_other.go
│   │   │   ├── native.go
│   │   │   ├── noop.go
│   │   │   ├── notification.go
│   │   │   └── notification_test.go
│   │   ├── styles/
│   │   │   ├── grad.go
│   │   │   └── styles.go
│   │   └── util/
│   │       └── util.go
│   ├── update/
│   │   ├── update.go
│   │   └── update_test.go
│   └── version/
│       └── version.go
├── main.go
├── schema.json
├── scripts/
│   ├── check_log_capitalization.sh
│   └── run-labeler.sh
└── sqlc.yaml
Download .txt
Showing preview only (255K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2878 symbols across 279 files)

FILE: internal/agent/agent.go
  constant DefaultSessionName (line 50) | DefaultSessionName = "Untitled Session"
  constant largeContextWindowThreshold (line 53) | largeContextWindowThreshold = 200_000
  constant largeContextWindowBuffer (line 54) | largeContextWindowBuffer    = 20_000
  constant smallContextWindowRatio (line 55) | smallContextWindowRatio     = 0.2
  type SessionAgentCall (line 69) | type SessionAgentCall struct
  type SessionAgent (line 83) | type SessionAgent interface
  type Model (line 99) | type Model struct
  type sessionAgent (line 105) | type sessionAgent struct
    method Run (line 157) | func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall)...
    method Summarize (line 587) | func (a *sessionAgent) Summarize(ctx context.Context, sessionID string...
    method getCacheControlOptions (line 701) | func (a *sessionAgent) getCacheControlOptions() fantasy.ProviderOptions {
    method createUserMessage (line 718) | func (a *sessionAgent) createUserMessage(ctx context.Context, call Ses...
    method preparePrompt (line 735) | func (a *sessionAgent) preparePrompt(msgs []message.Message, attachmen...
    method getSessionMessages (line 773) | func (a *sessionAgent) getSessionMessages(ctx context.Context, session...
    method generateTitle (line 796) | func (a *sessionAgent) generateTitle(ctx context.Context, sessionID st...
    method openrouterCost (line 915) | func (a *sessionAgent) openrouterCost(metadata fantasy.ProviderMetadat...
    method updateSessionUsage (line 928) | func (a *sessionAgent) updateSessionUsage(model Model, session *sessio...
    method Cancel (line 947) | func (a *sessionAgent) Cancel(sessionID string) {
    method ClearQueue (line 969) | func (a *sessionAgent) ClearQueue(sessionID string) {
    method CancelAll (line 976) | func (a *sessionAgent) CancelAll() {
    method IsBusy (line 995) | func (a *sessionAgent) IsBusy() bool {
    method IsSessionBusy (line 1006) | func (a *sessionAgent) IsSessionBusy(sessionID string) bool {
    method QueuedPrompts (line 1011) | func (a *sessionAgent) QueuedPrompts(sessionID string) int {
    method QueuedPromptsList (line 1019) | func (a *sessionAgent) QueuedPromptsList(sessionID string) []string {
    method SetModels (line 1031) | func (a *sessionAgent) SetModels(large Model, small Model) {
    method SetTools (line 1036) | func (a *sessionAgent) SetTools(tools []fantasy.AgentTool) {
    method SetSystemPrompt (line 1040) | func (a *sessionAgent) SetSystemPrompt(systemPrompt string) {
    method Model (line 1044) | func (a *sessionAgent) Model() Model {
    method convertToToolResult (line 1049) | func (a *sessionAgent) convertToToolResult(result fantasy.ToolResultCo...
    method workaroundProviderMediaLimitations (line 1102) | func (a *sessionAgent) workaroundProviderMediaLimitations(messages []f...
  type SessionAgentOptions (line 123) | type SessionAgentOptions struct
  function NewSessionAgent (line 137) | func NewSessionAgent(
  function buildSummaryPrompt (line 1171) | func buildSummaryPrompt(todos []session.Todo) string {

FILE: internal/agent/agent_test.go
  function getModels (line 29) | func getModels(t *testing.T, r *vcr.Recorder, pair modelPair) (fantasy.L...
  function setupAgent (line 37) | func setupAgent(t *testing.T, pair modelPair) (SessionAgent, fakeEnv) {
  function TestCoderAgent (line 48) | func TestCoderAgent(t *testing.T) {
  function makeTestTodos (line 621) | func makeTestTodos(n int) []session.Todo {
  function BenchmarkBuildSummaryPrompt (line 632) | func BenchmarkBuildSummaryPrompt(b *testing.B) {

FILE: internal/agent/agent_tool.go
  type AgentParams (line 18) | type AgentParams struct
  constant AgentToolName (line 23) | AgentToolName = "agent"
  method agentTool (line 26) | func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool,...

FILE: internal/agent/agentic_fetch_tool.go
  type agenticFetchValidationResult (line 23) | type agenticFetchValidationResult struct
  function validateAgenticFetchParams (line 29) | func validateAgenticFetchParams(ctx context.Context, params tools.Agenti...
  method agenticFetchTool (line 53) | func (c *coordinator) agenticFetchTool(_ context.Context, client *http.C...

FILE: internal/agent/common_test.go
  type fakeEnv (line 35) | type fakeEnv struct
  type builderFunc (line 45) | type builderFunc
  type modelPair (line 47) | type modelPair struct
  function anthropicBuilder (line 53) | func anthropicBuilder(model string) builderFunc {
  function openaiBuilder (line 66) | func openaiBuilder(model string) builderFunc {
  function openRouterBuilder (line 79) | func openRouterBuilder(model string) builderFunc {
  function zAIBuilder (line 92) | func zAIBuilder(model string) builderFunc {
  function testEnv (line 106) | func testEnv(t *testing.T) fakeEnv {
  function testSessionAgent (line 141) | func testSessionAgent(env fakeEnv, large, small fantasy.LanguageModel, s...
  function coderAgent (line 168) | func coderAgent(r *vcr.Recorder, env fakeEnv, large, small fantasy.Langu...
  function createSimpleGoProject (line 228) | func createSimpleGoProject(t *testing.T, dir string) {

FILE: internal/agent/coordinator.go
  type Coordinator (line 60) | type Coordinator interface
  type coordinator (line 76) | type coordinator struct
    method Run (line 136) | func (c *coordinator) Run(ctx context.Context, sessionID string, promp...
    method buildAgent (line 380) | func (c *coordinator) buildAgent(ctx context.Context, prompt *prompt.P...
    method buildTools (line 422) | func (c *coordinator) buildTools(ctx context.Context, agent config.Age...
    method buildAgentModels (line 515) | func (c *coordinator) buildAgentModels(ctx context.Context, isSubAgent...
    method buildAnthropicProvider (line 598) | func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, h...
    method buildOpenaiProvider (line 630) | func (c *coordinator) buildOpenaiProvider(baseURL, apiKey string, head...
    method buildOpenrouterProvider (line 648) | func (c *coordinator) buildOpenrouterProvider(_, apiKey string, header...
    method buildVercelProvider (line 662) | func (c *coordinator) buildVercelProvider(_, apiKey string, headers ma...
    method buildOpenaiCompatProvider (line 676) | func (c *coordinator) buildOpenaiCompatProvider(baseURL, apiKey string...
    method buildAzureProvider (line 705) | func (c *coordinator) buildAzureProvider(baseURL, apiKey string, heade...
    method buildBedrockProvider (line 728) | func (c *coordinator) buildBedrockProvider(apiKey string, headers map[...
    method buildGoogleProvider (line 748) | func (c *coordinator) buildGoogleProvider(baseURL, apiKey string, head...
    method buildGoogleVertexProvider (line 763) | func (c *coordinator) buildGoogleVertexProvider(headers map[string]str...
    method buildHyperProvider (line 781) | func (c *coordinator) buildHyperProvider(baseURL, apiKey string) (fant...
    method isAnthropicThinking (line 793) | func (c *coordinator) isAnthropicThinking(model config.SelectedModel) ...
    method buildProvider (line 801) | func (c *coordinator) buildProvider(providerCfg config.ProviderConfig,...
    method Cancel (line 862) | func (c *coordinator) Cancel(sessionID string) {
    method CancelAll (line 866) | func (c *coordinator) CancelAll() {
    method ClearQueue (line 870) | func (c *coordinator) ClearQueue(sessionID string) {
    method IsBusy (line 874) | func (c *coordinator) IsBusy() bool {
    method IsSessionBusy (line 878) | func (c *coordinator) IsSessionBusy(sessionID string) bool {
    method Model (line 882) | func (c *coordinator) Model() Model {
    method UpdateModels (line 886) | func (c *coordinator) UpdateModels(ctx context.Context) error {
    method QueuedPrompts (line 907) | func (c *coordinator) QueuedPrompts(sessionID string) int {
    method QueuedPromptsList (line 911) | func (c *coordinator) QueuedPromptsList(sessionID string) []string {
    method Summarize (line 915) | func (c *coordinator) Summarize(ctx context.Context, sessionID string)...
    method isUnauthorized (line 923) | func (c *coordinator) isUnauthorized(err error) bool {
    method refreshOAuth2Token (line 928) | func (c *coordinator) refreshOAuth2Token(ctx context.Context, provider...
    method refreshApiKeyTemplate (line 939) | func (c *coordinator) refreshApiKeyTemplate(ctx context.Context, provi...
    method runSubAgent (line 971) | func (c *coordinator) runSubAgent(ctx context.Context, params subAgent...
    method updateParentSessionCost (line 1022) | func (c *coordinator) updateParentSessionCost(ctx context.Context, chi...
  function NewCoordinator (line 92) | func NewCoordinator(
  function getProviderOptions (line 215) | func getProviderOptions(model Model, providerCfg config.ProviderConfig) ...
  function mergeCallOptions (line 370) | func mergeCallOptions(model Model, cfg config.ProviderConfig) (fantasy.P...
  function isExactoSupported (line 851) | func isExactoSupported(modelID string) bool {
  type subAgentParams (line 956) | type subAgentParams struct

FILE: internal/agent/coordinator_test.go
  type mockSessionAgent (line 16) | type mockSessionAgent struct
    method Run (line 22) | func (m *mockSessionAgent) Run(ctx context.Context, call SessionAgentC...
    method Model (line 26) | func (m *mockSessionAgent) Model() Model                        { retu...
    method SetModels (line 27) | func (m *mockSessionAgent) SetModels(large, small Model)        {}
    method SetTools (line 28) | func (m *mockSessionAgent) SetTools(tools []fantasy.AgentTool)  {}
    method SetSystemPrompt (line 29) | func (m *mockSessionAgent) SetSystemPrompt(systemPrompt string) {}
    method Cancel (line 30) | func (m *mockSessionAgent) Cancel(sessionID string) {
    method CancelAll (line 33) | func (m *mockSessionAgent) CancelAll()                                ...
    method IsSessionBusy (line 34) | func (m *mockSessionAgent) IsSessionBusy(sessionID string) bool       ...
    method IsBusy (line 35) | func (m *mockSessionAgent) IsBusy() bool                              ...
    method QueuedPrompts (line 36) | func (m *mockSessionAgent) QueuedPrompts(sessionID string) int        ...
    method QueuedPromptsList (line 37) | func (m *mockSessionAgent) QueuedPromptsList(sessionID string) []strin...
    method ClearQueue (line 38) | func (m *mockSessionAgent) ClearQueue(sessionID string)               ...
    method Summarize (line 39) | func (m *mockSessionAgent) Summarize(context.Context, string, fantasy....
  function newTestCoordinator (line 44) | func newTestCoordinator(t *testing.T, env fakeEnv, providerID string, pr...
  function newMockAgent (line 55) | func newMockAgent(providerID string, maxTokens int64, runFunc func(conte...
  function agentResultWithText (line 70) | func agentResultWithText(text string) *fantasy.AgentResult {
  function TestRunSubAgent (line 80) | func TestRunSubAgent(t *testing.T) {
  function TestUpdateParentSessionCost (line 280) | func TestUpdateParentSessionCost(t *testing.T) {

FILE: internal/agent/event.go
  method eventPromptSent (line 10) | func (a *sessionAgent) eventPromptSent(sessionID string) {
  method eventPromptResponded (line 16) | func (a *sessionAgent) eventPromptResponded(sessionID string, duration t...
  method eventTokensUsed (line 26) | func (a *sessionAgent) eventTokensUsed(sessionID string, model Model, us...
  method eventCommon (line 40) | func (a *sessionAgent) eventCommon(sessionID string, model Model) []any {

FILE: internal/agent/hyper/provider.go
  constant Name (line 62) | Name = "hyper"
  constant defaultBaseURL (line 64) | defaultBaseURL = "https://hyper.charm.land"
  type options (line 74) | type options struct
  function New (line 86) | func New(opts ...Option) (fantasy.Provider, error) {
  function WithBaseURL (line 102) | func WithBaseURL(url string) Option { return func(o *options) { o.baseUR...
  function WithName (line 105) | func WithName(name string) Option { return func(o *options) { o.name = n...
  function WithHeaders (line 108) | func WithHeaders(headers map[string]string) Option {
  function WithHTTPClient (line 115) | func WithHTTPClient(c *http.Client) Option { return func(o *options) { o...
  function WithAPIKey (line 118) | func WithAPIKey(key string) Option {
  type provider (line 124) | type provider struct
    method Name (line 126) | func (p *provider) Name() string { return p.options.name }
    method LanguageModel (line 129) | func (p *provider) LanguageModel(_ context.Context, modelID string) (f...
  type languageModel (line 136) | type languageModel struct
    method GenerateObject (line 143) | func (m *languageModel) GenerateObject(ctx context.Context, call fanta...
    method StreamObject (line 148) | func (m *languageModel) StreamObject(ctx context.Context, call fantasy...
    method Provider (line 152) | func (m *languageModel) Provider() string { return m.provider }
    method Model (line 153) | func (m *languageModel) Model() string    { return m.modelID }
    method Generate (line 156) | func (m *languageModel) Generate(ctx context.Context, call fantasy.Cal...
    method Stream (line 174) | func (m *languageModel) Stream(ctx context.Context, call fantasy.Call)...
    method doRequest (line 275) | func (m *languageModel) doRequest(ctx context.Context, stream bool, ca...
  function ioReadAllLimit (line 313) | func ioReadAllLimit(r io.Reader, n int64) ([]byte, error) {
  function toProviderError (line 323) | func toProviderError(resp *http.Response, message string) error {
  function retryAfter (line 331) | func retryAfter(resp *http.Response) string {

FILE: internal/agent/loop_detection.go
  constant loopDetectionWindowSize (line 12) | loopDetectionWindowSize = 10
  constant loopDetectionMaxRepeats (line 13) | loopDetectionMaxRepeats = 5
  function hasRepeatedToolCalls (line 19) | func hasRepeatedToolCalls(steps []fantasy.StepResult, windowSize, maxRep...
  function getToolInteractionSignature (line 45) | func getToolInteractionSignature(content fantasy.ResponseContent) string {
  function toolResultOutputString (line 75) | func toolResultOutputString(result fantasy.ToolResultOutputContent) stri...

FILE: internal/agent/loop_detection_test.go
  function makeStep (line 11) | func makeStep(calls []fantasy.ToolCallContent, results []fantasy.ToolRes...
  function makeToolStep (line 27) | func makeToolStep(name, input, output string) fantasy.StepResult {
  function makeEmptyStep (line 40) | func makeEmptyStep() fantasy.StepResult {
  function TestHasRepeatedToolCalls (line 50) | func TestHasRepeatedToolCalls(t *testing.T) {
  function TestGetToolInteractionSignature (line 145) | func TestGetToolInteractionSignature(t *testing.T) {

FILE: internal/agent/notify/notify.go
  type Type (line 7) | type Type
  constant TypeAgentFinished (line 11) | TypeAgentFinished Type = "agent_finished"
  type Notification (line 15) | type Notification struct

FILE: internal/agent/prompt/prompt.go
  type Prompt (line 21) | type Prompt struct
    method Build (line 79) | func (p *Prompt) Build(ctx context.Context, provider, model string, st...
    method promptData (line 151) | func (p *Prompt) promptData(ctx context.Context, provider, model strin...
    method Name (line 262) | func (p *Prompt) Name() string {
  type PromptDat (line 29) | type PromptDat struct
  type ContextFile (line 42) | type ContextFile struct
  type Option (line 47) | type Option
  function WithTimeFunc (line 49) | func WithTimeFunc(fn func() time.Time) Option {
  function WithPlatform (line 55) | func WithPlatform(platform string) Option {
  function WithWorkingDir (line 61) | func WithWorkingDir(workingDir string) Option {
  function NewPrompt (line 67) | func NewPrompt(name, promptTemplate string, opts ...Option) (*Prompt, er...
  function processFile (line 96) | func processFile(filePath string) *ContextFile {
  function processContextPath (line 107) | func processContextPath(p string, store *config.ConfigStore) []ContextFi...
  function expandPath (line 139) | func expandPath(path string, store *config.ConfigStore) string {
  function isGitRepo (line 205) | func isGitRepo(dir string) bool {
  function getGitStatus (line 210) | func getGitStatus(ctx context.Context, dir string) (string, error) {
  function getGitBranch (line 229) | func getGitBranch(ctx context.Context, sh *shell.Shell) (string, error) {
  function getGitStatusSummary (line 241) | func getGitStatusSummary(ctx context.Context, sh *shell.Shell) (string, ...
  function getGitRecentCommits (line 253) | func getGitRecentCommits(ctx context.Context, sh *shell.Shell) (string, ...

FILE: internal/agent/prompts.go
  function coderPrompt (line 20) | func coderPrompt(opts ...prompt.Option) (*prompt.Prompt, error) {
  function taskPrompt (line 28) | func taskPrompt(opts ...prompt.Option) (*prompt.Prompt, error) {
  function InitializePrompt (line 36) | func InitializePrompt(cfg *config.ConfigStore) (string, error) {

FILE: internal/agent/tools/bash.go
  type BashParams (line 22) | type BashParams struct
  type BashPermissionsParams (line 30) | type BashPermissionsParams struct
  type BashResponseMetadata (line 38) | type BashResponseMetadata struct
  constant BashToolName (line 49) | BashToolName = "bash"
  constant DefaultAutoBackgroundAfter (line 51) | DefaultAutoBackgroundAfter = 60
  constant MaxOutputLength (line 52) | MaxOutputLength            = 30000
  constant BashNoOutput (line 53) | BashNoOutput               = "no output"
  type bashDescriptionData (line 64) | type bashDescriptionData struct
  function bashDescription (line 144) | func bashDescription(attribution *config.Attribution, modelName string) ...
  function blockFuncs (line 159) | func blockFuncs() []shell.BlockFunc {
  function NewBashTool (line 191) | func NewBashTool(permissions permission.Service, workingDir string, attr...
  function formatOutput (line 380) | func formatOutput(stdout, stderr string, execErr error) string {
  function truncateOutput (line 417) | func truncateOutput(content string) string {
  function countLines (line 430) | func countLines(s string) int {
  function normalizeWorkingDir (line 437) | func normalizeWorkingDir(path string) string {

FILE: internal/agent/tools/bash_test.go
  type mockBashPermissionService (line 16) | type mockBashPermissionService struct
    method Request (line 20) | func (m *mockBashPermissionService) Request(ctx context.Context, req p...
    method Grant (line 24) | func (m *mockBashPermissionService) Grant(req permission.PermissionReq...
    method Deny (line 26) | func (m *mockBashPermissionService) Deny(req permission.PermissionRequ...
    method GrantPersistent (line 28) | func (m *mockBashPermissionService) GrantPersistent(req permission.Per...
    method AutoApproveSession (line 30) | func (m *mockBashPermissionService) AutoApproveSession(sessionID strin...
    method SetSkipRequests (line 32) | func (m *mockBashPermissionService) SetSkipRequests(skip bool) {}
    method SkipRequests (line 34) | func (m *mockBashPermissionService) SkipRequests() bool {
    method SubscribeNotifications (line 38) | func (m *mockBashPermissionService) SubscribeNotifications(ctx context...
  function TestBashTool_DefaultAutoBackgroundThreshold (line 42) | func TestBashTool_DefaultAutoBackgroundThreshold(t *testing.T) {
  function TestBashTool_CustomAutoBackgroundThreshold (line 60) | func TestBashTool_CustomAutoBackgroundThreshold(t *testing.T) {
  function newBashToolForTest (line 82) | func newBashToolForTest(workingDir string) fantasy.AgentTool {
  function runBashTool (line 88) | func runBashTool(t *testing.T, tool fantasy.AgentTool, ctx context.Conte...

FILE: internal/agent/tools/context_test.go
  type testStringKey (line 10) | type testStringKey
  type testBoolKey (line 11) | type testBoolKey
  type testIntKey (line 12) | type testIntKey
  constant testKey (line 16) | testKey     testStringKey = "testKey"
  constant missingKey (line 17) | missingKey  testStringKey = "missingKey"
  constant boolTestKey (line 18) | boolTestKey testBoolKey   = "boolKey"
  constant intTestKey (line 19) | intTestKey  testIntKey    = "intKey"
  function TestGetContextValue (line 22) | func TestGetContextValue(t *testing.T) {
  function TestGetSessionFromContext (line 98) | func TestGetSessionFromContext(t *testing.T) {
  function TestGetMessageFromContext (line 131) | func TestGetMessageFromContext(t *testing.T) {
  function TestGetSupportsImagesFromContext (line 164) | func TestGetSupportsImagesFromContext(t *testing.T) {
  function TestGetModelNameFromContext (line 202) | func TestGetModelNameFromContext(t *testing.T) {

FILE: internal/agent/tools/diagnostics.go
  type DiagnosticsParams (line 18) | type DiagnosticsParams struct
  constant DiagnosticsToolName (line 22) | DiagnosticsToolName = "lsp_diagnostics"
  function NewDiagnosticsTool (line 27) | func NewDiagnosticsTool(lspManager *lsp.Manager) fantasy.AgentTool {
  function openInLSPs (line 44) | func openInLSPs(
  function waitForLSPDiagnostics (line 66) | func waitForLSPDiagnostics(
  function notifyLSPs (line 90) | func notifyLSPs(
  function getDiagnostics (line 111) | func getDiagnostics(filePath string, manager *lsp.Manager) string {
  function writeDiagnostics (line 161) | func writeDiagnostics(output *strings.Builder, tag string, in []string) {
  function sortDiagnostics (line 175) | func sortDiagnostics(in []string) []string {
  function formatDiagnostic (line 187) | func formatDiagnostic(pth string, diagnostic protocol.Diagnostic, source...
  function countSeverity (line 235) | func countSeverity(diagnostics []string, severity string) int {

FILE: internal/agent/tools/download.go
  type DownloadParams (line 20) | type DownloadParams struct
  type DownloadPermissionsParams (line 26) | type DownloadPermissionsParams struct
  constant DownloadToolName (line 32) | DownloadToolName = "download"
  function NewDownloadTool (line 37) | func NewDownloadTool(permissions permission.Service, workingDir string, ...

FILE: internal/agent/tools/edit.go
  type EditParams (line 24) | type EditParams struct
  type EditPermissionsParams (line 31) | type EditPermissionsParams struct
  type EditResponseMetadata (line 37) | type EditResponseMetadata struct
  constant EditToolName (line 44) | EditToolName = "edit"
  type editContext (line 54) | type editContext struct
  function NewEditTool (line 62) | func NewEditTool(
  function createNewFile (line 110) | func createNewFile(edit editContext, filePath, content string, call fant...
  function deleteContent (line 190) | func deleteContent(edit editContext, filePath, oldString string, replace...
  function replaceContent (line 321) | func replaceContent(edit editContext, filePath, oldString, newString str...

FILE: internal/agent/tools/fetch.go
  constant FetchToolName (line 19) | FetchToolName = "fetch"
  function NewFetchTool (line 24) | func NewFetchTool(permissions permission.Service, workingDir string, cli...
  function extractTextFromHTML (line 173) | func extractTextFromHTML(html string) (string, error) {
  function convertHTMLToMarkdown (line 185) | func convertHTMLToMarkdown(html string) (string, error) {

FILE: internal/agent/tools/fetch_helpers.go
  constant BrowserUserAgent (line 20) | BrowserUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKi...
  function FetchURLAndConvert (line 25) | func FetchURLAndConvert(ctx context.Context, client *http.Client, url st...
  function removeNoisyElements (line 83) | func removeNoisyElements(htmlContent string) string {
  function cleanupMarkdown (line 131) | func cleanupMarkdown(content string) string {
  function ConvertHTMLToMarkdown (line 149) | func ConvertHTMLToMarkdown(htmlContent string) (string, error) {
  function FormatJSON (line 161) | func FormatJSON(content string) (string, error) {

FILE: internal/agent/tools/fetch_types.go
  constant AgenticFetchToolName (line 4) | AgenticFetchToolName = "agentic_fetch"
  constant WebFetchToolName (line 7) | WebFetchToolName = "web_fetch"
  constant WebSearchToolName (line 10) | WebSearchToolName = "web_search"
  constant LargeContentThreshold (line 13) | LargeContentThreshold = 50000
  type AgenticFetchParams (line 16) | type AgenticFetchParams struct
  type AgenticFetchPermissionsParams (line 22) | type AgenticFetchPermissionsParams struct
  type WebFetchParams (line 28) | type WebFetchParams struct
  type WebSearchParams (line 33) | type WebSearchParams struct
  type FetchParams (line 39) | type FetchParams struct
  type FetchPermissionsParams (line 46) | type FetchPermissionsParams struct

FILE: internal/agent/tools/glob.go
  constant GlobToolName (line 19) | GlobToolName = "glob"
  type GlobParams (line 24) | type GlobParams struct
  type GlobResponseMetadata (line 29) | type GlobResponseMetadata struct
  function NewGlobTool (line 34) | func NewGlobTool(workingDir string) fantasy.AgentTool {
  function globFiles (line 71) | func globFiles(ctx context.Context, pattern, searchPath string, limit in...
  function runRipgrep (line 85) | func runRipgrep(cmd *exec.Cmd, searchRoot string, limit int) ([]string, ...
  function normalizeFilePaths (line 119) | func normalizeFilePaths(paths []string) {

FILE: internal/agent/tools/grep.go
  type regexCache (line 28) | type regexCache struct
    method get (line 40) | func (rc *regexCache) get(pattern string) (*regexp.Regexp, error) {
  function newRegexCache (line 33) | func newRegexCache() *regexCache {
  function ResetCache (line 52) | func ResetCache() {
  type GrepParams (line 65) | type GrepParams struct
  type grepMatch (line 72) | type grepMatch struct
  type GrepResponseMetadata (line 80) | type GrepResponseMetadata struct
  constant GrepToolName (line 86) | GrepToolName        = "grep"
  constant maxGrepContentWidth (line 87) | maxGrepContentWidth = 500
  function escapeRegexPattern (line 94) | func escapeRegexPattern(pattern string) string {
  function NewGrepTool (line 105) | func NewGrepTool(workingDir string, config config.ToolGrep) fantasy.Agen...
  function searchFiles (line 174) | func searchFiles(ctx context.Context, pattern, rootPath, include string,...
  function searchWithRipgrep (line 195) | func searchWithRipgrep(ctx context.Context, pattern, path, include strin...
  type ripgrepMatch (line 248) | type ripgrepMatch struct
  function searchFilesWithRegex (line 264) | func searchFilesWithRegex(pattern, rootPath, include string) ([]grepMatc...
  function fileContainsPattern (line 341) | func fileContainsPattern(filePath string, pattern *regexp.Regexp) (bool,...
  function isTextFile (line 368) | func isTextFile(filePath string) bool {
  function globToRegex (line 393) | func globToRegex(glob string) string {

FILE: internal/agent/tools/grep_test.go
  function TestRegexCache (line 12) | func TestRegexCache(t *testing.T) {
  function TestGlobToRegexCaching (line 38) | func TestGlobToRegexCaching(t *testing.T) {
  function TestGrepWithIgnoreFiles (line 59) | func TestGrepWithIgnoreFiles(t *testing.T) {
  function TestSearchImplementations (line 124) | func TestSearchImplementations(t *testing.T) {
  function BenchmarkRegexCacheVsCompile (line 179) | func BenchmarkRegexCacheVsCompile(b *testing.B) {
  function TestIsTextFile (line 202) | func TestIsTextFile(t *testing.T) {
  function TestColumnMatch (line 394) | func TestColumnMatch(t *testing.T) {

FILE: internal/agent/tools/job_kill.go
  constant JobKillToolName (line 13) | JobKillToolName = "job_kill"
  type JobKillParams (line 19) | type JobKillParams struct
  type JobKillResponseMetadata (line 23) | type JobKillResponseMetadata struct
  function NewJobKillTool (line 29) | func NewJobKillTool() fantasy.AgentTool {

FILE: internal/agent/tools/job_output.go
  constant JobOutputToolName (line 14) | JobOutputToolName = "job_output"
  type JobOutputParams (line 20) | type JobOutputParams struct
  type JobOutputResponseMetadata (line 25) | type JobOutputResponseMetadata struct
  function NewJobOutputTool (line 33) | func NewJobOutputTool() fantasy.AgentTool {

FILE: internal/agent/tools/job_test.go
  function TestBackgroundShell_Integration (line 13) | func TestBackgroundShell_Integration(t *testing.T) {
  function TestBackgroundShell_Kill (line 40) | func TestBackgroundShell_Kill(t *testing.T) {
  function TestBackgroundShell_MultipleOutputCalls (line 63) | func TestBackgroundShell_MultipleOutputCalls(t *testing.T) {
  function TestBackgroundShell_EmptyOutput (line 99) | func TestBackgroundShell_EmptyOutput(t *testing.T) {
  function TestBackgroundShell_ExitCode (line 125) | func TestBackgroundShell_ExitCode(t *testing.T) {
  function TestBackgroundShell_WithBlockFuncs (line 149) | func TestBackgroundShell_WithBlockFuncs(t *testing.T) {
  function TestBackgroundShell_StdoutAndStderr (line 182) | func TestBackgroundShell_StdoutAndStderr(t *testing.T) {
  function TestBackgroundShell_ConcurrentAccess (line 204) | func TestBackgroundShell_ConcurrentAccess(t *testing.T) {
  function TestBackgroundShell_List (line 254) | func TestBackgroundShell_List(t *testing.T) {
  function TestBackgroundShell_AutoBackground (line 284) | func TestBackgroundShell_AutoBackground(t *testing.T) {

FILE: internal/agent/tools/list_mcp_resources.go
  type ListMCPResourcesParams (line 18) | type ListMCPResourcesParams struct
  type ListMCPResourcesPermissionsParams (line 22) | type ListMCPResourcesPermissionsParams struct
  constant ListMCPResourcesToolName (line 26) | ListMCPResourcesToolName = "list_mcp_resources"
  function NewListMCPResourcesTool (line 31) | func NewListMCPResourcesTool(cfg *config.ConfigStore, permissions permis...

FILE: internal/agent/tools/ls.go
  type LSParams (line 19) | type LSParams struct
  type LSPermissionsParams (line 25) | type LSPermissionsParams struct
  type NodeType (line 31) | type NodeType
  constant NodeTypeFile (line 34) | NodeTypeFile      NodeType = "file"
  constant NodeTypeDirectory (line 35) | NodeTypeDirectory NodeType = "directory"
  type TreeNode (line 38) | type TreeNode struct
  type LSResponseMetadata (line 45) | type LSResponseMetadata struct
  constant LSToolName (line 51) | LSToolName = "ls"
  constant maxLSFiles (line 52) | maxLSFiles = 1000
  function NewLsTool (line 58) | func NewLsTool(permissions permission.Service, workingDir string, lsConf...
  function ListDirectoryTree (line 120) | func ListDirectoryTree(searchPath string, params LSParams, lsConfig conf...
  function createFileTree (line 153) | func createFileTree(sortedPaths []string, rootPath string) []*TreeNode {
  function printTree (line 217) | func printTree(tree []*TreeNode, rootPath string) string {
  function printNode (line 234) | func printNode(builder *strings.Builder, node *TreeNode, level int) {

FILE: internal/agent/tools/lsp_restart.go
  constant LSPRestartToolName (line 16) | LSPRestartToolName = "lsp_restart"
  type LSPRestartParams (line 21) | type LSPRestartParams struct
  function NewLSPRestartTool (line 27) | func NewLSPRestartTool(lspManager *lsp.Manager) fantasy.AgentTool {

FILE: internal/agent/tools/mcp-tools.go
  function GetMCPTools (line 24) | func GetMCPTools(permissions permission.Service, cfg *config.ConfigStore...
  type Tool (line 41) | type Tool struct
    method SetProviderOptions (line 50) | func (m *Tool) SetProviderOptions(opts fantasy.ProviderOptions) {
    method ProviderOptions (line 54) | func (m *Tool) ProviderOptions() fantasy.ProviderOptions {
    method Name (line 58) | func (m *Tool) Name() string {
    method MCP (line 62) | func (m *Tool) MCP() string {
    method MCPToolName (line 66) | func (m *Tool) MCPToolName() string {
    method Info (line 70) | func (m *Tool) Info() fantasy.ToolInfo {
    method Run (line 99) | func (m *Tool) Run(ctx context.Context, params fantasy.ToolCall) (fant...

FILE: internal/agent/tools/mcp/init.go
  function parseLevel (line 28) | func parseLevel(level mcp.LoggingLevel) slog.Level {
  type ClientSession (line 44) | type ClientSession struct
    method Close (line 50) | func (s *ClientSession) Close() error {
  type State (line 64) | type State
    method String (line 73) | func (s State) String() string {
  constant StateDisabled (line 67) | StateDisabled State = iota
  constant StateStarting (line 68) | StateStarting
  constant StateConnected (line 69) | StateConnected
  constant StateError (line 70) | StateError
  type EventType (line 89) | type EventType
  constant EventStateChanged (line 92) | EventStateChanged EventType = iota
  constant EventToolsListChanged (line 93) | EventToolsListChanged
  constant EventPromptsListChanged (line 94) | EventPromptsListChanged
  constant EventResourcesListChanged (line 95) | EventResourcesListChanged
  type Event (line 99) | type Event struct
  type Counts (line 108) | type Counts struct
  type ClientInfo (line 115) | type ClientInfo struct
  function SubscribeEvents (line 125) | func SubscribeEvents(ctx context.Context) <-chan pubsub.Event[Event] {
  function GetStates (line 130) | func GetStates() map[string]ClientInfo {
  function GetState (line 135) | func GetState(name string) (ClientInfo, bool) {
  function Close (line 140) | func Close(ctx context.Context) error {
  function Initialize (line 166) | func Initialize(ctx context.Context, permissions permission.Service, cfg...
  function WaitForInit (line 208) | func WaitForInit(ctx context.Context) error {
  function InitializeSingle (line 218) | func InitializeSingle(ctx context.Context, name string, cfg *config.Conf...
  function initClient (line 234) | func initClient(ctx context.Context, cfg *config.ConfigStore, name strin...
  function DisableSingle (line 273) | func DisableSingle(cfg *config.ConfigStore, name string) error {
  function getOrRenewClient (line 296) | func getOrRenewClient(ctx context.Context, cfg *config.ConfigStore, name...
  function updateState (line 325) | func updateState(name string, state State, err error, client *ClientSess...
  function createSession (line 351) | func createSession(ctx context.Context, name string, m config.MCPConfig,...
  function maybeStdioErr (line 419) | func maybeStdioErr(err error, transport mcp.Transport) error {
  function maybeTimeoutErr (line 433) | func maybeTimeoutErr(err error, timeout time.Duration) error {
  function createTransport (line 440) | func createTransport(ctx context.Context, m config.MCPConfig, resolver c...
  type headerRoundTripper (line 486) | type headerRoundTripper struct
    method RoundTrip (line 490) | func (rt headerRoundTripper) RoundTrip(req *http.Request) (*http.Respo...
  function mcpTimeout (line 497) | func mcpTimeout(m config.MCPConfig) time.Duration {
  function stdioCheck (line 501) | func stdioCheck(old *exec.Cmd) error {

FILE: internal/agent/tools/mcp/init_test.go
  function TestMCPSession_CancelOnClose (line 12) | func TestMCPSession_CancelOnClose(t *testing.T) {

FILE: internal/agent/tools/mcp/prompts.go
  function Prompts (line 18) | func Prompts() iter.Seq2[string, []*Prompt] {
  function GetPromptMessages (line 23) | func GetPromptMessages(ctx context.Context, cfg *config.ConfigStore, cli...
  function RefreshPrompts (line 50) | func RefreshPrompts(ctx context.Context, name string) {
  function getPrompts (line 70) | func getPrompts(ctx context.Context, c *ClientSession) ([]*Prompt, error) {
  function updatePrompts (line 82) | func updatePrompts(mcpName string, prompts []*Prompt) {

FILE: internal/agent/tools/mcp/resources.go
  function Resources (line 22) | func Resources() iter.Seq2[string, []*Resource] {
  function ListResources (line 27) | func ListResources(ctx context.Context, cfg *config.ConfigStore, name st...
  function ReadResource (line 46) | func ReadResource(ctx context.Context, cfg *config.ConfigStore, name, ur...
  function RefreshResources (line 60) | func RefreshResources(ctx context.Context, name string) {
  function getResources (line 80) | func getResources(ctx context.Context, c *ClientSession) ([]*Resource, e...
  function isMethodNotFoundError (line 97) | func isMethodNotFoundError(err error) bool {
  function updateResources (line 102) | func updateResources(name string, resources []*Resource) int {

FILE: internal/agent/tools/mcp/tools.go
  type ToolResult (line 21) | type ToolResult struct
  function Tools (line 31) | func Tools() iter.Seq2[string, []*Tool] {
  function RunTool (line 36) | func RunTool(ctx context.Context, cfg *config.ConfigStore, name, toolNam...
  function RefreshTools (line 113) | func RefreshTools(ctx context.Context, cfg *config.ConfigStore, name str...
  function getTools (line 133) | func getTools(ctx context.Context, session *ClientSession) ([]*Tool, err...
  function updateTools (line 144) | func updateTools(cfg *config.ConfigStore, name string, tools []*Tool) int {
  function filterDisabledTools (line 155) | func filterDisabledTools(cfg *config.ConfigStore, mcpName string, tools ...
  function ensureBase64 (line 172) | func ensureBase64(data []byte) []byte {
  function normalizeBase64Input (line 189) | func normalizeBase64Input(data []byte) []byte {
  function decodeBase64 (line 194) | func decodeBase64(data []byte) ([]byte, bool) {
  function isValidBase64 (line 218) | func isValidBase64(data []byte) bool {

FILE: internal/agent/tools/mcp/tools_test.go
  function TestEnsureBase64 (line 10) | func TestEnsureBase64(t *testing.T) {
  function TestIsValidBase64 (line 73) | func TestIsValidBase64(t *testing.T) {

FILE: internal/agent/tools/multiedit.go
  type MultiEditOperation (line 23) | type MultiEditOperation struct
  type MultiEditParams (line 29) | type MultiEditParams struct
  type MultiEditPermissionsParams (line 34) | type MultiEditPermissionsParams struct
  type FailedEdit (line 40) | type FailedEdit struct
  type MultiEditResponseMetadata (line 46) | type MultiEditResponseMetadata struct
  constant MultiEditToolName (line 55) | MultiEditToolName = "multiedit"
  function NewMultiEditTool (line 60) | func NewMultiEditTool(
  function validateEdits (line 116) | func validateEdits(edits []MultiEditOperation) error {
  function processMultiEditWithCreation (line 126) | func processMultiEditWithCreation(edit editContext, params MultiEditPara...
  function processMultiEditExistingFile (line 240) | func processMultiEditExistingFile(edit editContext, params MultiEditPara...
  function applyEditToContent (line 397) | func applyEditToContent(content string, edit MultiEditOperation) (string...

FILE: internal/agent/tools/multiedit_test.go
  type mockPermissionService (line 15) | type mockPermissionService struct
    method Request (line 19) | func (m *mockPermissionService) Request(ctx context.Context, req permi...
    method Grant (line 23) | func (m *mockPermissionService) Grant(req permission.PermissionRequest...
    method Deny (line 25) | func (m *mockPermissionService) Deny(req permission.PermissionRequest) {}
    method GrantPersistent (line 27) | func (m *mockPermissionService) GrantPersistent(req permission.Permiss...
    method AutoApproveSession (line 29) | func (m *mockPermissionService) AutoApproveSession(sessionID string) {}
    method SetSkipRequests (line 31) | func (m *mockPermissionService) SetSkipRequests(skip bool) {}
    method SkipRequests (line 33) | func (m *mockPermissionService) SkipRequests() bool {
    method SubscribeNotifications (line 37) | func (m *mockPermissionService) SubscribeNotifications(ctx context.Con...
  type mockHistoryService (line 41) | type mockHistoryService struct
    method Create (line 45) | func (m *mockHistoryService) Create(ctx context.Context, sessionID, pa...
    method CreateVersion (line 49) | func (m *mockHistoryService) CreateVersion(ctx context.Context, sessio...
    method GetByPathAndSession (line 53) | func (m *mockHistoryService) GetByPathAndSession(ctx context.Context, ...
    method Get (line 57) | func (m *mockHistoryService) Get(ctx context.Context, id string) (hist...
    method ListBySession (line 61) | func (m *mockHistoryService) ListBySession(ctx context.Context, sessio...
    method ListLatestSessionFiles (line 65) | func (m *mockHistoryService) ListLatestSessionFiles(ctx context.Contex...
    method Delete (line 69) | func (m *mockHistoryService) Delete(ctx context.Context, id string) er...
    method DeleteSessionFiles (line 73) | func (m *mockHistoryService) DeleteSessionFiles(ctx context.Context, s...
  function TestApplyEditToContentPartialSuccess (line 77) | func TestApplyEditToContentPartialSuccess(t *testing.T) {
  function TestMultiEditSequentialApplication (line 100) | func TestMultiEditSequentialApplication(t *testing.T) {
  function TestMultiEditAllEditsSucceed (line 155) | func TestMultiEditAllEditsSucceed(t *testing.T) {
  function TestMultiEditAllEditsFail (line 184) | func TestMultiEditAllEditsFail(t *testing.T) {

FILE: internal/agent/tools/read_mcp_resource.go
  type ReadMCPResourceParams (line 18) | type ReadMCPResourceParams struct
  type ReadMCPResourcePermissionsParams (line 23) | type ReadMCPResourcePermissionsParams struct
  constant ReadMCPResourceToolName (line 28) | ReadMCPResourceToolName = "read_mcp_resource"
  function NewReadMCPResourceTool (line 33) | func NewReadMCPResourceTool(cfg *config.ConfigStore, permissions permiss...

FILE: internal/agent/tools/references.go
  type ReferencesParams (line 22) | type ReferencesParams struct
  type referencesTool (line 27) | type referencesTool struct
    method Name (line 93) | func (r *referencesTool) Name() string {
  constant ReferencesToolName (line 31) | ReferencesToolName = "lsp_references"
  function NewReferencesTool (line 36) | func NewReferencesTool(lspManager *lsp.Manager) fantasy.AgentTool {
  function find (line 97) | func find(ctx context.Context, lspManager *lsp.Manager, symbol string, m...
  function getSymbolOffset (line 127) | func getSymbolOffset(symbol string) int {
  function cleanupLocations (line 143) | func cleanupLocations(locations []protocol.Location) []protocol.Location {
  function groupByFilename (line 160) | func groupByFilename(locations []protocol.Location) map[string][]protoco...
  function formatReferences (line 173) | func formatReferences(locations []protocol.Location) string {

FILE: internal/agent/tools/rg.go
  function getRgCmd (line 25) | func getRgCmd(ctx context.Context, globPattern string) *exec.Cmd {
  function getRgSearchCmd (line 40) | func getRgSearchCmd(ctx context.Context, pattern, path, include string) ...

FILE: internal/agent/tools/safe.go
  function init (line 57) | func init() {

FILE: internal/agent/tools/search.go
  type SearchResult (line 19) | type SearchResult struct
  function searchDuckDuckGo (line 48) | func searchDuckDuckGo(ctx context.Context, client *http.Client, query st...
  function setRandomizedHeaders (line 80) | func setRandomizedHeaders(req *http.Request) {
  function parseLiteSearchResults (line 97) | func parseLiteSearchResults(htmlContent string, maxResults int) ([]Searc...
  function hasClass (line 147) | func hasClass(n *html.Node, class string) bool {
  function getTextContent (line 158) | func getTextContent(n *html.Node) string {
  function cleanDuckDuckGoURL (line 173) | func cleanDuckDuckGoURL(rawURL string) string {
  function formatSearchResults (line 188) | func formatSearchResults(results []SearchResult) string {
  function maybeDelaySearch (line 209) | func maybeDelaySearch() {

FILE: internal/agent/tools/sourcegraph.go
  type SourcegraphParams (line 17) | type SourcegraphParams struct
  type SourcegraphResponseMetadata (line 24) | type SourcegraphResponseMetadata struct
  constant SourcegraphToolName (line 29) | SourcegraphToolName = "sourcegraph"
  function NewSourcegraphTool (line 34) | func NewSourcegraphTool(client *http.Client) fantasy.AgentTool {
  function formatSourcegraphResults (line 140) | func formatSourcegraphResults(result map[string]any, contextWindow int) ...

FILE: internal/agent/tools/todos.go
  constant TodosToolName (line 15) | TodosToolName = "todos"
  type TodosParams (line 17) | type TodosParams struct
  type TodoItem (line 21) | type TodoItem struct
  type TodosResponseMetadata (line 27) | type TodosResponseMetadata struct
  function NewTodosTool (line 36) | func NewTodosTool(sessions session.Service) fantasy.AgentTool {

FILE: internal/agent/tools/tools.go
  type sessionIDContextKey (line 8) | type sessionIDContextKey
  type messageIDContextKey (line 9) | type messageIDContextKey
  type supportsImagesKey (line 10) | type supportsImagesKey
  type modelNameKey (line 11) | type modelNameKey
  constant SessionIDContextKey (line 16) | SessionIDContextKey sessionIDContextKey = "session_id"
  constant MessageIDContextKey (line 18) | MessageIDContextKey messageIDContextKey = "message_id"
  constant SupportsImagesContextKey (line 20) | SupportsImagesContextKey supportsImagesKey = "supports_images"
  constant ModelNameContextKey (line 22) | ModelNameContextKey modelNameKey = "model_name"
  function getContextValue (line 27) | func getContextValue[T any](ctx context.Context, key any, defaultValue T...
  function GetSessionFromContext (line 39) | func GetSessionFromContext(ctx context.Context) string {
  function GetMessageFromContext (line 44) | func GetMessageFromContext(ctx context.Context) string {
  function GetSupportsImagesFromContext (line 49) | func GetSupportsImagesFromContext(ctx context.Context) bool {
  function GetModelNameFromContext (line 54) | func GetModelNameFromContext(ctx context.Context) string {

FILE: internal/agent/tools/view.go
  type ViewParams (line 27) | type ViewParams struct
  type ViewPermissionsParams (line 33) | type ViewPermissionsParams struct
  type ViewResourceType (line 39) | type ViewResourceType
  constant ViewResourceUnset (line 42) | ViewResourceUnset ViewResourceType = ""
  constant ViewResourceSkill (line 43) | ViewResourceSkill ViewResourceType = "skill"
  type ViewResponseMetadata (line 46) | type ViewResponseMetadata struct
  constant ViewToolName (line 55) | ViewToolName     = "view"
  constant MaxReadSize (line 56) | MaxReadSize      = 5 * 1024 * 1024
  constant DefaultReadLimit (line 57) | DefaultReadLimit = 2000
  constant MaxLineLength (line 58) | MaxLineLength    = 2000
  function NewViewTool (line 61) | func NewViewTool(
  function addLineNumbers (line 229) | func addLineNumbers(content string, startLine int) string {
  function readTextFile (line 254) | func readTextFile(filePath string, offset, limit int) (string, bool, err...
  function getImageMimeType (line 293) | func getImageMimeType(filePath string) (bool, string) {
  type LineScanner (line 309) | type LineScanner struct
    method Scan (line 324) | func (s *LineScanner) Scan() bool {
    method Text (line 328) | func (s *LineScanner) Text() string {
    method Err (line 332) | func (s *LineScanner) Err() error {
  function NewLineScanner (line 313) | func NewLineScanner(r io.Reader) *LineScanner {
  function isInSkillsPath (line 342) | func isInSkillsPath(filePath string, skillsPaths []string) bool {

FILE: internal/agent/tools/view_test.go
  function TestReadTextFileBoundaryCases (line 13) | func TestReadTextFileBoundaryCases(t *testing.T) {
  function TestReadTextFileTruncatesLongLines (line 74) | func TestReadTextFileTruncatesLongLines(t *testing.T) {

FILE: internal/agent/tools/web_fetch.go
  function NewWebFetchTool (line 19) | func NewWebFetchTool(workingDir string, client *http.Client) fantasy.Age...

FILE: internal/agent/tools/web_search.go
  function NewWebSearchTool (line 17) | func NewWebSearchTool(client *http.Client) fantasy.AgentTool {

FILE: internal/agent/tools/write.go
  type WriteParams (line 27) | type WriteParams struct
  type WritePermissionsParams (line 32) | type WritePermissionsParams struct
  type WriteResponseMetadata (line 38) | type WriteResponseMetadata struct
  constant WriteToolName (line 44) | WriteToolName = "write"
  function NewWriteTool (line 46) | func NewWriteTool(

FILE: internal/ansiext/ansi.go
  function Escape (line 11) | func Escape(content string) string {

FILE: internal/app/app.go
  type UpdateAvailableMsg (line 47) | type UpdateAvailableMsg struct
  type App (line 53) | type App struct
    method Config (line 146) | func (app *App) Config() *config.Config {
    method Store (line 151) | func (app *App) Store() *config.ConfigStore {
    method AgentNotifications (line 156) | func (app *App) AgentNotifications() *pubsub.Broker[notify.Notificatio...
    method resolveSession (line 164) | func (app *App) resolveSession(ctx context.Context, continueSessionID ...
    method RunNonInteractive (line 193) | func (app *App) RunNonInteractive(ctx context.Context, output io.Write...
    method UpdateAgentModel (line 362) | func (app *App) UpdateAgentModel(ctx context.Context) error {
    method overrideModelsForNonInteractive (line 375) | func (app *App) overrideModelsForNonInteractive(ctx context.Context, l...
    method GetDefaultSmallModel (line 423) | func (app *App) GetDefaultSmallModel(providerID string) config.Selecte...
    method setupEvents (line 459) | func (app *App) setupEvents() {
    method InitCoderAgent (line 525) | func (app *App) InitCoderAgent(ctx context.Context) error {
    method Subscribe (line 550) | func (app *App) Subscribe(program *tea.Program) {
    method Shutdown (line 582) | func (app *App) Shutdown() {
    method checkForUpdates (line 628) | func (app *App) checkForUpdates(ctx context.Context) {
  function New (line 78) | func New(ctx context.Context, conn *sql.DB, store *config.ConfigStore) (...
  constant subscriberSendTimeout (line 478) | subscriberSendTimeout = 2 * time.Second
  function setupSubscriber (line 480) | func setupSubscriber[T any](

FILE: internal/app/app_test.go
  function TestSetupSubscriber_NormalFlow (line 16) | func TestSetupSubscriber_NormalFlow(t *testing.T) {
  function TestSetupSubscriber_SlowConsumer (line 39) | func TestSetupSubscriber_SlowConsumer(t *testing.T) {
  function TestSetupSubscriber_ContextCancellation (line 73) | func TestSetupSubscriber_ContextCancellation(t *testing.T) {
  function TestSetupSubscriber_DrainAfterDrop (line 86) | func TestSetupSubscriber_DrainAfterDrop(t *testing.T) {
  function TestSetupSubscriber_NoTimerLeak (line 117) | func TestSetupSubscriber_NoTimerLeak(t *testing.T) {
  type subscriberFixture (line 133) | type subscriberFixture struct
  function newSubscriberFixture (line 140) | func newSubscriberFixture(t *testing.T, bufSize int) *subscriberFixture {

FILE: internal/app/lsp_events.go
  type LSPEventType (line 13) | type LSPEventType
  constant LSPEventStateChanged (line 16) | LSPEventStateChanged       LSPEventType = "state_changed"
  constant LSPEventDiagnosticsChanged (line 17) | LSPEventDiagnosticsChanged LSPEventType = "diagnostics_changed"
  type LSPEvent (line 21) | type LSPEvent struct
  type LSPClientInfo (line 30) | type LSPClientInfo struct
  function SubscribeLSPEvents (line 45) | func SubscribeLSPEvents(ctx context.Context) <-chan pubsub.Event[LSPEven...
  function GetLSPStates (line 50) | func GetLSPStates() map[string]LSPClientInfo {
  function GetLSPState (line 55) | func GetLSPState(name string) (LSPClientInfo, bool) {
  function updateLSPState (line 60) | func updateLSPState(name string, state lsp.ServerState, err error, clien...
  function updateLSPDiagnostics (line 86) | func updateLSPDiagnostics(name string, diagnosticCount int) {

FILE: internal/app/provider.go
  function parseModelStr (line 15) | func parseModelStr(providers map[string]config.ProviderConfig, modelStr ...
  type modelMatch (line 30) | type modelMatch struct
  function findModels (line 35) | func findModels(providers map[string]config.ProviderConfig, largeModel, ...
  function filter (line 72) | func filter(modelFilter, providerFilter, model, provider string) bool {
  function validateMatches (line 78) | func validateMatches(matches []modelMatch, modelID, label string) (model...

FILE: internal/app/provider_test.go
  function TestParseModelStr (line 11) | func TestParseModelStr(t *testing.T) {
  function setupMockProviders (line 74) | func setupMockProviders() map[string]config.ProviderConfig {
  function setupMockProvidersWithSlashes (line 89) | func setupMockProvidersWithSlashes() map[string]config.ProviderConfig {
  function TestFindModels (line 107) | func TestFindModels(t *testing.T) {

FILE: internal/app/resolve_session_test.go
  type mockSessionService (line 16) | type mockSessionService struct
    method Subscribe (line 21) | func (m *mockSessionService) Subscribe(context.Context) <-chan pubsub....
    method Create (line 25) | func (m *mockSessionService) Create(_ context.Context, title string) (...
    method CreateTitleSession (line 31) | func (m *mockSessionService) CreateTitleSession(context.Context, strin...
    method CreateTaskSession (line 35) | func (m *mockSessionService) CreateTaskSession(context.Context, string...
    method Get (line 39) | func (m *mockSessionService) Get(_ context.Context, id string) (sessio...
    method GetLast (line 48) | func (m *mockSessionService) GetLast(_ context.Context) (session.Sessi...
    method List (line 55) | func (m *mockSessionService) List(context.Context) ([]session.Session,...
    method Save (line 59) | func (m *mockSessionService) Save(_ context.Context, s session.Session...
    method UpdateTitleAndUsage (line 63) | func (m *mockSessionService) UpdateTitleAndUsage(context.Context, stri...
    method Rename (line 67) | func (m *mockSessionService) Rename(context.Context, string, string) e...
    method Delete (line 71) | func (m *mockSessionService) Delete(context.Context, string) error {
    method CreateAgentToolSessionID (line 75) | func (m *mockSessionService) CreateAgentToolSessionID(messageID, toolC...
    method ParseAgentToolSessionID (line 79) | func (m *mockSessionService) ParseAgentToolSessionID(sessionID string)...
    method IsAgentToolSession (line 87) | func (m *mockSessionService) IsAgentToolSession(sessionID string) bool {
  function newTestApp (line 92) | func newTestApp(sessions session.Service) *App {
  function TestResolveSession_NewSession (line 96) | func TestResolveSession_NewSession(t *testing.T) {
  function TestResolveSession_ContinueByID (line 106) | func TestResolveSession_ContinueByID(t *testing.T) {
  function TestResolveSession_ContinueByID_NotFound (line 121) | func TestResolveSession_ContinueByID_NotFound(t *testing.T) {
  function TestResolveSession_ContinueByID_ChildSession (line 130) | func TestResolveSession_ContinueByID_ChildSession(t *testing.T) {
  function TestResolveSession_ContinueByID_AgentToolSession (line 143) | func TestResolveSession_ContinueByID_AgentToolSession(t *testing.T) {
  function TestResolveSession_Last (line 152) | func TestResolveSession_Last(t *testing.T) {
  function TestResolveSession_Last_NoSessions (line 167) | func TestResolveSession_Last_NoSessions(t *testing.T) {

FILE: internal/cmd/dirs.go
  function init (line 64) | func init() {

FILE: internal/cmd/dirs_test.go
  function init (line 12) | func init() {
  function TestDirs (line 19) | func TestDirs(t *testing.T) {
  function TestConfigDir (line 30) | func TestConfigDir(t *testing.T) {
  function TestDataDir (line 40) | func TestDataDir(t *testing.T) {

FILE: internal/cmd/login.go
  function loginHyper (line 64) | func loginHyper(cfg *config.ConfigStore) error {
  function loginCopilot (line 126) | func loginCopilot(cfg *config.ConfigStore) error {
  function getLoginContext (line 191) | func getLoginContext() context.Context {
  function waitEnter (line 201) | func waitEnter() {

FILE: internal/cmd/logs.go
  constant defaultTailLines (line 21) | defaultTailLines = 1000
  function init (line 73) | func init() {
  function followLogs (line 78) | func followLogs(ctx context.Context, logsFile string, tailLines int) err...
  function showLogs (line 133) | func showLogs(logsFile string, tailLines int) error {
  function printLogLine (line 167) | func printLogLine(lineText string) {

FILE: internal/cmd/models.go
  function init (line 108) | func init() {

FILE: internal/cmd/projects.go
  function init (line 75) | func init() {

FILE: internal/cmd/projects_test.go
  function TestProjectsEmpty (line 12) | func TestProjectsEmpty(t *testing.T) {
  function TestProjectsJSON (line 26) | func TestProjectsJSON(t *testing.T) {

FILE: internal/cmd/root.go
  function init (line 34) | func init() {
  constant defaultVersionTemplate (line 145) | defaultVersionTemplate = `{{with .DisplayName}}{{printf "%s " .}}{{end}}...
  function Execute (line 148) | func Execute() {
  function supportsProgressBar (line 175) | func supportsProgressBar() bool {
  function setupAppWithProgressBar (line 185) | func setupAppWithProgressBar(cmd *cobra.Command) (*app.App, error) {
  function setupApp (line 203) | func setupApp(cmd *cobra.Command) (*app.App, error) {
  function shouldEnableMetrics (line 254) | func shouldEnableMetrics(cfg *config.Config) bool {
  function MaybePrependStdin (line 267) | func MaybePrependStdin(prompt string) (string, error) {
  function ResolveCwd (line 286) | func ResolveCwd(cmd *cobra.Command) (string, error) {
  function createDotCrushDir (line 302) | func createDotCrushDir(dir string) error {

FILE: internal/cmd/run.go
  function init (line 110) | func init() {

FILE: internal/cmd/session.go
  function init (line 86) | func init() {
  type sessionServices (line 99) | type sessionServices struct
  function sessionSetup (line 104) | func sessionSetup(cmd *cobra.Command) (context.Context, *sessionServices...
  function runSessionList (line 129) | func runSessionList(cmd *cobra.Command, _ []string) error {
  type sessionJSON (line 194) | type sessionJSON struct
  type sessionMutationResult (line 202) | type sessionMutationResult struct
  function resolveSessionID (line 212) | func resolveSessionID(ctx context.Context, svc session.Service, id strin...
  function runSessionShow (line 255) | func runSessionShow(cmd *cobra.Command, args []string) error {
  function runSessionDelete (line 282) | func runSessionDelete(cmd *cobra.Command, args []string) error {
  function runSessionRename (line 317) | func runSessionRename(cmd *cobra.Command, args []string) error {
  function runSessionLast (line 353) | func runSessionLast(cmd *cobra.Command, _ []string) error {
  constant sessionOutputWidth (line 387) | sessionOutputWidth     = 80
  constant sessionMaxContentWidth (line 388) | sessionMaxContentWidth = 120
  function messagePtrs (line 391) | func messagePtrs(msgs []message.Message) []*message.Message {
  function outputSessionJSON (line 399) | func outputSessionJSON(w io.Writer, sess session.Session, msgs []*messag...
  function outputSessionHuman (line 431) | func outputSessionHuman(ctx context.Context, sess session.Session, msgs ...
  function isBrokenPipe (line 483) | func isBrokenPipe(err error) bool {
  function sessionWriter (line 499) | func sessionWriter(ctx context.Context, contentHeight int) (io.Writer, f...
  type sessionShowMeta (line 541) | type sessionShowMeta struct
  type sessionShowMessage (line 553) | type sessionShowMessage struct
  type sessionShowPart (line 562) | type sessionShowPart struct
  function convertParts (line 595) | func convertParts(parts []message.ContentPart) []sessionShowPart {
  type sessionShowOutput (line 654) | type sessionShowOutput struct

FILE: internal/cmd/stats.go
  type Stats (line 53) | type Stats struct
  type TotalStats (line 66) | type TotalStats struct
  type DailyUsage (line 77) | type DailyUsage struct
  type ModelUsage (line 86) | type ModelUsage struct
  type HourlyUsage (line 92) | type HourlyUsage struct
  type DayOfWeekUsage (line 97) | type DayOfWeekUsage struct
  type DailyActivity (line 105) | type DailyActivity struct
  type ToolUsage (line 112) | type ToolUsage struct
  type HourDayHeatmapPt (line 117) | type HourDayHeatmapPt struct
  function runStats (line 123) | func runStats(cmd *cobra.Command, _ []string) error {
  function gatherStats (line 178) | func gatherStats(ctx context.Context, conn *sql.DB) (*Stats, error) {
  function toInt64 (line 310) | func toInt64(v any) int64 {
  function toFloat64 (line 323) | func toFloat64(v any) float64 {
  function nullFloat64ToInt64 (line 336) | func nullFloat64ToInt64(n sql.NullFloat64) int64 {
  function generateHTML (line 343) | func generateHTML(stats *Stats, projName, username, path string) error {

FILE: internal/cmd/stats/index.js
  function formatNumber (line 22) | function formatNumber(n) {
  function formatCompact (line 26) | function formatCompact(n) {
  function formatCost (line 32) | function formatCost(n) {
  function formatTime (line 36) | function formatTime(ms) {
  function interpolateColor (line 44) | function interpolateColor(ratio, alpha = 1) {
  function getTopItemsWithOthers (line 54) | function getTopItemsWithOthers(items, countKey, labelKey, topN = 10) {

FILE: internal/cmd/update_providers.go
  function init (line 80) | func init() {

FILE: internal/commands/commands.go
  constant userCommandPrefix (line 19) | userCommandPrefix    = "user:"
  constant projectCommandPrefix (line 20) | projectCommandPrefix = "project:"
  type Argument (line 24) | type Argument struct
  type MCPPrompt (line 32) | type MCPPrompt struct
  type CustomCommand (line 42) | type CustomCommand struct
  type commandSource (line 49) | type commandSource struct
  function LoadCustomCommands (line 56) | func LoadCustomCommands(cfg *config.Config) ([]CustomCommand, error) {
  function LoadMCPPrompts (line 61) | func LoadMCPPrompts() ([]MCPPrompt, error) {
  function buildCommandSources (line 92) | func buildCommandSources(cfg *config.Config) []commandSource {
  function loadAll (line 120) | func loadAll(sources []commandSource) ([]CustomCommand, error) {
  function loadFromSource (line 132) | func loadFromSource(source commandSource) ([]CustomCommand, error) {
  function loadCommand (line 156) | func loadCommand(path, baseDir, prefix string) (CustomCommand, error) {
  function extractArgNames (line 172) | func extractArgNames(content string) []Argument {
  function buildCommandID (line 193) | func buildCommandID(path, baseDir, prefix string) string {
  function getXDGCommandsDir (line 206) | func getXDGCommandsDir() string {
  function ensureDir (line 219) | func ensureDir(path string) error {
  function isMarkdownFile (line 226) | func isMarkdownFile(name string) bool {
  function GetMCPPrompt (line 230) | func GetMCPPrompt(cfg *config.ConfigStore, clientID, promptID string, ar...

FILE: internal/config/agent_id_test.go
  function TestConfig_AgentIDs (line 10) | func TestConfig_AgentIDs(t *testing.T) {

FILE: internal/config/attribution_migration_test.go
  function TestAttributionMigration (line 9) | func TestAttributionMigration(t *testing.T) {

FILE: internal/config/catwalk.go
  type catwalkClient (line 14) | type catwalkClient interface
  type catwalkSync (line 20) | type catwalkSync struct
    method Init (line 29) | func (s *catwalkSync) Init(client catwalkClient, path string, autoupda...
    method Get (line 36) | func (s *catwalkSync) Get(ctx context.Context) ([]catwalk.Provider, er...

FILE: internal/config/catwalk_test.go
  type mockCatwalkClient (line 14) | type mockCatwalkClient struct
    method GetProviders (line 20) | func (m *mockCatwalkClient) GetProviders(ctx context.Context, etag str...
  function TestCatwalkSync_Init (line 25) | func TestCatwalkSync_Init(t *testing.T) {
  function TestCatwalkSync_GetPanicIfNotInit (line 40) | func TestCatwalkSync_GetPanicIfNotInit(t *testing.T) {
  function TestCatwalkSync_GetWithAutoUpdateDisabled (line 49) | func TestCatwalkSync_GetWithAutoUpdateDisabled(t *testing.T) {
  function TestCatwalkSync_GetFreshProviders (line 71) | func TestCatwalkSync_GetFreshProviders(t *testing.T) {
  function TestCatwalkSync_GetNotModifiedUsesCached (line 96) | func TestCatwalkSync_GetNotModifiedUsesCached(t *testing.T) {
  function TestCatwalkSync_GetEmptyResultFallbackToCached (line 124) | func TestCatwalkSync_GetEmptyResultFallbackToCached(t *testing.T) {
  function TestCatwalkSync_GetEmptyCacheDefaultsToEmbedded (line 152) | func TestCatwalkSync_GetEmptyCacheDefaultsToEmbedded(t *testing.T) {
  function TestCatwalkSync_GetClientError (line 179) | func TestCatwalkSync_GetClientError(t *testing.T) {
  function TestCatwalkSync_GetCalledMultipleTimesUsesOnce (line 197) | func TestCatwalkSync_GetCalledMultipleTimesUsesOnce(t *testing.T) {

FILE: internal/config/config.go
  constant appName (line 25) | appName              = "crush"
  constant defaultDataDirectory (line 26) | defaultDataDirectory = ".crush"
  constant defaultInitializeAs (line 27) | defaultInitializeAs  = "AGENTS.md"
  type SelectedModelType (line 49) | type SelectedModelType
    method String (line 52) | func (s SelectedModelType) String() string {
  constant SelectedModelTypeLarge (line 57) | SelectedModelTypeLarge SelectedModelType = "large"
  constant SelectedModelTypeSmall (line 58) | SelectedModelTypeSmall SelectedModelType = "small"
  constant AgentCoder (line 62) | AgentCoder string = "coder"
  constant AgentTask (line 63) | AgentTask  string = "task"
  type SelectedModel (line 66) | type SelectedModel struct
  type ProviderConfig (line 92) | type ProviderConfig struct
    method ToProvider (line 128) | func (pc *ProviderConfig) ToProvider() catwalk.Provider {
    method SetupGitHubCopilot (line 157) | func (pc *ProviderConfig) SetupGitHubCopilot() {
    method TestConnection (line 540) | func (c *ProviderConfig) TestConnection(resolver VariableResolver) err...
  type MCPType (line 161) | type MCPType
  constant MCPStdio (line 164) | MCPStdio MCPType = "stdio"
  constant MCPSSE (line 165) | MCPSSE   MCPType = "sse"
  constant MCPHttp (line 166) | MCPHttp  MCPType = "http"
  type MCPConfig (line 169) | type MCPConfig struct
    method ResolvedEnv (line 308) | func (m MCPConfig) ResolvedEnv() []string {
    method ResolvedHeaders (line 312) | func (m MCPConfig) ResolvedHeaders() map[string]string {
  type LSPConfig (line 183) | type LSPConfig struct
    method ResolvedEnv (line 304) | func (l LSPConfig) ResolvedEnv() []string {
  type TUIOptions (line 195) | type TUIOptions struct
  type Completions (line 206) | type Completions struct
    method Limits (line 211) | func (c Completions) Limits() (depth, items int) {
  type Permissions (line 215) | type Permissions struct
  type TrailerStyle (line 220) | type TrailerStyle
  constant TrailerStyleNone (line 223) | TrailerStyleNone         TrailerStyle = "none"
  constant TrailerStyleCoAuthoredBy (line 224) | TrailerStyleCoAuthoredBy TrailerStyle = "co-authored-by"
  constant TrailerStyleAssistedBy (line 225) | TrailerStyleAssistedBy   TrailerStyle = "assisted-by"
  type Attribution (line 228) | type Attribution struct
    method JSONSchemaExtend (line 235) | func (Attribution) JSONSchemaExtend(schema *jsonschema.Schema) {
  type Options (line 243) | type Options struct
  type MCPs (line 262) | type MCPs
    method Sorted (line 269) | func (m MCPs) Sorted() []MCP {
  type MCP (line 264) | type MCP struct
  type LSPs (line 283) | type LSPs
    method Sorted (line 290) | func (l LSPs) Sorted() []LSP {
  type LSP (line 285) | type LSP struct
  type Agent (line 325) | type Agent struct
  type Tools (line 348) | type Tools struct
  type ToolLs (line 353) | type ToolLs struct
    method Limits (line 359) | func (t ToolLs) Limits() (depth, items int) {
  type ToolGrep (line 363) | type ToolGrep struct
    method GetTimeout (line 368) | func (t ToolGrep) GetTimeout() time.Duration {
  type Config (line 373) | type Config struct
    method EnabledProviders (line 398) | func (c *Config) EnabledProviders() []ProviderConfig {
    method IsConfigured (line 409) | func (c *Config) IsConfigured() bool {
    method GetModel (line 413) | func (c *Config) GetModel(provider, model string) *catwalk.Model {
    method GetProviderForModel (line 424) | func (c *Config) GetProviderForModel(modelType SelectedModelType) *Pro...
    method GetModelByType (line 435) | func (c *Config) GetModelByType(modelType SelectedModelType) *catwalk....
    method LargeModel (line 443) | func (c *Config) LargeModel() *catwalk.Model {
    method SmallModel (line 451) | func (c *Config) SmallModel() *catwalk.Model {
    method SetupAgents (line 513) | func (c *Config) SetupAgents() {
  constant maxRecentModelsPerType (line 459) | maxRecentModelsPerType = 5
  function allToolNames (line 461) | func allToolNames() []string {
  function resolveAllowedTools (line 487) | func resolveAllowedTools(allTools []string, disabledTools []string) []st...
  function resolveReadOnlyTools (line 495) | func resolveReadOnlyTools(tools []string) []string {
  function filterSlice (line 501) | func filterSlice(data []string, mask []string, include bool) []string {
  function resolveEnvs (line 638) | func resolveEnvs(envs map[string]string) []string {
  function ptrValOr (line 656) | func ptrValOr[T any](t *T, el T) T {

FILE: internal/config/docker_mcp.go
  constant dockerMCPAvailabilityTTL (line 16) | dockerMCPAvailabilityTTL = 10 * time.Second
  constant DockerMCPName (line 26) | DockerMCPName = "docker"
  function IsDockerMCPAvailable (line 30) | func IsDockerMCPAvailable() bool {
  function DockerMCPAvailabilityCached (line 40) | func DockerMCPAvailabilityCached() (available bool, known bool) {
  function RefreshDockerMCPAvailability (line 54) | func RefreshDockerMCPAvailability() bool {
  method IsDockerMCPEnabled (line 65) | func (c *Config) IsDockerMCPEnabled() bool {
  function DockerMCPConfig (line 74) | func DockerMCPConfig() MCPConfig {
  method PrepareDockerMCPConfig (line 85) | func (s *ConfigStore) PrepareDockerMCPConfig() (MCPConfig, error) {
  method PersistDockerMCPConfig (line 100) | func (s *ConfigStore) PersistDockerMCPConfig(mcpConfig MCPConfig) error {
  method EnableDockerMCP (line 108) | func (s *ConfigStore) EnableDockerMCP() error {
  method DisableDockerMCP (line 120) | func (s *ConfigStore) DisableDockerMCP() error {

FILE: internal/config/docker_mcp_test.go
  function setDockerMCPVersionRunner (line 16) | func setDockerMCPVersionRunner(t *testing.T, runner func(context.Context...
  function TestIsDockerMCPEnabled (line 25) | func TestIsDockerMCPEnabled(t *testing.T) {
  function TestEnableDockerMCP (line 58) | func TestEnableDockerMCP(t *testing.T) {
  function TestDisableDockerMCP (line 116) | func TestDisableDockerMCP(t *testing.T) {
  function TestEnableDockerMCPWithRealDockerWhenAvailable (line 171) | func TestEnableDockerMCPWithRealDockerWhenAvailable(t *testing.T) {

FILE: internal/config/hyper.go
  type hyperClient (line 19) | type hyperClient interface
  type hyperSync (line 25) | type hyperSync struct
    method Init (line 34) | func (s *hyperSync) Init(client hyperClient, path string, autoupdate b...
    method Get (line 41) | func (s *hyperSync) Get(ctx context.Context) (catwalk.Provider, error) {
  type realHyperClient (line 86) | type realHyperClient struct
    method Get (line 91) | func (r realHyperClient) Get(ctx context.Context, etag string) (catwal...

FILE: internal/config/hyper_test.go
  type mockHyperClient (line 14) | type mockHyperClient struct
    method Get (line 20) | func (m *mockHyperClient) Get(ctx context.Context, etag string) (catwa...
  function TestHyperSync_Init (line 25) | func TestHyperSync_Init(t *testing.T) {
  function TestHyperSync_GetPanicIfNotInit (line 39) | func TestHyperSync_GetPanicIfNotInit(t *testing.T) {
  function TestHyperSync_GetFreshProvider (line 48) | func TestHyperSync_GetFreshProvider(t *testing.T) {
  function TestHyperSync_GetNotModifiedUsesCached (line 76) | func TestHyperSync_GetNotModifiedUsesCached(t *testing.T) {
  function TestHyperSync_GetClientError (line 104) | func TestHyperSync_GetClientError(t *testing.T) {
  function TestHyperSync_GetEmptyCache (line 123) | func TestHyperSync_GetEmptyCache(t *testing.T) {
  function TestHyperSync_GetCalledMultipleTimesUsesOnce (line 147) | func TestHyperSync_GetCalledMultipleTimesUsesOnce(t *testing.T) {
  function TestHyperSync_GetCacheStoreError (line 177) | func TestHyperSync_GetCacheStoreError(t *testing.T) {

FILE: internal/config/init.go
  constant InitFlagFilename (line 14) | InitFlagFilename = "init"
  type ProjectInitFlag (line 17) | type ProjectInitFlag struct
  function Init (line 21) | func Init(workingDir, dataDir string, debug bool) (*ConfigStore, error) {
  function ProjectNeedsInitialization (line 29) | func ProjectNeedsInitialization(store *ConfigStore) (bool, error) {
  function contextPathsExist (line 66) | func contextPathsExist(dir string) (bool, error) {
  function dirHasNoVisibleFiles (line 95) | func dirHasNoVisibleFiles(dir string) (bool, error) {
  function MarkProjectInitialized (line 103) | func MarkProjectInitialized(store *ConfigStore) error {
  function HasInitialDataConfig (line 118) | func HasInitialDataConfig(store *ConfigStore) bool {

FILE: internal/config/load.go
  constant defaultCatwalkURL (line 30) | defaultCatwalkURL = "https://catwalk.charm.sh"
  function Load (line 34) | func Load(workingDir, dataDir string, debug bool) (*ConfigStore, error) {
  function mustMarshalConfig (line 117) | func mustMarshalConfig(cfg *Config) []byte {
  function PushPopCrushEnv (line 125) | func PushPopCrushEnv() func() {
  method configureProviders (line 153) | func (c *Config) configureProviders(store *ConfigStore, env env.Env, res...
  method setDefaults (line 370) | func (c *Config) setDefaults(workingDir, dataDir string) {
  method applyLSPDefaults (line 446) | func (c *Config) applyLSPDefaults() {
  method defaultModelSelection (line 485) | func (c *Config) defaultModelSelection(knownProviders []catwalk.Provider...
  function configureSelectedModels (line 554) | func configureSelectedModels(store *ConfigStore, knownProviders []catwal...
  function lookupConfigs (line 655) | func lookupConfigs(cwd string) []string {
  function loadFromConfigPaths (line 676) | func loadFromConfigPaths(configPaths []string) (*Config, error) {
  function loadFromBytes (line 696) | func loadFromBytes(configs [][]byte) (*Config, error) {
  function hasAWSCredentials (line 712) | func hasAWSCredentials(env env.Env) bool {
  function GlobalConfig (line 742) | func GlobalConfig() string {
  function GlobalConfigData (line 754) | func GlobalConfigData() string {
  function assignIfNil (line 776) | func assignIfNil[T any](ptr **T, val T) {
  function isInsideWorktree (line 782) | func isInsideWorktree() bool {
  function GlobalSkillsDirs (line 794) | func GlobalSkillsDirs() []string {
  function isAppleTerminal (line 818) | func isAppleTerminal() bool { return os.Getenv("TERM_PROGRAM") == "Apple...

FILE: internal/config/load_bench_test.go
  function BenchmarkLoadFromConfigPaths (line 9) | func BenchmarkLoadFromConfigPaths(b *testing.B) {
  function BenchmarkLoadFromConfigPaths_MissingFiles (line 63) | func BenchmarkLoadFromConfigPaths_MissingFiles(b *testing.B) {
  function BenchmarkLoadFromConfigPaths_Empty (line 88) | func BenchmarkLoadFromConfigPaths_Empty(b *testing.B) {

FILE: internal/config/load_test.go
  function TestMain (line 17) | func TestMain(m *testing.M) {
  function TestConfig_LoadFromBytes (line 24) | func TestConfig_LoadFromBytes(t *testing.T) {
  function testStore (line 40) | func testStore(cfg *Config) *ConfigStore {
  function TestConfig_setDefaults (line 44) | func TestConfig_setDefaults(t *testing.T) {
  function TestConfig_configureProviders (line 63) | func TestConfig_configureProviders(t *testing.T) {
  function TestConfig_configureProvidersWithOverride (line 90) | func TestConfig_configureProvidersWithOverride(t *testing.T) {
  function TestConfig_configureProvidersWithNewProvider (line 136) | func TestConfig_configureProvidersWithNewProvider(t *testing.T) {
  function TestConfig_configureProvidersBedrockWithCredentials (line 183) | func TestConfig_configureProvidersBedrockWithCredentials(t *testing.T) {
  function TestConfig_configureProvidersBedrockWithoutCredentials (line 212) | func TestConfig_configureProvidersBedrockWithoutCredentials(t *testing.T) {
  function TestConfig_configureProvidersBedrockWithoutUnsupportedModel (line 234) | func TestConfig_configureProvidersBedrockWithoutUnsupportedModel(t *test...
  function TestConfig_configureProvidersVertexAIWithCredentials (line 257) | func TestConfig_configureProvidersVertexAIWithCredentials(t *testing.T) {
  function TestConfig_configureProvidersVertexAIWithoutCredentials (line 288) | func TestConfig_configureProvidersVertexAIWithoutCredentials(t *testing....
  function TestConfig_configureProvidersVertexAIMissingProject (line 314) | func TestConfig_configureProvidersVertexAIMissingProject(t *testing.T) {
  function TestConfig_configureProvidersSetProviderID (line 339) | func TestConfig_configureProvidersSetProviderID(t *testing.T) {
  function TestConfig_EnabledProviders (line 366) | func TestConfig_EnabledProviders(t *testing.T) {
  function TestConfig_IsConfigured (line 418) | func TestConfig_IsConfigured(t *testing.T) {
  function TestConfig_setupAgentsWithNoDisabledTools (line 461) | func TestConfig_setupAgentsWithNoDisabledTools(t *testing.T) {
  function TestConfig_setupAgentsWithDisabledTools (line 478) | func TestConfig_setupAgentsWithDisabledTools(t *testing.T) {
  function TestConfig_setupAgentsWithEveryReadOnlyToolDisabled (line 500) | func TestConfig_setupAgentsWithEveryReadOnlyToolDisabled(t *testing.T) {
  function TestConfig_configureProvidersWithDisabledProvider (line 523) | func TestConfig_configureProvidersWithDisabledProvider(t *testing.T) {
  function TestConfig_configureProvidersCustomProviderValidation (line 557) | func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
  function TestConfig_configureProvidersEnhancedCredentialValidation (line 738) | func TestConfig_configureProvidersEnhancedCredentialValidation(t *testin...
  function TestConfig_defaultModelSelection (line 868) | func TestConfig_defaultModelSelection(t *testing.T) {
  function TestConfig_configureProvidersDisableDefaultProviders (line 1101) | func TestConfig_configureProvidersDisableDefaultProviders(t *testing.T) {
  function TestConfig_setDefaultsDisableDefaultProvidersEnvVar (line 1290) | func TestConfig_setDefaultsDisableDefaultProvidersEnvVar(t *testing.T) {
  function TestConfig_configureSelectedModels (line 1312) | func TestConfig_configureSelectedModels(t *testing.T) {

FILE: internal/config/lsp_defaults_test.go
  function TestApplyLSPDefaults (line 9) | func TestApplyLSPDefaults(t *testing.T) {

FILE: internal/config/provider.go
  type syncer (line 26) | type syncer interface
  function cachePathFor (line 37) | func cachePathFor(name string) string {
  function UpdateProviders (line 58) | func UpdateProviders(pathOrURL string) error {
  function UpdateHyper (line 93) | func UpdateHyper(pathOrURL string) error {
  function Providers (line 142) | func Providers(cfg *Config) ([]catwalk.Provider, error) {
  type cache (line 194) | type cache struct
  function newCache (line 198) | func newCache[T any](path string) cache[T] {
  method Get (line 202) | func (c cache[T]) Get() (T, string, error) {
  method Store (line 216) | func (c cache[T]) Store(v T) error {

FILE: internal/config/provider_empty_test.go
  type emptyProviderClient (line 12) | type emptyProviderClient struct
    method GetProviders (line 14) | func (m *emptyProviderClient) GetProviders(context.Context, string) ([...
  function TestCatwalkSync_GetEmptyResultFromClient (line 20) | func TestCatwalkSync_GetEmptyResultFromClient(t *testing.T) {

FILE: internal/config/provider_test.go
  function resetProviderState (line 14) | func resetProviderState() {
  function TestProviders_Integration_AutoUpdateDisabled (line 22) | func TestProviders_Integration_AutoUpdateDisabled(t *testing.T) {
  function TestProviders_Integration_WithMockClients (line 55) | func TestProviders_Integration_WithMockClients(t *testing.T) {
  function TestProviders_Integration_WithCachedData (line 100) | func TestProviders_Integration_WithCachedData(t *testing.T) {
  function TestProviders_Integration_CatwalkFailsHyperSucceeds (line 154) | func TestProviders_Integration_CatwalkFailsHyperSucceeds(t *testing.T) {
  function TestProviders_Integration_BothFail (line 190) | func TestProviders_Integration_BothFail(t *testing.T) {
  function TestCache_StoreAndGet (line 220) | func TestCache_StoreAndGet(t *testing.T) {
  function TestCache_GetNonExistent (line 245) | func TestCache_GetNonExistent(t *testing.T) {
  function TestCache_GetInvalidJSON (line 258) | func TestCache_GetInvalidJSON(t *testing.T) {
  function TestCachePathFor (line 273) | func TestCachePathFor(t *testing.T) {

FILE: internal/config/recent_models_test.go
  function readConfigJSON (line 14) | func readConfigJSON(t *testing.T, path string) map[string]any {
  function readRecentModels (line 26) | func readRecentModels(t *testing.T, path string) map[string]any {
  function testStoreWithPath (line 35) | func testStoreWithPath(cfg *Config, dir string) *ConfigStore {
  function TestRecordRecentModel_AddsAndPersists (line 42) | func TestRecordRecentModel_AddsAndPersists(t *testing.T) {
  function TestRecordRecentModel_DedupeAndMoveToFront (line 69) | func TestRecordRecentModel_DedupeAndMoveToFront(t *testing.T) {
  function TestRecordRecentModel_TrimsToMax (line 89) | func TestRecordRecentModel_TrimsToMax(t *testing.T) {
  function TestRecordRecentModel_SkipsEmptyValues (line 134) | func TestRecordRecentModel_SkipsEmptyValues(t *testing.T) {
  function TestRecordRecentModel_NoPersistOnNoop (line 159) | func TestRecordRecentModel_NoPersistOnNoop(t *testing.T) {
  function TestUpdatePreferredModel_UpdatesRecents (line 193) | func TestUpdatePreferredModel_UpdatesRecents(t *testing.T) {
  function TestRecordRecentModel_TypeIsolation (line 215) | func TestRecordRecentModel_TypeIsolation(t *testing.T) {

FILE: internal/config/resolve.go
  type VariableResolver (line 13) | type VariableResolver interface
  type Shell (line 17) | type Shell interface
  type shellVariableResolver (line 21) | type shellVariableResolver struct
    method ResolveValue (line 41) | func (r *shellVariableResolver) ResolveValue(value string) (string, er...
  function NewShellVariableResolver (line 26) | func NewShellVariableResolver(env env.Env) VariableResolver {
  type environmentVariableResolver (line 154) | type environmentVariableResolver struct
    method ResolveValue (line 165) | func (r *environmentVariableResolver) ResolveValue(value string) (stri...
  function NewEnvironmentVariableResolver (line 158) | func NewEnvironmentVariableResolver(env env.Env) VariableResolver {

FILE: internal/config/resolve_test.go
  type mockShell (line 13) | type mockShell struct
    method Exec (line 17) | func (m *mockShell) Exec(ctx context.Context, command string) (stdout,...
  function TestShellVariableResolver_ResolveValue (line 24) | func TestShellVariableResolver_ResolveValue(t *testing.T) {
  function TestShellVariableResolver_EnhancedResolveValue (line 97) | func TestShellVariableResolver_EnhancedResolveValue(t *testing.T) {
  function TestEnvironmentVariableResolver_ResolveValue (line 262) | func TestEnvironmentVariableResolver_ResolveValue(t *testing.T) {
  function TestNewShellVariableResolver (line 318) | func TestNewShellVariableResolver(t *testing.T) {
  function TestNewEnvironmentVariableResolver (line 326) | func TestNewEnvironmentVariableResolver(t *testing.T) {

FILE: internal/config/scope.go
  type Scope (line 4) | type Scope
  constant ScopeGlobal (line 8) | ScopeGlobal Scope = iota
  constant ScopeWorkspace (line 10) | ScopeWorkspace

FILE: internal/config/store.go
  type ConfigStore (line 24) | type ConfigStore struct
    method Config (line 34) | func (s *ConfigStore) Config() *Config {
    method WorkingDir (line 39) | func (s *ConfigStore) WorkingDir() string {
    method Resolver (line 44) | func (s *ConfigStore) Resolver() VariableResolver {
    method Resolve (line 49) | func (s *ConfigStore) Resolve(key string) (string, error) {
    method KnownProviders (line 57) | func (s *ConfigStore) KnownProviders() []catwalk.Provider {
    method SetupAgents (line 62) | func (s *ConfigStore) SetupAgents() {
    method configPath (line 67) | func (s *ConfigStore) configPath(scope Scope) string {
    method HasConfigField (line 78) | func (s *ConfigStore) HasConfigField(scope Scope, key string) bool {
    method SetConfigField (line 87) | func (s *ConfigStore) SetConfigField(scope Scope, key string, value an...
    method RemoveConfigField (line 112) | func (s *ConfigStore) RemoveConfigField(scope Scope, key string) error {
    method UpdatePreferredModel (line 134) | func (s *ConfigStore) UpdatePreferredModel(scope Scope, modelType Sele...
    method SetCompactMode (line 146) | func (s *ConfigStore) SetCompactMode(scope Scope, enabled bool) error {
    method SetTransparentBackground (line 155) | func (s *ConfigStore) SetTransparentBackground(scope Scope, enabled bo...
    method SetProviderAPIKey (line 164) | func (s *ConfigStore) SetProviderAPIKey(scope Scope, providerID string...
    method RefreshOAuthToken (line 227) | func (s *ConfigStore) RefreshOAuthToken(ctx context.Context, scope Sco...
    method recordRecentModel (line 273) | func (s *ConfigStore) recordRecentModel(scope Scope, modelType Selecte...
    method ImportCopilot (line 315) | func (s *ConfigStore) ImportCopilot() (*oauth.Token, bool) {

FILE: internal/csync/maps.go
  type Map (line 11) | type Map struct
  function NewMap (line 17) | func NewMap[K comparable, V any]() *Map[K, V] {
  function NewMapFrom (line 24) | func NewMapFrom[K comparable, V any](m map[K]V) *Map[K, V] {
  function NewLazyMap (line 32) | func NewLazyMap[K comparable, V any](load func() map[K]V) *Map[K, V] {
  method Reset (line 43) | func (m *Map[K, V]) Reset(input map[K]V) {
  method Set (line 50) | func (m *Map[K, V]) Set(key K, value V) {
  method Del (line 57) | func (m *Map[K, V]) Del(key K) {
  method Get (line 64) | func (m *Map[K, V]) Get(key K) (V, bool) {
  method Len (line 72) | func (m *Map[K, V]) Len() int {
  method GetOrSet (line 80) | func (m *Map[K, V]) GetOrSet(key K, fn func() V) V {
  method Take (line 91) | func (m *Map[K, V]) Take(key K) (V, bool) {
  method Copy (line 100) | func (m *Map[K, V]) Copy() map[K]V {
  method Seq2 (line 107) | func (m *Map[K, V]) Seq2() iter.Seq2[K, V] {
  method Seq (line 119) | func (m *Map[K, V]) Seq() iter.Seq[V] {
  method JSONSchemaAlias (line 134) | func (Map[K, V]) JSONSchemaAlias() any { //nolint
  method UnmarshalJSON (line 140) | func (m *Map[K, V]) UnmarshalJSON(data []byte) error {
  method MarshalJSON (line 148) | func (m *Map[K, V]) MarshalJSON() ([]byte, error) {

FILE: internal/csync/maps_test.go
  function TestNewMap (line 15) | func TestNewMap(t *testing.T) {
  function TestNewMapFrom (line 24) | func TestNewMapFrom(t *testing.T) {
  function TestNewLazyMap (line 42) | func TestNewLazyMap(t *testing.T) {
  function TestMap_Reset (line 76) | func TestMap_Reset(t *testing.T) {
  function TestMap_Set (line 92) | func TestMap_Set(t *testing.T) {
  function TestMap_GetOrSet (line 110) | func TestMap_GetOrSet(t *testing.T) {
  function TestMap_Get (line 120) | func TestMap_Get(t *testing.T) {
  function TestMap_Del (line 135) | func TestMap_Del(t *testing.T) {
  function TestMap_Len (line 157) | func TestMap_Len(t *testing.T) {
  function TestMap_Take (line 176) | func TestMap_Take(t *testing.T) {
  function TestMap_Take_NonexistentKey (line 198) | func TestMap_Take_NonexistentKey(t *testing.T) {
  function TestMap_Take_EmptyMap (line 214) | func TestMap_Take_EmptyMap(t *testing.T) {
  function TestMap_Take_SameKeyTwice (line 225) | func TestMap_Take_SameKeyTwice(t *testing.T) {
  function TestMap_Seq2 (line 242) | func TestMap_Seq2(t *testing.T) {
  function TestMap_Seq2_EarlyReturn (line 258) | func TestMap_Seq2_EarlyReturn(t *testing.T) {
  function TestMap_Seq2_EmptyMap (line 277) | func TestMap_Seq2_EmptyMap(t *testing.T) {
  function TestMap_Seq (line 290) | func TestMap_Seq(t *testing.T) {
  function TestMap_Seq_EarlyReturn (line 309) | func TestMap_Seq_EarlyReturn(t *testing.T) {
  function TestMap_Seq_EmptyMap (line 328) | func TestMap_Seq_EmptyMap(t *testing.T) {
  function TestMap_MarshalJSON (line 341) | func TestMap_MarshalJSON(t *testing.T) {
  function TestMap_MarshalJSON_EmptyMap (line 361) | func TestMap_MarshalJSON_EmptyMap(t *testing.T) {
  function TestMap_UnmarshalJSON (line 371) | func TestMap_UnmarshalJSON(t *testing.T) {
  function TestMap_UnmarshalJSON_EmptyJSON (line 390) | func TestMap_UnmarshalJSON_EmptyJSON(t *testing.T) {
  function TestMap_UnmarshalJSON_InvalidJSON (line 401) | func TestMap_UnmarshalJSON_InvalidJSON(t *testing.T) {
  function TestMap_UnmarshalJSON_OverwritesExistingData (line 411) | func TestMap_UnmarshalJSON_OverwritesExistingData(t *testing.T) {
  function TestMap_JSONRoundTrip (line 430) | func TestMap_JSONRoundTrip(t *testing.T) {
  function TestMap_ConcurrentAccess (line 454) | func TestMap_ConcurrentAccess(t *testing.T) {
  function TestMap_ConcurrentReadWrite (line 482) | func TestMap_ConcurrentReadWrite(t *testing.T) {
  function TestMap_ConcurrentSeq2 (line 527) | func TestMap_ConcurrentSeq2(t *testing.T) {
  function TestMap_ConcurrentSeq (line 554) | func TestMap_ConcurrentSeq(t *testing.T) {
  function TestMap_ConcurrentTake (line 585) | func TestMap_ConcurrentTake(t *testing.T) {
  function TestMap_TypeSafety (line 630) | func TestMap_TypeSafety(t *testing.T) {
  function TestMap_InterfaceCompliance (line 652) | func TestMap_InterfaceCompliance(t *testing.T) {
  function BenchmarkMap_Set (line 659) | func BenchmarkMap_Set(b *testing.B) {
  function BenchmarkMap_Get (line 667) | func BenchmarkMap_Get(b *testing.B) {
  function BenchmarkMap_Seq2 (line 678) | func BenchmarkMap_Seq2(b *testing.B) {
  function BenchmarkMap_Seq (line 690) | func BenchmarkMap_Seq(b *testing.B) {
  function BenchmarkMap_Take (line 702) | func BenchmarkMap_Take(b *testing.B) {
  function BenchmarkMap_ConcurrentReadWrite (line 722) | func BenchmarkMap_ConcurrentReadWrite(b *testing.B) {

FILE: internal/csync/slices.go
  type LazySlice (line 9) | type LazySlice struct
  function NewLazySlice (line 16) | func NewLazySlice[K any](load func() []K) *LazySlice[K] {
  method Seq (line 25) | func (s *LazySlice[K]) Seq() iter.Seq[K] {
  type Slice (line 37) | type Slice struct
  function NewSlice (line 43) | func NewSlice[T any]() *Slice[T] {
  function NewSliceFrom (line 50) | func NewSliceFrom[T any](s []T) *Slice[T] {
  method Append (line 59) | func (s *Slice[T]) Append(items ...T) {
  method Get (line 66) | func (s *Slice[T]) Get(index int) (T, bool) {
  method Len (line 77) | func (s *Slice[T]) Len() int {
  method SetSlice (line 84) | func (s *Slice[T]) SetSlice(items []T) {
  method Seq (line 92) | func (s *Slice[T]) Seq() iter.Seq[T] {
  method Seq2 (line 103) | func (s *Slice[T]) Seq2() iter.Seq2[int, T] {
  method Copy (line 115) | func (s *Slice[T]) Copy() []T {

FILE: internal/csync/slices_test.go
  function TestLazySlice_Seq (line 14) | func TestLazySlice_Seq(t *testing.T) {
  function TestLazySlice_SeqWaitsForLoading (line 28) | func TestLazySlice_SeqWaitsForLoading(t *testing.T) {
  function TestLazySlice_EmptySlice (line 48) | func TestLazySlice_EmptySlice(t *testing.T) {
  function TestLazySlice_EarlyBreak (line 56) | func TestLazySlice_EarlyBreak(t *testing.T) {
  function TestSlice (line 79) | func TestSlice(t *testing.T) {

FILE: internal/csync/value.go
  type Value (line 11) | type Value struct
  function NewValue (line 19) | func NewValue[T any](t T) *Value[T] {
  method Get (line 33) | func (v *Value[T]) Get() T {
  method Set (line 40) | func (v *Value[T]) Set(t T) {

FILE: internal/csync/value_test.go
  function TestValue_GetSet (line 10) | func TestValue_GetSet(t *testing.T) {
  function TestValue_ZeroValue (line 20) | func TestValue_ZeroValue(t *testing.T) {
  function TestValue_Struct (line 30) | func TestValue_Struct(t *testing.T) {
  function TestValue_PointerPanics (line 45) | func TestValue_PointerPanics(t *testing.T) {
  function TestValue_SlicePanics (line 53) | func TestValue_SlicePanics(t *testing.T) {
  function TestValue_MapPanics (line 61) | func TestValue_MapPanics(t *testing.T) {
  function TestValue_ConcurrentAccess (line 69) | func TestValue_ConcurrentAccess(t *testing.T) {

FILE: internal/csync/versionedmap.go
  function NewVersionedMap (line 9) | func NewVersionedMap[K comparable, V any]() *VersionedMap[K, V] {
  type VersionedMap (line 16) | type VersionedMap struct
  method Get (line 22) | func (m *VersionedMap[K, V]) Get(key K) (V, bool) {
  method Set (line 27) | func (m *VersionedMap[K, V]) Set(key K, value V) {
  method Del (line 33) | func (m *VersionedMap[K, V]) Del(key K) {
  method Seq2 (line 39) | func (m *VersionedMap[K, V]) Seq2() iter.Seq2[K, V] {
  method Copy (line 44) | func (m *VersionedMap[K, V]) Copy() map[K]V {
  method Len (line 49) | func (m *VersionedMap[K, V]) Len() int {
  method Version (line 54) | func (m *VersionedMap[K, V]) Version() uint64 {

FILE: internal/csync/versionedmap_test.go
  function TestVersionedMap_Set (line 9) | func TestVersionedMap_Set(t *testing.T) {
  function TestVersionedMap_Del (line 23) | func TestVersionedMap_Del(t *testing.T) {
  function TestVersionedMap_VersionIncrement (line 37) | func TestVersionedMap_VersionIncrement(t *testing.T) {
  function TestVersionedMap_ConcurrentAccess (line 56) | func TestVersionedMap_ConcurrentAccess(t *testing.T) {

FILE: internal/db/connect.go
  function Connect (line 24) | func Connect(ctx context.Context, dataDir string) (*sql.DB, error) {

FILE: internal/db/connect_modernc.go
  function openDB (line 13) | func openDB(dbPath string) (*sql.DB, error) {

FILE: internal/db/connect_ncruces.go
  function openDB (line 14) | func openDB(dbPath string) (*sql.DB, error) {

FILE: internal/db/db.go
  type DBTX (line 13) | type DBTX interface
  function New (line 20) | func New(db DBTX) *Queries {
  function Prepare (line 24) | func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
  type Queries (line 364) | type Queries struct
    method Close (line 141) | func (q *Queries) Close() error {
    method exec (line 331) | func (q *Queries) exec(ctx context.Context, stmt *sql.Stmt, query stri...
    method query (line 342) | func (q *Queries) query(ctx context.Context, stmt *sql.Stmt, query str...
    method queryRow (line 353) | func (q *Queries) queryRow(ctx context.Context, stmt *sql.Stmt, query ...
    method WithTx (line 406) | func (q *Queries) WithTx(tx *sql.Tx) *Queries {

FILE: internal/db/files.sql.go
  constant createFile (line 12) | createFile = `-- name: CreateFile :one
  type CreateFileParams (line 27) | type CreateFileParams struct
  method CreateFile (line 35) | func (q *Queries) CreateFile(ctx context.Context, arg CreateFileParams) ...
  constant deleteFile (line 56) | deleteFile = `-- name: DeleteFile :exec
  method DeleteFile (line 61) | func (q *Queries) DeleteFile(ctx context.Context, id string) error {
  constant deleteSessionFiles (line 66) | deleteSessionFiles = `-- name: DeleteSessionFiles :exec
  method DeleteSessionFiles (line 71) | func (q *Queries) DeleteSessionFiles(ctx context.Context, sessionID stri...
  constant getFile (line 76) | getFile = `-- name: GetFile :one
  method GetFile (line 82) | func (q *Queries) GetFile(ctx context.Context, id string) (File, error) {
  constant getFileByPathAndSession (line 97) | getFileByPathAndSession = `-- name: GetFileByPathAndSession :one
  type GetFileByPathAndSessionParams (line 105) | type GetFileByPathAndSessionParams struct
  method GetFileByPathAndSession (line 110) | func (q *Queries) GetFileByPathAndSession(ctx context.Context, arg GetFi...
  constant listFilesByPath (line 125) | listFilesByPath = `-- name: ListFilesByPath :many
  method ListFilesByPath (line 132) | func (q *Queries) ListFilesByPath(ctx context.Context, path string) ([]F...
  constant listFilesBySession (line 163) | listFilesBySession = `-- name: ListFilesBySession :many
  method ListFilesBySession (line 170) | func (q *Queries) ListFilesBySession(ctx context.Context, sessionID stri...
  constant listLatestSessionFiles (line 201) | listLatestSessionFiles = `-- name: ListLatestSessionFiles :many
  method ListLatestSessionFiles (line 213) | func (q *Queries) ListLatestSessionFiles(ctx context.Context, sessionID ...
  constant listNewFiles (line 244) | listNewFiles = `-- name: ListNewFiles :many
  method ListNewFiles (line 251) | func (q *Queries) ListNewFiles(ctx context.Context) ([]File, error) {

FILE: internal/db/messages.sql.go
  constant createMessage (line 13) | createMessage = `-- name: CreateMessage :one
  type CreateMessageParams (line 30) | type CreateMessageParams struct
  method CreateMessage (line 40) | func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessagePa...
  constant deleteMessage (line 66) | deleteMessage = `-- name: DeleteMessage :exec
  method DeleteMessage (line 71) | func (q *Queries) DeleteMessage(ctx context.Context, id string) error {
  constant deleteSessionMessages (line 76) | deleteSessionMessages = `-- name: DeleteSessionMessages :exec
  method DeleteSessionMessages (line 81) | func (q *Queries) DeleteSessionMessages(ctx context.Context, sessionID s...
  constant getMessage (line 86) | getMessage = `-- name: GetMessage :one
  method GetMessage (line 92) | func (q *Queries) GetMessage(ctx context.Context, id string) (Message, e...
  constant listAllUserMessages (line 110) | listAllUserMessages = `-- name: ListAllUserMessages :many
  method ListAllUserMessages (line 117) | func (q *Queries) ListAllUserMessages(ctx context.Context) ([]Message, e...
  constant listMessagesBySession (line 151) | listMessagesBySession = `-- name: ListMessagesBySession :many
  method ListMessagesBySession (line 158) | func (q *Queries) ListMessagesBySession(ctx context.Context, sessionID s...
  constant listUserMessagesBySession (line 192) | listUserMessagesBySession = `-- name: ListUserMessagesBySession :many
  method ListUserMessagesBySession (line 199) | func (q *Queries) ListUserMessagesBySession(ctx context.Context, session...
  constant updateMessage (line 233) | updateMessage = `-- name: UpdateMessage :exec
  type UpdateMessageParams (line 242) | type UpdateMessageParams struct
  method UpdateMessage (line 248) | func (q *Queries) UpdateMessage(ctx context.Context, arg UpdateMessagePa...

FILE: internal/db/migrations/20250424200609_initial.sql
  type sessions (line 4) | CREATE TABLE IF NOT EXISTS sessions (

FILE: internal/db/migrations/20250624000000_add_created_at_indexes.sql
  type idx_sessions_created_at (line 4) | CREATE INDEX IF NOT EXISTS idx_sessions_created_at ON sessions (created_at)
  type idx_messages_created_at (line 5) | CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages (created_at)
  type idx_files_created_at (line 6) | CREATE INDEX IF NOT EXISTS idx_files_created_at ON files (created_at)

FILE: internal/db/migrations/20260127000000_add_read_files_table.sql
  type read_files (line 3) | CREATE TABLE IF NOT EXISTS read_files (
  type idx_read_files_session_id (line 11) | CREATE INDEX IF NOT EXISTS idx_read_files_session_id ON read_files (sess...
  type idx_read_files_path (line 12) | CREATE INDEX IF NOT EXISTS idx_read_files_path ON read_files (path)

FILE: internal/db/models.go
  type File (line 11) | type File struct
  type Message (line 21) | type Message struct
  type ReadFile (line 34) | type ReadFile struct
  type Session (line 40) | type Session struct

FILE: internal/db/querier.go
  type Querier (line 11) | type Querier interface

FILE: internal/db/read_files.sql.go
  constant getFileRead (line 12) | getFileRead = `-- name: GetFileRead :one
  type GetFileReadParams (line 17) | type GetFileReadParams struct
  method GetFileRead (line 22) | func (q *Queries) GetFileRead(ctx context.Context, arg GetFileReadParams...
  constant listSessionReadFiles (line 29) | listSessionReadFiles = `-- name: ListSessionReadFiles :many
  method ListSessionReadFiles (line 35) | func (q *Queries) ListSessionReadFiles(ctx context.Context, sessionID st...
  constant recordFileRead (line 58) | recordFileRead = `-- name: RecordFileRead :exec
  type RecordFileReadParams (line 71) | type RecordFileReadParams struct
  method RecordFileRead (line 76) | func (q *Queries) RecordFileRead(ctx context.Context, arg RecordFileRead...

FILE: internal/db/sessions.sql.go
  constant createSession (line 13) | createSession = `-- name: CreateSession :one
  type CreateSessionParams (line 39) | type CreateSessionParams struct
  method CreateSession (line 49) | func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionPa...
  constant deleteSession (line 76) | deleteSession = `-- name: DeleteSession :exec
  method DeleteSession (line 81) | func (q *Queries) DeleteSession(ctx context.Context, id string) error {
  constant getLastSession (line 86) | getLastSession = `-- name: GetLastSession :one
  method GetLastSession (line 93) | func (q *Queries) GetLastSession(ctx context.Context) (Session, error) {
  constant getSessionByID (line 112) | getSessionByID = `-- name: GetSessionByID :one
  method GetSessionByID (line 118) | func (q *Queries) GetSessionByID(ctx context.Context, id string) (Sessio...
  constant listSessions (line 137) | listSessions = `-- name: ListSessions :many
  method ListSessions (line 144) | func (q *Queries) ListSessions(ctx context.Context) ([]Session, error) {
  constant renameSession (line 179) | renameSession = `-- name: RenameSession :exec
  type RenameSessionParams (line 186) | type RenameSessionParams struct
  method RenameSession (line 191) | func (q *Queries) RenameSession(ctx context.Context, arg RenameSessionPa...
  constant updateSession (line 196) | updateSession = `-- name: UpdateSession :one
  type UpdateSessionParams (line 209) | type UpdateSessionParams struct
  method UpdateSession (line 219) | func (q *Queries) UpdateSession(ctx context.Context, arg UpdateSessionPa...
  constant updateSessionTitleAndUsage (line 246) | updateSessionTitleAndUsage = `-- name: UpdateSessionTitleAndUsage :exec
  type UpdateSessionTitleAndUsageParams (line 257) | type UpdateSessionTitleAndUsageParams struct
  method UpdateSessionTitleAndUsage (line 265) | func (q *Queries) UpdateSessionTitleAndUsage(ctx context.Context, arg Up...

FILE: internal/db/stats.sql.go
  constant getAverageResponseTime (line 13) | getAverageResponseTime = `-- name: GetAverageResponseTime :one
  method GetAverageResponseTime (line 22) | func (q *Queries) GetAverageResponseTime(ctx context.Context) (int64, er...
  constant getHourDayHeatmap (line 29) | getHourDayHeatmap = `-- name: GetHourDayHeatmap :many
  type GetHourDayHeatmapRow (line 40) | type GetHourDayHeatmapRow struct
  method GetHourDayHeatmap (line 46) | func (q *Queries) GetHourDayHeatmap(ctx context.Context) ([]GetHourDayHe...
  constant getRecentActivity (line 69) | getRecentActivity = `-- name: GetRecentActivity :many
  type GetRecentActivityRow (line 82) | type GetRecentActivityRow struct
  method GetRecentActivity (line 89) | func (q *Queries) GetRecentActivity(ctx context.Context) ([]GetRecentAct...
  constant getToolUsage (line 117) | getToolUsage = `-- name: GetToolUsage :many
  type GetToolUsageRow (line 128) | type GetToolUsageRow struct
  method GetToolUsage (line 133) | func (q *Queries) GetToolUsage(ctx context.Context) ([]GetToolUsageRow, ...
  constant getTotalStats (line 156) | getTotalStats = `-- name: GetTotalStats :one
  type GetTotalStatsRow (line 169) | type GetTotalStatsRow struct
  method GetTotalStats (line 179) | func (q *Queries) GetTotalStats(ctx context.Context) (GetTotalStatsRow, ...
  constant getUsageByDay (line 194) | getUsageByDay = `-- name: GetUsageByDay :many
  type GetUsageByDayRow (line 207) | type GetUsageByDayRow struct
  method GetUsageByDay (line 215) | func (q *Queries) GetUsageByDay(ctx context.Context) ([]GetUsageByDayRow...
  constant getUsageByDayOfWeek (line 244) | getUsageByDayOfWeek = `-- name: GetUsageByDayOfWeek :many
  type GetUsageByDayOfWeekRow (line 256) | type GetUsageByDayOfWeekRow struct
  method GetUsageByDayOfWeek (line 263) | func (q *Queries) GetUsageByDayOfWeek(ctx context.Context) ([]GetUsageBy...
  constant getUsageByHour (line 291) | getUsageByHour = `-- name: GetUsageByHour :many
  type GetUsageByHourRow (line 301) | type GetUsageByHourRow struct
  method GetUsageByHour (line 306) | func (q *Queries) GetUsageByHour(ctx context.Context) ([]GetUsageByHourR...
  constant getUsageByModel (line 329) | getUsageByModel = `-- name: GetUsageByModel :many
  type GetUsageByModelRow (line 340) | type GetUsageByModelRow struct
  method GetUsageByModel (line 346) | func (q *Queries) GetUsageByModel(ctx context.Context) ([]GetUsageByMode...

FILE: internal/diff/diff.go
  function GenerateDiff (line 10) | func GenerateDiff(beforeContent, afterContent, fileName string) (string,...

FILE: internal/env/env.go
  type Env (line 7) | type Env interface
  type osEnv (line 12) | type osEnv struct
    method Get (line 15) | func (o *osEnv) Get(key string) string {
    method Env (line 19) | func (o *osEnv) Env() []string {
  function New (line 23) | func New() Env {
  type mapEnv (line 27) | type mapEnv struct
    method Get (line 32) | func (m *mapEnv) Get(key string) string {
    method Env (line 40) | func (m *mapEnv) Env() []string {
  function NewFromMap (line 48) | func NewFromMap(m map[string]string) Env {

FILE: internal/env/env_test.go
  function TestOsEnv_Get (line 10) | func TestOsEnv_Get(t *testing.T) {
  function TestOsEnv_Env (line 24) | func TestOsEnv_Env(t *testing.T) {
  function TestNewFromMap (line 39) | func TestNewFromMap(t *testing.T) {
  function TestMapEnv_Get (line 50) | func TestMapEnv_Get(t *testing.T) {
  function TestMapEnv_Env (line 66) | func TestMapEnv_Env(t *testing.T) {
  function TestMapEnv_GetEmptyValue (line 105) | func TestMapEnv_GetEmptyValue(t *testing.T) {
  function TestMapEnv_EnvFormat (line 118) | func TestMapEnv_EnvFormat(t *testing.T) {

FILE: internal/event/all.go
  function AppInitialized (line 9) | func AppInitialized() {
  function AppExited (line 14) | func AppExited() {
  function SessionCreated (line 24) | func SessionCreated() {
  function SessionDeleted (line 28) | func SessionDeleted() {
  function SessionSwitched (line 32) | func SessionSwitched() {
  function FilePickerOpened (line 36) | func FilePickerOpened() {
  function PromptSent (line 40) | func PromptSent(props ...any) {
  function PromptResponded (line 47) | func PromptResponded(props ...any) {
  function TokensUsed (line 54) | func TokensUsed(props ...any) {
  function StatsViewed (line 61) | func StatsViewed() {
  function SessionListed (line 65) | func SessionListed(json bool) {
  function SessionShown (line 69) | func SessionShown(json bool) {
  function SessionLastShown (line 73) | func SessionLastShown(json bool) {
  function SessionDeletedCommand (line 77) | func SessionDeletedCommand(json bool) {
  function SessionRenamed (line 81) | func SessionRenamed(json bool) {

FILE: internal/event/event.go
  constant endpoint (line 17) | endpoint = "https://data.charm.land"
  constant key (line 18) | key      = "phc_4zt4VgDWLqbYnJYEwLRxFoaTL2noNrQij0C6E8k3I0V"
  constant nonInteractiveAttrName (line 20) | nonInteractiveAttrName      = "NonInteractive"
  constant continueSessionByIDAttrName (line 21) | continueSessionByIDAttrName = "ContinueSessionByID"
  constant continueLastSessionAttrName (line 22) | continueLastSessionAttrName = "ContinueLastSession"
  function SetNonInteractive (line 38) | func SetNonInteractive(nonInteractive bool) {
  function SetContinueBySessionID (line 42) | func SetContinueBySessionID(continueBySessionID bool) {
  function SetContinueLastSession (line 46) | func SetContinueLastSession(continueLastSession bool) {
  function Init (line 50) | func Init() {
  function GetID (line 63) | func GetID() string { return distinctId }
  function Alias (line 65) | func Alias(userID string) {
  function send (line 80) | func send(event string, props ...any) {
  function Error (line 96) | func Error(errToLog any, props ...any) {
  function Flush (line 112) | func Flush() {
  function pairsToProps (line 121) | func pairsToProps(props ...any) posthog.Properties {
  function isEven (line 137) | func isEven(n int) bool {

FILE: internal/event/event_test.go
  function TestError (line 10) | func TestError(t *testing.T) {
  function newDefaultTestError (line 66) | func newDefaultTestError(s string) error {
  type testError (line 70) | type testError
    method Error (line 72) | func (e testError) Error() string {

FILE: internal/event/identifier.go
  constant hashKey (line 16) | hashKey    = "charm"
  constant fallbackId (line 17) | fallbackId = "unknown"
  function getDistinctId (line 20) | func getDistinctId() string {
  function getMacAddr (line 30) | func getMacAddr() (string, error) {
  function hashString (line 45) | func hashString(str string) string {

FILE: internal/event/logger.go
  type logger (line 12) | type logger struct
    method Debugf (line 14) | func (logger) Debugf(format string, args ...any) {
    method Logf (line 18) | func (logger) Logf(format string, args ...any) {
    method Warnf (line 22) | func (logger) Warnf(format string, args ...any) {
    method Errorf (line 26) | func (logger) Errorf(format string, args ...any) {

FILE: internal/filepathext/filepath.go
  function SmartJoin (line 11) | func SmartJoin(one, two string) string {
  function SmartIsAbs (line 20) | func SmartIsAbs(path string) bool {

FILE: internal/filetracker/service.go
  type Service (line 16) | type Service interface
  type service (line 28) | type service struct
    method RecordRead (line 38) | func (s *service) RecordRead(ctx context.Context, sessionID, path stri...
    method LastReadTime (line 49) | func (s *service) LastReadTime(ctx context.Context, sessionID, path st...
    method ListReadFiles (line 77) | func (s *service) ListReadFiles(ctx context.Context, sessionID string)...
  function NewService (line 33) | func NewService(q *db.Queries) Service {
  function relpath (line 61) | func relpath(path string) string {

FILE: internal/filetracker/service_test.go
  type testEnv (line 13) | type testEnv struct
    method createSession (line 34) | func (e *testEnv) createSession(t *testing.T, sessionID string) {
  function setupTest (line 19) | func setupTest(t *testing.T) *testEnv {
  function TestService_RecordRead (line 43) | func TestService_RecordRead(t *testing.T) {
  function TestService_LastReadTime_NotFound (line 57) | func TestService_LastReadTime_NotFound(t *testing.T) {
  function TestService_RecordRead_UpdatesTimestamp (line 64) | func TestService_RecordRead_UpdatesTimestamp(t *testing.T) {
  function TestService_RecordRead_DifferentSessions (line 85) | func TestService_RecordRead_DifferentSessions(t *testing.T) {
  function TestService_RecordRead_DifferentPaths (line 102) | func TestService_RecordRead_DifferentPaths(t *testing.T) {

FILE: internal/format/spinner.go
  type Spinner (line 15) | type Spinner struct
    method Start (line 60) | func (s *Spinner) Start() {
    method Stop (line 73) | func (s *Spinner) Stop() {
  type model (line 20) | type model struct
    method Init (line 25) | func (m model) Init() tea.Cmd  { return m.anim.Start() }
    method View (line 26) | func (m model) View() tea.View { return tea.NewView(m.anim.Render()) }
    method Update (line 29) | func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  function NewSpinner (line 45) | func NewSpinner(ctx context.Context, cancel context.CancelFunc, animSett...

FILE: internal/fsext/drive_other.go
  function WindowsWorkingDirDrive (line 9) | func WindowsWorkingDirDrive() string {
  function WindowsSystemDrive (line 14) | func WindowsSystemDrive() string {

FILE: internal/fsext/drive_windows.go
  function WindowsWorkingDirDrive (line 15) | func WindowsWorkingDirDrive() string {
  function WindowsSystemDrive (line 23) | func WindowsSystemDrive() string {

FILE: internal/fsext/expand.go
  function Expand (line 14) | func Expand(s string) (string, error) {

FILE: internal/fsext/fileutil.go
  type FileInfo (line 18) | type FileInfo struct
  function SkipHidden (line 23) | func SkipHidden(path string) bool {
  type FastGlobWalker (line 63) | type FastGlobWalker struct
    method ShouldSkip (line 75) | func (w *FastGlobWalker) ShouldSkip(path string) bool {
    method ShouldSkipDir (line 81) | func (w *FastGlobWalker) ShouldSkipDir(path string) bool {
  function NewFastGlobWalker (line 67) | func NewFastGlobWalker(searchPath string) *FastGlobWalker {
  function Glob (line 88) | func Glob(pattern string, cwd string, limit int) ([]string, bool, error) {
  function GlobGitignoreAware (line 93) | func GlobGitignoreAware(pattern string, cwd string, limit int) ([]string...
  function globWithDoubleStar (line 97) | func globWithDoubleStar(pattern, searchPath string, limit int, gitignore...
  function ShouldExcludeFile (line 168) | func ShouldExcludeFile(rootPath, filePath string) bool {
  function PrettyPath (line 175) | func PrettyPath(path string) string {
  function DirTrim (line 179) | func DirTrim(pwd string, lim int) string {
  function PathOrPrefix (line 205) | func PathOrPrefix(path, prefix string) string {
  function HasPrefix (line 214) | func HasPrefix(path, prefix string) bool {
  function ToUnixLineEndings (line 224) | func ToUnixLineEndings(content string) (string, bool) {
  function ToWindowsLineEndings (line 232) | func ToWindowsLineEndings(content string) (string, bool) {
  function truncate (line 239) | func truncate[T any](input []T, limit int) ([]T, bool) {

FILE: internal/fsext/fileutil_test.go
  function TestGlobWithDoubleStar (line 13) | func TestGlobWithDoubleStar(t *testing.T) {

FILE: internal/fsext/ignore_test.go
  function TestCrushIgnore (line 11) | func TestCrushIgnore(t *testing.T) {
  function TestShouldExcludeFile (line 29) | func TestShouldExcludeFile(t *testing.T) {
  function TestShouldExcludeFileHierarchical (line 71) | func TestShouldExcludeFileHierarchical(t *testing.T) {
  function TestShouldExcludeFileCommonPatterns (line 98) | func TestShouldExcludeFileCommonPatterns(t *testing.T) {

FILE: internal/fsext/lookup.go
  function Lookup (line 19) | func Lookup(dir string, targets ...string) ([]string, error) {
  function LookupClosest (line 59) | func LookupClosest(dir, target string) (string, bool) {
  function traverseUp (line 88) | func traverseUp(dir string, walkFn func(dir string, owner int) error) er...
  function probeEnt (line 120) | func probeEnt(fspath string, owner int) error {

FILE: internal/fsext/lookup_test.go
  function TestLookupClosest (line 13) | func TestLookupClosest(t *testing.T) {
  function TestLookupClosestWithOwnership (line 125) | func TestLookupClosestWithOwnership(t *testing.T) {
  function TestLookup (line 153) | func TestLookup(t *testing.T) {
  function TestProbeEnt (line 356) | func TestProbeEnt(t *testing.T) {

FILE: internal/fsext/ls.go
  function parsePatterns (line 100) | func parsePatterns(lines []string, domain []string) []gitignore.Pattern {
  type directoryLister (line 112) | type directoryLister struct
    method getDirPatterns (line 141) | func (dl *directoryLister) getDirPatterns(dir string) []gitignore.Patt...
    method getCombinedMatcher (line 165) | func (dl *directoryLister) getCombinedMatcher(dir string) gitignore.Ma...
    method shouldIgnore (line 197) | func (dl *directoryLister) shouldIgnore(path string, ignorePatterns []...
  function NewDirectoryLister (line 122) | func NewDirectoryLister(rootPath string) *directoryLister {
  function pathToComponents (line 131) | func pathToComponents(path string) []string {
  function ListDirectory (line 242) | func ListDirectory(initialPath string, ignorePatterns []string, depth, l...

FILE: internal/fsext/ls_test.go
  function TestListDirectory (line 11) | func TestListDirectory(t *testing.T) {
  function relPaths (line 51) | func relPaths(tb testing.TB, in []string, base string) []string {

FILE: internal/fsext/owner_others.go
  function Owner (line 12) | func Owner(path string) (int, error) {

FILE: internal/fsext/owner_windows.go
  function Owner (line 9) | func Owner(path string) (int, error) {

FILE: internal/fsext/paste.go
  function ParsePastedFiles (line 8) | func ParsePastedFiles(s string) []string {
  function attemptStat (line 24) | func attemptStat(s string) bool {
  function windowsTerminalParsePastedFiles (line 33) | func windowsTerminalParsePastedFiles(s string) []string {
  function unixParsePastedFiles (line 80) | func unixParsePastedFiles(s string) []string {

FILE: internal/fsext/paste_test.go
  function TestParsePastedFiles (line 9) | func TestParsePastedFiles(t *testing.T) {

FILE: internal/history/file.go
  constant InitialVersion (line 15) | InitialVersion = 0
  type File (line 18) | type File struct
  type Service (line 29) | type Service interface
  type service (line 44) | type service struct
    method Create (line 58) | func (s *service) Create(ctx context.Context, sessionID, path, content...
    method CreateVersion (line 65) | func (s *service) CreateVersion(ctx context.Context, sessionID, path, ...
    method createWithVersion (line 84) | func (s *service) createWithVersion(ctx context.Context, sessionID, pa...
    method Get (line 137) | func (s *service) Get(ctx context.Context, id string) (File, error) {
    method GetByPathAndSession (line 145) | func (s *service) GetByPathAndSession(ctx context.Context, path, sessi...
    method ListBySession (line 156) | func (s *service) ListBySession(ctx context.Context, sessionID string)...
    method ListLatestSessionFiles (line 168) | func (s *service) ListLatestSessionFiles(ctx context.Context, sessionI...
    method Delete (line 180) | func (s *service) Delete(ctx context.Context, id string) error {
    method DeleteSessionFiles (line 193) | func (s *service) DeleteSessionFiles(ctx context.Context, sessionID st...
    method fromDBItem (line 207) | func (s *service) fromDBItem(item db.File) File {
  function NewService (line 50) | func NewService(q *db.Queries, db *sql.DB) Service {

FILE: internal/home/home.go
  function init (line 13) | func init() {
  function Dir (line 20) | func Dir() string {
  function Short (line 25) | func Short(p string) string {
  function Long (line 33) | func Long(p string) string {

FILE: internal/home/home_test.go
  function TestDir (line 10) | func TestDir(t *testing.T) {
  function TestShort (line 14) | func TestShort(t *testing.T) {
  function TestLong (line 21) | func TestLong(t *testing.T) {

FILE: internal/log/http.go
  function NewHTTPClient (line 14) | func NewHTTPClient() *http.Client {
  type HTTPRoundTripLogger (line 23) | type HTTPRoundTripLogger struct
    method RoundTrip (line 28) | func (h *HTTPRoundTripLogger) RoundTrip(req *http.Request) (*http.Resp...
  function bodyToString (line 81) | func bodyToString(body io.ReadCloser) string {
  function formatHeaders (line 99) | func formatHeaders(headers http.Header) map[string][]string {
  function drainBody (line 116) | func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {

FILE: internal/log/http_test.go
  function TestHTTPRoundTripLogger (line 10) | func TestHTTPRoundTripLogger(t *testing.T) {
  function TestFormatHeaders (line 48) | func TestFormatHeaders(t *testing.T) {

FILE: internal/log/log.go
  function Setup (line 21) | func Setup(logFile string, debug bool) {
  function Initialized (line 46) | func Initialized() bool {
  function RecoverPanic (line 50) | func RecoverPanic(name string, cleanup func()) {

FILE: internal/lsp/client.go
  type DiagnosticCounts (line 25) | type DiagnosticCounts struct
  type Client (line 32) | type Client struct
    method Initialize (line 98) | func (c *Client) Initialize(ctx context.Context, workspaceDir string) ...
    method Kill (line 132) | func (c *Client) Kill() { c.client.Kill() }
    method Close (line 136) | func (c *Client) Close(ctx context.Context) error {
    method createPowernapClient (line 163) | func (c *Client) createPowernapClient() error {
    method registerHandlers (line 196) | func (c *Client) registerHandlers() {
    method Restart (line 211) | func (c *Client) Restart() error {
    method GetServerState (line 272) | func (c *Client) GetServerState() ServerState {
    method SetServerState (line 280) | func (c *Client) SetServerState(state ServerState) {
    method GetName (line 285) | func (c *Client) GetName() string {
    method SetDiagnosticsCallback (line 290) | func (c *Client) SetDiagnosticsCallback(callback func(name string, cou...
    method WaitForServerReady (line 295) | func (c *Client) WaitForServerReady(ctx context.Context) error {
    method HandlesFile (line 341) | func (c *Client) HandlesFile(path string) bool {
    method OpenFile (line 353) | func (c *Client) OpenFile(ctx context.Context, filepath string) error {
    method NotifyChange (line 384) | func (c *Client) NotifyChange(ctx context.Context, filepath string) er...
    method IsFileOpen (line 416) | func (c *Client) IsFileOpen(filepath string) bool {
    method CloseAllFiles (line 423) | func (c *Client) CloseAllFiles(ctx context.Context) {
    method GetFileDiagnostics (line 437) | func (c *Client) GetFileDiagnostics(uri protocol.DocumentURI) []protoc...
    method GetDiagnostics (line 443) | func (c *Client) GetDiagnostics() map[protocol.DocumentURI][]protocol....
    method GetDiagnosticCounts (line 452) | func (c *Client) GetDiagnosticCounts() DiagnosticCounts {
    method OpenFileOnDemand (line 488) | func (c *Client) OpenFileOnDemand(ctx context.Context, filepath string...
    method RegisterNotificationHandler (line 502) | func (c *Client) RegisterNotificationHandler(method string, handler tr...
    method RegisterServerRequestHandler (line 507) | func (c *Client) RegisterServerRequestHandler(method string, handler t...
    method openKeyConfigFiles (line 512) | func (c *Client) openKeyConfigFiles(ctx context.Context) {
    method WaitForDiagnostics (line 528) | func (c *Client) WaitForDiagnostics(ctx context.Context, d time.Durati...
    method FindReferences (line 551) | func (c *Client) FindReferences(ctx context.Context, filepath string, ...
  function New (line 69) | func New(
  constant closeTimeout (line 129) | closeTimeout = 5 * time.Second
  type ServerState (line 260) | type ServerState
  constant StateUnstarted (line 263) | StateUnstarted ServerState = iota
  constant StateStarting (line 264) | StateStarting
  constant StateReady (line 265) | StateReady
  constant StateError (line 266) | StateError
  constant StateStopped (line 267) | StateStopped
  constant StateDisabled (line 268) | StateDisabled
  type OpenFileInfo (line 334) | type OpenFileInfo struct

FILE: internal/lsp/client_test.go
  function TestClient (line 13) | func TestClient(t *testing.T) {
  function TestNilClient (line 61) | func TestNilClient(t *testing.T) {

FILE: internal/lsp/handlers.go
  function HandleWorkspaceConfiguration (line 14) | func HandleWorkspaceConfiguration(_ context.Context, _ string, params js...
  function HandleRegisterCapability (line 19) | func HandleRegisterCapability(_ context.Context, _ string, params json.R...
  function HandleApplyEdit (line 48) | func HandleApplyEdit(encoding powernap.OffsetEncoding) func(_ context.Co...
  type FileWatchRegistrationHandler (line 66) | type FileWatchRegistrationHandler
  function RegisterFileWatchHandler (line 72) | func RegisterFileWatchHandler(handler FileWatchRegistrationHandler) {
  function notifyFileWatchRegistration (line 77) | func notifyFileWatchRegistration(id string, watchers []protocol.FileSyst...
  function HandleServerMessage (line 84) | func HandleServerMessage(_ context.Context, method string, params json.R...
  function HandleDiagnostics (line 104) | func HandleDiagnostics(client *Client, params json.RawMessage) {

FILE: internal/lsp/manager.go
  type Manager (line 27) | type Manager struct
    method Clients (line 70) | func (s *Manager) Clients() *csync.Map[string, *Client] {
    method SetCallback (line 76) | func (s *Manager) SetCallback(cb func(name string, client *Client)) {
    method TrackConfigured (line 82) | func (s *Manager) TrackConfigured() {
    method Start (line 97) | func (s *Manager) Start(ctx context.Context, path string) {
    method startServer (line 143) | func (s *Manager) startServer(ctx context.Context, name, filepath stri...
    method isUserConfigured (line 246) | func (s *Manager) isUserConfigured(name string) bool {
    method buildConfig (line 251) | func (s *Manager) buildConfig(name string, server *powernapconfig.Serv...
    method KillAll (line 328) | func (s *Manager) KillAll(context.Context) {
    method StopAll (line 343) | func (s *Manager) StopAll(ctx context.Context) {
  function NewManager (line 35) | func NewManager(cfg *config.ConfigStore) *Manager {
  function resolveServerName (line 267) | func resolveServerName(manager *powernapconfig.Manager, name string) str...
  function handlesFiletype (line 279) | func handlesFiletype(sname string, fileTypes []string, filePath string) ...
  function hasRootMarkers (line 301) | func hasRootMarkers(dir string, markers []string) bool {
  function handles (line 317) | func handles(server *powernapconfig.ServerConfig, filePath, workDir stri...

FILE: internal/lsp/util/edit.go
  function applyTextEdits (line 14) | func applyTextEdits(uri protocol.DocumentURI, edits []protocol.TextEdit,...
  function applyTextEdit (line 89) | func applyTextEdit(lines []string, edit protocol.TextEdit, encoding powe...
  function applyDocumentChange (line 171) | func applyDocumentChange(change protocol.DocumentChange, encoding powern...
  function utf32ToByteOffset (line 251) | func utf32ToByteOffset(lineText string, codepointOffset uint32) int {
  function ApplyWorkspaceEdit (line 269) | func ApplyWorkspaceEdit(edit protocol.WorkspaceEdit, encoding powernap.O...
  function rangesOverlap (line 291) | func rangesOverlap(r1, r2 protocol.Range) bool {

FILE: internal/lsp/util/edit_test.go
  function TestPositionToByteOffset (line 11) | func TestPositionToByteOffset(t *testing.T) {
  function TestApplyTextEdit_UTF16 (line 121) | func TestApplyTextEdit_UTF16(t *testing.T) {
  function TestApplyTextEdit_UTF8 (line 265) | func TestApplyTextEdit_UTF8(t *testing.T) {
  function TestRangesOverlap (line 319) | func TestRangesOverlap(t *testing.T) {

FILE: internal/message/attachment.go
  type Attachment (line 8) | type Attachment struct
    method IsText (line 15) | func (a Attachment) IsText() bool  { return strings.HasPrefix(a.MimeTy...
    method IsImage (line 16) | func (a Attachment) IsImage() bool { return strings.HasPrefix(a.MimeTy...
  function ContainsTextAttachment (line 19) | func ContainsTextAttachment(attachments []Attachment) bool {

FILE: internal/message/content.go
  type MessageRole (line 18) | type MessageRole
  constant Assistant (line 21) | Assistant MessageRole = "assistant"
  constant User (line 22) | User      MessageRole = "user"
  constant System (line 23) | System    MessageRole = "system"
  constant Tool (line 24) | Tool      MessageRole = "tool"
  type FinishReason (line 27) | type FinishReason
  constant FinishReasonEndTurn (line 30) | FinishReasonEndTurn          FinishReason = "end_turn"
  constant FinishReasonMaxTokens (line 31) | FinishReasonMaxTokens        FinishReason = "max_tokens"
  constant FinishReasonToolUse (line 32) | FinishReasonToolUse          FinishReason = "tool_use"
  constant FinishReasonCanceled (line 33) | FinishReasonCanceled         FinishReason = "canceled"
  constant FinishReasonError (line 34) | FinishReasonError            FinishReason = "error"
  constant FinishReasonPermissionDenied (line 35) | FinishReasonPermissionDenied FinishReason = "permission_denied"
  constant FinishReasonUnknown (line 38) | FinishReasonUnknown FinishReason = "unknown"
  type ContentPart (line 41) | type ContentPart interface
  type ReasoningContent (line 45) | type ReasoningContent struct
    method String (line 55) | func (tc ReasoningContent) String() string {
    method isPart (line 58) | func (ReasoningContent) isPart() {}
  type TextContent (line 60) | type TextContent struct
    method String (line 64) | func (tc TextContent) String() string {
    method isPart (line 68) | func (TextContent) isPart() {}
  type ImageURLContent (line 70) | type ImageURLContent struct
    method String (line 75) | func (iuc ImageURLContent) String() string {
    method isPart (line 79) | func (ImageURLContent) isPart() {}
  type BinaryContent (line 81) | type BinaryContent struct
    method String (line 87) | func (bc BinaryContent) String(p catwalk.InferenceProvider) string {
    method isPart (line 95) | func (BinaryContent) isPart() {}
  type ToolCall (line 97) | type ToolCall struct
    method isPart (line 105) | func (ToolCall) isPart() {}
  type ToolResult (line 107) | type ToolResult struct
    method isPart (line 117) | func (ToolResult) isPart() {}
  type Finish (line 119) | type Finish struct
    method isPart (line 126) | func (Finish) isPart() {}
  type Message (line 128) | type Message struct
    method Content (line 140) | func (m *Message) Content() TextContent {
    method ReasoningContent (line 149) | func (m *Message) ReasoningContent() ReasoningContent {
    method ImageURLContent (line 158) | func (m *Message) ImageURLContent() []ImageURLContent {
    method BinaryContent (line 168) | func (m *Message) BinaryContent() []BinaryContent {
    method ToolCalls (line 178) | func (m *Message) ToolCalls() []ToolCall {
    method ToolResults (line 188) | func (m *Message) ToolResults() []ToolResult {
    method IsFinished (line 198) | func (m *Message) IsFinished() bool {
    method FinishPart (line 207) | func (m *Message) FinishPart() *Finish {
    method FinishReason (line 216) | func (m *Message) FinishReason() FinishReason {
    method IsThinking (line 225) | func (m *Message) IsThinking() bool {
    method AppendContent (line 232) | func (m *Message) AppendContent(delta string) {
    method AppendReasoningContent (line 245) | func (m *Message) AppendReasoningContent(delta string) {
    method AppendThoughtSignature (line 266) | func (m *Message) AppendThoughtSignature(signature string, toolCallID ...
    method AppendReasoningSignature (line 283) | func (m *Message) AppendReasoningSignature(signature string) {
    method SetReasoningResponsesData (line 298) | func (m *Message) SetReasoningResponsesData(data *openai.ResponsesReas...
    method FinishThinking (line 312) | func (m *Message) FinishThinking() {
    method ThinkingDuration (line 328) | func (m *Message) ThinkingDuration() time.Duration {
    method FinishToolCall (line 342) | func (m *Message) FinishToolCall(toolCallID string) {
    method AppendToolCallInput (line 358) | func (m *Message) AppendToolCallInput(toolCallID string, inputDelta st...
    method AddToolCall (line 374) | func (m *Message) AddToolCall(tc ToolCall) {
    method SetToolCalls (line 386) | func (m *Message) SetToolCalls(tc []ToolCall) {
    method AddToolResult (line 401) | func (m *Message) AddToolResult(tr ToolResult) {
    method SetToolResults (line 405) | func (m *Message) SetToolResults(tr []ToolResult) {
    method Clone (line 413) | func (m *Message) Clone() Message {
    method AddFinish (line 420) | func (m *Message) AddFinish(reason FinishReason, message, details stri...
    method AddImageURL (line 431) | func (m *Message) AddImageURL(url, detail string) {
    method AddBinary (line 435) | func (m *Message) AddBinary(mimeType string, data []byte) {
    method ToAIMessage (line 463) | func (m *Message) ToAIMessage() []fantasy.Message {
  function PromptWithTextAttachments (line 439) | func PromptWithTextAttachments(prompt string, attachments []Attachment) ...

FILE: internal/message/content_test.go
  function makeTestAttachments (line 9) | func makeTestAttachments(n int, contentSize int) []Attachment {
  function BenchmarkPromptWithTextAttachments (line 22) | func BenchmarkPromptWithTextAttachments(b *testing.B) {

FILE: internal/message/message.go
  type CreateMessageParams (line 15) | type CreateMessageParams struct
  type Service (line 23) | type Service interface
  type service (line 35) | type service struct
    method Delete (line 47) | func (s *service) Delete(ctx context.Context, id string) error {
    method Create (line 62) | func (s *service) Create(ctx context.Context, sessionID string, params...
    method DeleteSessionMessages (line 98) | func (s *service) DeleteSessionMessages(ctx context.Context, sessionID...
    method Update (line 114) | func (s *service) Update(ctx context.Context, message Message) error {
    method Get (line 139) | func (s *service) Get(ctx context.Context, id string) (Message, error) {
    method List (line 147) | func (s *service) List(ctx context.Context, sessionID string) ([]Messa...
    method ListUserMessages (line 162) | func (s *service) ListUserMessages(ctx context.Context, sessionID stri...
    method ListAllUserMessages (line 177) | func (s *service) ListAllUserMessages(ctx context.Context) ([]Message,...
    method fromDBItem (line 192) | func (s *service) fromDBItem(item db.Message) (Message, error) {
  function NewService (line 40) | func NewService(q db.Querier) Service {
  type partType (line 210) | type partType
  constant reasoningType (line 213) | reasoningType  partType = "reasoning"
  constant textType (line 214) | textType       partType = "text"
  constant imageURLType (line 215) | imageURLType   partType = "image_url"
  constant binaryType (line 216) | binaryType     partType = "binary"
  constant toolCallType (line 217) | toolCallType   partType = "tool_call"
  constant toolResultType (line 218) | toolResultType partType = "tool_result"
  constant finishType (line 219) | finishType     partType = "finish"
  type partWrapper (line 222) | type partWrapper struct
  function marshalParts (line 227) | func marshalParts(parts []ContentPart) ([]byte, error) {
  function unmarshalParts (line 260) | func unmarshalParts(data []byte) ([]ContentPart, error) {

FILE: internal/oauth/copilot/client.go
  function NewClient (line 19) | func NewClient(isSubAgent, debug bool) *http.Client {
  type initiatorTransport (line 25) | type initiatorTransport struct
    method RoundTrip (line 30) | func (t *initiatorTransport) RoundTrip(req *http.Request) (*http.Respo...
    method roundTrip (line 74) | func (t *initiatorTransport) roundTrip(req *http.Request) (*http.Respo...

FILE: internal/oauth/copilot/disk.go
  function RefreshTokenFromDisk (line 10) | func RefreshTokenFromDisk() (string, bool) {
  function tokenFilePath (line 29) | func tokenFilePath() string {

FILE: internal/oauth/copilot/http.go
  constant userAgent (line 4) | userAgent           = "GitHubCopilotChat/0.32.4"
  constant editorVersion (line 5) | editorVersion       = "vscode/1.105.1"
  constant editorPluginVersion (line 6) | editorPluginVersion = "copilot-chat/0.32.4"
  constant integrationID (line 7) | integrationID       = "vscode-chat"
  function Headers (line 10) | func Headers() map[string]string {

FILE: internal/oauth/copilot/oauth.go
  constant clientID (line 18) | clientID = "Iv1.b507a08c87ecfe98"
  constant deviceCodeURL (line 20) | deviceCodeURL   = "https://github.com/login/device/code"
  constant accessTokenURL (line 21) | accessTokenURL  = "https://github.com/login/oauth/access_token"
  constant copilotTokenURL (line 22) | copilotTokenURL = "https://api.github.com/copilot_internal/v2/token"
  type DeviceCode (line 27) | type DeviceCode struct
  function RequestDeviceCode (line 36) | func RequestDeviceCode(ctx context.Context) (*DeviceCode, error) {
  function PollForToken (line 69) | func PollForToken(ctx context.Context, dc *DeviceCode) (*oauth.Token, er...
  function tryGetToken (line 105) | func tryGetToken(ctx context.Context, deviceCode string) (*oauth.Token, ...
  function getCopilotToken (line 149) | func getCopilotToken(ctx context.Context, githubToken string) (*oauth.To...
  function RefreshToken (line 198) | func RefreshToken(ctx context.Context, githubToken string) (*oauth.Token...

FILE: internal/oauth/copilot/urls.go
  constant SignupURL (line 4) | SignupURL = "https://github.com/github-copilot/signup?editor=crush"
  constant FreeURL (line 5) | FreeURL   = "https://docs.github.com/en/copilot/how-tos/manage-your-acco...

FILE: internal/oauth/hyper/device.go
  type DeviceAuthResponse (line 22) | type DeviceAuthResponse struct
  type TokenResponse (line 30) | type TokenResponse struct
  function InitiateDeviceAuth (line 40) | func InitiateDeviceAuth(ctx context.Context) (*DeviceAuthResponse, error) {
  function deviceName (line 78) | func deviceName() string {
  function PollForToken (line 87) | func PollForToken(ctx context.Context, deviceCode string, expiresIn int)...
  function pollOnce (line 118) | func pollOnce(ctx context.Context, deviceCode string) (TokenResponse, er...
  function ExchangeToken (line 153) | func ExchangeToken(ctx context.Context, refreshToken string) (*oauth.Tok...
  type IntrospectTokenResponse (line 198) | type IntrospectTokenResponse struct
  function IntrospectToken (line 210) | func IntrospectToken(ctx context.Context, accessToken string) (*Introspe...

FILE: internal/oauth/token.go
  type Token (line 8) | type Token struct
    method SetExpiresAt (line 16) | func (t *Token) SetExpiresAt() {
    method IsExpired (line 21) | func (t *Token) IsExpired() bool {
    method SetExpiresIn (line 26) | func (t *Token) SetExpiresIn() {

FILE: internal/permission/permission.go
  type CreatePermissionRequest (line 18) | type CreatePermissionRequest struct
  type PermissionNotification (line 28) | type PermissionNotification struct
  type PermissionRequest (line 34) | type PermissionRequest struct
  type Service (line 45) | type Service interface
  type permissionService (line 57) | type permissionService struct
    method GrantPersistent (line 76) | func (s *permissionService) GrantPersistent(permission PermissionReque...
    method Grant (line 97) | func (s *permissionService) Grant(permission PermissionRequest) {
    method Deny (line 114) | func (s *permissionService) Deny(permission PermissionRequest) {
    method Request (line 132) | func (s *permissionService) Request(ctx context.Context, opts CreatePe...
    method AutoApproveSession (line 218) | func (s *permissionService) AutoApproveSession(sessionID string) {
    method SubscribeNotifications (line 224) | func (s *permissionService) SubscribeNotifications(ctx context.Context...
    method SetSkipRequests (line 228) | func (s *permissionService) SetSkipRequests(skip bool) {
    method SkipRequests (line 232) | func (s *permissionService) SkipRequests() bool {
  function NewPermissionService (line 236) | func NewPermissionService(workingDir string, skip bool, allowedTools []s...

FILE: internal/permission/permission_test.go
  function TestPermissionService_AllowedCommands (line 11) | func TestPermissionService_AllowedCommands(t *testing.T) {
  function TestPermissionService_SkipMode (line 82) | func TestPermissionService_SkipMode(t *testing.T) {
  function TestPermissionService_SequentialProperties (line 100) | func TestPermissionService_SequentialProperties(t *testing.T) {

FILE: internal/projects/projects.go
  constant projectsFileName (line 14) | projectsFileName = "projects.json"
  type Project (line 17) | type Project struct
  type ProjectList (line 24) | type ProjectList struct
  function projectsFilePath (line 31) | func projectsFilePath() string {
  function Load (line 36) | func Load() (*ProjectList, error) {
  function Save (line 58) | func Save(list *ProjectList) error {
  function Register (line 78) | func Register(workingDir, dataDir string) error {
  function List (line 120) | func List() ([]Project, error) {

FILE: internal/projects/projects_test.go
  function TestRegisterAndList (line 9) | func TestRegisterAndList(t *testing.T) {
  function TestRegisterUpdatesExisting (line 62) | func TestRegisterUpdatesExisting(t *testing.T) {
  function TestLoadEmptyFile (line 99) | func TestLoadEmptyFile(t *testing.T) {
  function TestProjectsFilePath (line 115) | func TestProjectsFilePath(t *testing.T) {
  function TestRegisterWithParentDataDir (line 128) | func TestRegisterWithParentDataDir(t *testing.T) {
  function TestRegisterWithExternalDataDir (line 158) | func TestRegisterWithExternalDataDir(t *testing.T) {

FILE: internal/pubsub/broker.go
  constant bufferSize (line 8) | bufferSize = 64
  type Broker (line 10) | type Broker struct
  function NewBroker (line 18) | func NewBroker[T any]() *Broker[T] {
  function NewBrokerWithOptions (line 22) | func NewBrokerWithOptions[T any](channelBufferSize, maxEvents int) *Brok...
  method Shutdown (line 30) | func (b *Broker[T]) Shutdown() {
  method Subscribe (line 49) | func (b *Broker[T]) Subscribe(ctx context.Context) <-chan Event[T] {
  method GetSubscriberCount (line 85) | func (b *Broker[T]) GetSubscriberCount() int {
  method Publish (line 91) | func (b *Broker[T]) Publish(t EventType, payload T) {

FILE: internal/pubsub/events.go
  constant CreatedEvent (line 6) | CreatedEvent EventType = "created"
  constant UpdatedEvent (line 7) | UpdatedEvent EventType = "updated"
  constant DeletedEvent (line 8) | DeletedEvent EventType = "deleted"
  type Subscriber (line 11) | type Subscriber interface
  type EventType (line 17) | type EventType
  type Event (line 20) | type Event struct
  type Publisher (line 25) | type Publisher interface

FILE: internal/session/session.go
  type TodoStatus (line 18) | type TodoStatus
  constant TodoStatusPending (line 21) | TodoStatusPending    TodoStatus = "pending"
  constant TodoStatusInProgress (line 22) | TodoStatusInProgress TodoStatus = "in_progress"
  constant TodoStatusCompleted (line 23) | TodoStatusCompleted  TodoStatus = "completed"
  function HashID (line 27) | func HashID(id string) string {
  type Todo (line 33) | type Todo struct
  function HasIncompleteTodos (line 40) | func HasIncompleteTodos(todos []Todo) bool {
  type Session (line 49) | type Session struct
  type Service (line 63) | type Service interface
  type service (line 82) | type service struct
    method Create (line 88) | func (s *service) Create(ctx context.Context, title string) (Session, ...
    method CreateTaskSession (line 102) | func (s *service) CreateTaskSession(ctx context.Context, toolCallID, p...
    method CreateTitleSession (line 116) | func (s *service) CreateTitleSession(ctx context.Context, parentSessio...
    method Delete (line 130) | func (s *service) Delete(ctx context.Context, id string) error {
    method Get (line 162) | func (s *service) Get(ctx context.Context, id string) (Session, error) {
    method GetLast (line 170) | func (s *service) GetLast(ctx context.Context) (Session, error) {
    method Save (line 178) | func (s *service) Save(ctx context.Context, session Session) (Session,...
    method UpdateTitleAndUsage (line 209) | func (s *service) UpdateTitleAndUsage(ctx context.Context, sessionID, ...
    method Rename (line 221) | func (s *service) Rename(ctx context.Context, id string, title string)...
    method List (line 228) | func (s *service) List(ctx context.Context) ([]Session, error) {
    method fromDBItem (line 240) | func (s service) fromDBItem(item db.Session) Session {
    method CreateAgentToolSessionID (line 292) | func (s *service) CreateAgentToolSessionID(messageID, toolCallID strin...
    method ParseAgentToolSessionID (line 297) | func (s *service) ParseAgentToolSessionID(sessionID string) (messageID...
    method IsAgentToolSession (line 306) | func (s *service) IsAgentToolSession(sessionID string) bool {
  function marshalTodos (line 260) | func marshalTodos(todos []Todo) (string, error) {
  function unmarshalTodos (line 271) | func unmarshalTodos(data string) ([]Todo, error) {
  function NewService (line 282) | func NewService(q *db.Queries, conn *sql.DB) Service {

FILE: internal/shell/background.go
  constant MaxBackgroundJobs (line 17) | MaxBackgroundJobs = 50
  constant CompletedJobRetentionMinutes (line 19) | CompletedJobRetentionMinutes = 8 * 60
  type syncBuffer (line 23) | type syncBuffer struct
    method Write (line 28) | func (sb *syncBuffer) Write(p []byte) (n int, err error) {
    method WriteString (line 34) | func (sb *syncBuffer) WriteString(s string) (n int, err error) {
    method String (line 40) | func (sb *syncBuffer) String() string {
  type BackgroundShell (line 47) | type BackgroundShell struct
    method GetOutput (line 214) | func (bs *BackgroundShell) GetOutput() (stdout string, stderr string, ...
    method IsDone (line 224) | func (bs *BackgroundShell) IsDone() bool {
    method Wait (line 234) | func (bs *BackgroundShell) Wait() {
    method WaitContext (line 238) | func (bs *BackgroundShell) WaitContext(ctx context.Context) bool {
  type BackgroundShellManager (line 63) | type BackgroundShellManager struct
    method Start (line 89) | func (m *BackgroundShellManager) Start(ctx context.Context, workingDir...
    method Get (line 132) | func (m *BackgroundShellManager) Get(id string) (*BackgroundShell, boo...
    method Remove (line 138) | func (m *BackgroundShellManager) Remove(id string) error {
    method Kill (line 147) | func (m *BackgroundShellManager) Kill(id string) error {
    method List (line 166) | func (m *BackgroundShellManager) List() []string {
    method Cleanup (line 175) | func (m *BackgroundShellManager) Cleanup() int {
    method KillAll (line 196) | func (m *BackgroundShellManager) KillAll(ctx context.Context) {
  function newBackgroundShellManager (line 74) | func newBackgroundShellManager() *BackgroundShellManager {
  function GetBackgroundShellManager (line 81) | func GetBackgroundShellManager() *BackgroundShellManager {
  type BackgroundShellInfo (line 159) | type BackgroundShellInfo struct

FILE: internal/shell/background_test.go
  function TestBackgroundShellManager_Start (line 13) | func TestBackgroundShellManager_Start(t *testing.T) {
  function TestBackgroundShellManager_Get (line 51) | func TestBackgroundShellManager_Get(t *testing.T) {
  function TestBackgroundShellManager_Kill (line 77) | func TestBackgroundShellManager_Kill(t *testing.T) {
  function TestBackgroundShellManager_KillNonExistent (line 108) | func TestBackgroundShellManager_KillNonExistent(t *testing.T) {
  function TestBackgroundShell_IsDone (line 119) | func TestBackgroundShell_IsDone(t *testing.T) {
  function TestBackgroundShell_WithBlockFuncs (line 142) | func TestBackgroundShell_WithBlockFuncs(t *testing.T) {
  function TestBackgroundShellManager_List (line 176) | func TestBackgroundShellManager_List(t *testing.T) {
  function TestBackgroundShellManager_KillAll (line 224) | func TestBackgroundShellManager_KillAll(t *testing.T) {
  function TestBackgroundShellManager_KillAll_Timeout (line 286) | func TestBackgroundShellManager_KillAll_Timeout(t *testing.T) {
  function TestBackgroundShell_WaitContext_Completed (line 311) | func TestBackgroundShell_WaitContext_Completed(t *testing.T) {
  function TestBackgroundShell_WaitContext_Canceled (line 325) | func TestBackgroundShell_WaitContext_Canceled(t *testing.T) {

FILE: internal/shell/command_block_test.go
  function TestCommandBlocking (line 10) | func TestCommandBlocking(t *testing.T) {
  function TestArgumentsBlocker (line 113) | func TestArgumentsBlocker(t *testing.T) {
  function TestCommandsBlocker (line 263) | func TestCommandsBlocker(t *testing.T) {
  function TestSplitArgsFlags (line 312) | func TestSplitArgsFlags(t *testing.T) {

FILE: internal/shell/comparison_test.go
  function TestShellPerformanceComparison (line 10) | func TestShellPerformanceComparison(t *testing.T) {
  function BenchmarkShellPolling (line 28) | func BenchmarkShellPolling(b *testing.B) {

FILE: internal/shell/coreutils.go
  function init (line 11) | func init() {

FILE: internal/shell/shell.go
  type ShellType (line 31) | type ShellType
  constant ShellTypePOSIX (line 34) | ShellTypePOSIX ShellType = iota
  constant ShellTypeCmd (line 35) | ShellTypeCmd
  constant ShellTypePowerShell (line 36) | ShellTypePowerShell
  type Logger (line 40) | type Logger interface
  type noopLogger (line 45) | type noopLogger struct
    method InfoPersist (line 47) | func (noopLogger) InfoPersist(msg string, keysAndValues ...any) {}
  type BlockFunc (line 50) | type BlockFunc
  type Shell (line 53) | type Shell struct
    method Exec (line 99) | func (s *Shell) Exec(ctx context.Context, command string) (string, str...
    method ExecStream (line 107) | func (s *Shell) ExecStream(ctx context.Context, command string, stdout...
    method GetWorkingDir (line 115) | func (s *Shell) GetWorkingDir() string {
    method SetWorkingDir (line 122) | func (s *Shell) SetWorkingDir(dir string) error {
    method GetEnv (line 136) | func (s *Shell) GetEnv() []string {
    method SetEnv (line 146) | func (s *Shell) SetEnv(key, value string) {
    method SetBlockFuncs (line 162) | func (s *Shell) SetBlockFuncs(blockFuncs []BlockFunc) {
    method blockHandler (line 221) | func (s *Shell) blockHandler() func(next interp.ExecHandlerFunc) inter...
    method newInterp (line 240) | func (s *Shell) newInterp(stdout, stderr io.Writer) (*interp.Runner, e...
    method updateShellFromRunner (line 251) | func (s *Shell) updateShellFromRunner(runner *interp.Runner) {
    method execCommon (line 262) | func (s *Shell) execCommon(ctx context.Context, command string, stdout...
    method exec (line 289) | func (s *Shell) exec(ctx context.Context, command string) (string, str...
    method execStream (line 296) | func (s *Shell) execStream(ctx context.Context, command string, stdout...
    method execHandlers (line 300) | func (s *Shell) execHandlers() []func(next interp.ExecHandlerFunc) int...
  type Options (line 62) | type Options struct
  function NewShell (line 70) | func NewShell(opts *Options) *Shell {
  function CommandsBlocker (line 169) | func CommandsBlocker(cmds []string) BlockFunc {
  function ArgumentsBlocker (line 185) | func ArgumentsBlocker(cmd string, args []string, flags []string) BlockFu...
  function splitArgsFlags (line 203) | func splitArgsFlags(parts []string) (args []string, flags []string) {
  function IsInterrupt (line 311) | func IsInterrupt(err error) bool {
  function ExitCode (line 317) | func ExitCode(err error) int {

FILE: internal/shell/shell_test.go
  function BenchmarkShellQuickCommands (line 13) | func BenchmarkShellQuickCommands(b *testing.B) {
  function TestTestTimeout (line 27) | func TestTestTimeout(t *testing.T) {
  function TestTestCancel (line 49) | func TestTestCancel(t *testing.T) {
  function TestRunCommandError (line 66) | func TestRunCommandError(t *testing.T) {
  function TestRunContinuity (line 80) | func TestRunContinuity(t *testing.T) {
  function TestCrossPlatformExecution (line 101) | func TestCrossPlatformExecution(t *testing.T) {

FILE: internal/skills/skills.go
  constant SkillFileName (line 20) | SkillFileName          = "SKILL.md"
  constant MaxNameLength (line 21) | MaxNameLength          = 64
  constant MaxDescriptionLength (line 22) | MaxDescriptionLength   = 1024
  constant MaxCompatibilityLength (line 23) | MaxCompatibilityLength = 500
  type Skill (line 29) | type Skill struct
    method Validate (line 41) | func (s *Skill) Validate() error {
  function Parse (line 72) | func Parse(path string) (*Skill, error) {
  function splitFrontmatter (line 96) | func splitFrontmatter(content string) (frontmatter, body string, err err...
  function Discover (line 113) | func Discover(paths []string) []*Skill {
  function ToPromptXML (line 162) | func ToPromptXML(skills []*Skill) string {
  function escape (line 180) | func escape(s string) string {

FILE: internal/skills/skills_test.go
  function TestParse (line 12) | func TestParse(t *testing.T) {
  function TestSkillValidate (line 103) | func TestSkillValidate(t *testing.T) {
  function TestDiscover (line 184) | func TestDiscover(t *testing.T) {
  function TestToPromptXML (line 229) | func TestToPromptXML(t *testing.T) {
  function TestToPromptXMLEmpty (line 245) | func TestToPromptXMLEmpty(t *testing.T) {

FILE: internal/stringext/string.go
  function Capitalize (line 10) | func Capitalize(text string) string {
  function NormalizeSpace (line 17) | func NormalizeSpace(content string) string {

FILE: internal/ui/anim/anim.go
  constant fps (line 22) | fps           = 20
  constant initialChar (line 23) | initialChar   = '.'
  constant labelGap (line 24) | labelGap      = " "
  constant labelGapWidth (line 25) | labelGapWidth = 1
  constant ellipsisAnimSpeed (line 31) | ellipsisAnimSpeed = 8
  constant maxBirthOffset (line 35) | maxBirthOffset = time.Second
  constant prerenderedFrames (line 40) | prerenderedFrames = 10
  constant defaultNumCyclingChars (line 43) | defaultNumCyclingChars = 10
  function nextID (line 62) | func nextID() int {
  type animCache (line 67) | type animCache struct
  function settingsHash (line 79) | func settingsHash(opts Settings) string {
  type StepMsg (line 87) | type StepMsg struct
  type Settings (line 90) | type Settings struct
  type Anim (line 104) | type Anim struct
    method SetLabel (line 262) | func (a *Anim) SetLabel(newLabel string) {
    method renderLabel (line 276) | func (a *Anim) renderLabel(label string) {
    method Width (line 303) | func (a *Anim) Width() (w int) {
    method Start (line 321) | func (a *Anim) Start() tea.Cmd {
    method Animate (line 326) | func (a *Anim) Animate(msg StepMsg) tea.Cmd {
    method Render (line 349) | func (a *Anim) Render() string {
    method Step (line 383) | func (a *Anim) Step() tea.Cmd {
  function New (line 122) | func New(opts Settings) *Anim {
  function makeGradientRamp (line 391) | func makeGradientRamp(size int, stops ...color.Color) []color.Color {
  function colorIsUnset (line 439) | func colorIsUnset(c color.Color) bool {

FILE: internal/ui/attachments/attachments.go
  constant maxFilename (line 17) | maxFilename = 15
  type Keymap (line 19) | type Keymap struct
  function New (line 25) | func New(renderer *Renderer, keyMap Keymap) *Attachments {
  type Attachments (line 32) | type Attachments struct
    method List (line 39) | func (m *Attachments) List() []message.Attachment { return m.list }
    method Reset (line 40) | func (m *Attachments) Reset()                     { m.list = nil }
    method Update (line 42) | func (m *Attachments) Update(msg tea.Msg) bool {
    method Render (line 77) | func (m *Attachments) Render(width int) string {
  function NewRenderer (line 81) | func NewRenderer(normalStyle, deletingStyle, imageStyle, textStyle lipgl...
  type Renderer (line 90) | type Renderer struct
    method Render (line 94) | func (r *Renderer) Render(attachments []message.Attachment, deleting b...
    method icon (line 130) | func (r *Renderer) icon(a message.Attachment) lipgloss.Style {

FILE: internal/ui/chat/agent.go
  type NestedToolContainer (line 21) | type NestedToolContainer interface
  type AgentToolMessageItem (line 28) | type AgentToolMessageItem struct
    method Animate (line 56) | func (a *AgentToolMessageItem) Animate(msg anim.StepMsg) tea.Cmd {
    method NestedTools (line 75) | func (a *AgentToolMessageItem) NestedTools() []ToolMessageItem {
    method SetNestedTools (line 80) | func (a *AgentToolMessageItem) SetNestedTools(tools []ToolMessageItem) {
    method AddNestedTool (line 86) | func (a *AgentToolMessageItem) AddNestedTool(tool ToolMessageItem) {
  function NewAgentToolMessageItem (line 40) | func NewAgentToolMessageItem(
  type AgentToolRenderContext (line 96) | type AgentToolRenderContext struct
    method RenderTool (line 101) | func (r *AgentToolRenderContext) RenderTool(sty *styles.Styles, width ...
  type AgenticFetchToolMessageItem (line 172) | type AgenticFetchToolMessageItem struct
    method NestedTools (line 200) | func (a *AgenticFetchToolMessageItem) NestedTools() []ToolMessageItem {
    method SetNestedTools (line 205) | func (a *AgenticFetchToolMessageItem) SetNestedTools(tools []ToolMessa...
    method AddNestedTool (line 211) | func (a *AgenticFetchToolMessageItem) AddNestedTool(tool ToolMessageIt...
  function NewAgenticFetchToolMessageItem (line 184) | func NewAgenticFetchToolMessageItem(
  type AgenticFetchToolRenderContext (line 221) | type AgenticFetchToolRenderContext struct
    method RenderTool (line 232) | func (r *AgenticFetchToolRenderContext) RenderTool(sty *styles.Styles,...
  type agenticFetchParams (line 226) | type agenticFetchParams struct

FILE: internal/ui/chat/assistant.go
  constant assistantMessageTruncateFormat (line 18) | assistantMessageTruncateFormat = "… (%d lines hidden) [click or space to...
  constant maxCollapsedThinkingHeight (line 21) | maxCollapsedThinkingHeight = 10
  type AssistantMessageItem (line 26) | type AssistantMessageItem struct
    method StartAnimation (line 60) | func (a *AssistantMessageItem) StartAnimation() tea.Cmd {
    method Animate (line 68) | func (a *AssistantMessageItem) Animate(msg anim.StepMsg) tea.Cmd {
    method ID (line 76) | func (a *AssistantMessageItem) ID() string {
    method RawRender (line 81) | func (a *AssistantMessageItem) RawRender(width int) string {
    method Render (line 109) | func (a *AssistantMessageItem) Render(width int) string {
    method renderMessageContent (line 130) | func (a *AssistantMessageItem) renderMessageContent(width int) string {
    method renderThinking (line 162) | func (a *AssistantMessageItem) renderThinking(thinking string, width i...
    method renderMarkdown (line 204) | func (a *AssistantMessageItem) renderMarkdown(content string, width in...
    method renderSpinning (line 213) | func (a *AssistantMessageItem) renderSpinning() string {
    method renderError (line 223) | func (a *AssistantMessageItem) renderError(width int) string {
    method isSpinning (line 233) | func (a *AssistantMessageItem) isSpinning() bool {
    method SetMessage (line 242) | func (a *AssistantMessageItem) SetMessage(message *message.Message) te...
    method ToggleExpanded (line 253) | func (a *AssistantMessageItem) ToggleExpanded() {
    method HandleMouseClick (line 259) | func (a *AssistantMessageItem) HandleMouseClick(btn ansi.MouseButton, ...
    method HandleKeyEvent (line 272) | func (a *AssistantMessageItem) HandleKeyEvent(key tea.KeyMsg) (bool, t...
  function NewAssistantMessageItem (line 39) | func NewAssistantMessageItem(sty *styles.Styles, message *message.Messag...

FILE: internal/ui/chat/bash.go
  type BashToolMessageItem (line 21) | type BashToolMessageItem struct
  function NewBashToolMessageItem (line 28) | func NewBashToolMessageItem(
  type BashToolRenderContext (line 38) | type BashToolRenderContext struct
    method RenderTool (line 41) | func (b *BashToolRenderContext) RenderTool(sty *styles.Styles, width i...
  type JobOutputToolMessageItem (line 103) | type JobOutputToolMessageItem struct
  function NewJobOutputToolMessageItem (line 110) | func NewJobOutputToolMessageItem(
  type JobOutputToolRenderContext (line 120) | type JobOutputToolRenderContext struct
    method RenderTool (line 123) | func (j *JobOutputToolRenderContext) RenderTool(sty *styles.Styles, wi...
  type JobKillToolMessageItem (line 154) | type JobKillToolMessageItem struct
  function NewJobKillToolMessageItem (line 161) | func NewJobKillToolMessageItem(
  type JobKillToolRenderContext (line 171) | type JobKillToolRenderContext struct
    method RenderTool (line 174) | func (j *JobKillToolRenderContext) RenderTool(sty *styles.Styles, widt...
  function renderJobTool (line 202) | func renderJobTool(sty *styles.Styles, opts *ToolRenderOpts, width int, ...
  function jobHeader (line 223) | func jobHeader(sty *styles.Styles, status ToolStatus, action, shellID, d...
  function joinToolParts (line 246) | func joinToolParts(header, body string) string {

FILE: internal/ui/chat/diagnostics.go
  type DiagnosticsToolMessageItem (line 17) | type DiagnosticsToolMessageItem struct
  function NewDiagnosticsToolMessageItem (line 24) | func NewDiagnosticsToolMessageItem(
  type DiagnosticsToolRenderContext (line 34) | type DiagnosticsToolRenderContext struct
    method RenderTool (line 37) | func (d *DiagnosticsToolRenderContext) RenderTool(sty *styles.Styles, ...

FILE: internal/ui/chat/docker_mcp.go
  type DockerMCPToolMessageItem (line 18) | type DockerMCPToolMessageItem struct
  function NewDockerMCPToolMessageItem (line 25) | func NewDockerMCPToolMessageItem(
  type DockerMCPToolRenderContext (line 35) | type DockerMCPToolRenderContext struct
    method RenderTool (line 38) | func (d *DockerMCPToolRenderContext) RenderTool(sty *styles.Styles, wi...
    method renderMCPServers (line 178) | func (d *DockerMCPToolRenderContext) renderMCPServers(sty *styles.Styl...
    method makeHeader (line 226) | func (d *DockerMCPToolRenderContext) makeHeader(sty *styles.Styles, to...
    method formatToolName (line 239) | func (d *DockerMCPToolRenderContext) formatToolName(sty *styles.Styles...
    method makeCompactHeader (line 269) | func (d *DockerMCPToolRenderContext) makeCompactHeader(sty *styles.Sty...
  type FindMCPResponse (line 171) | type FindMCPResponse struct
  function IsDockerMCPTool (line 294) | func IsDockerMCPTool(name string) bool {

FILE: internal/ui/chat/fetch.go
  type FetchToolMessageItem (line 16) | type FetchToolMessageItem struct
  function NewFetchToolMessageItem (line 23) | func NewFetchToolMessageItem(
  type FetchToolRenderContext (line 33) | type FetchToolRenderContext struct
    method RenderTool (line 36) | func (f *FetchToolRenderContext) RenderTool(sty *styles.Styles, width ...
  function getFileExtensionForFormat (line 75) | func getFileExtensionForFormat(format string) string {
  type WebFetchToolMessageItem (line 91) | type WebFetchToolMessageItem struct
  function NewWebFetchToolMessageItem (line 98) | func NewWebFetchToolMessageItem(
  type WebFetchToolRenderContext (line 108) | type WebFetchToolRenderContext struct
    method RenderTool (line 111) | func (w *WebFetchToolRenderContext) RenderTool(sty *styles.Styles, wid...
  type WebSearchToolMessageItem (line 145) | type WebSearchToolMessageItem struct
  function NewWebSearchToolMessageItem (line 152) | func NewWebSearchToolMessageItem(
  type WebSearchToolRenderContext (line 162) | type WebSearchToolRenderContext struct
    method RenderTool (line 165) | func (w *WebSearchToolRenderContext) RenderTool(sty *styles.Styles, wi...

FILE: internal/ui/chat/file.go
  type ViewToolMessageItem (line 19) | type ViewToolMessageItem struct
  function NewViewToolMessageItem (line 26) | func NewViewToolMessageItem(
  type ViewToolRenderContext (line 36) | type ViewToolRenderContext struct
    method RenderTool (line 39) | func (v *ViewToolRenderContext) RenderTool(sty *styles.Styles, width i...
  type WriteToolMessageItem (line 105) | type WriteToolMessageItem struct
  function NewWriteToolMessageItem (line 112) | func NewWriteToolMessageItem(
  type WriteToolRenderContext (line 122) | type WriteToolRenderContext struct
    method RenderTool (line 125) | func (w *WriteToolRenderContext) RenderTool(sty *styles.Styles, width ...
  type EditToolMessageItem (line 160) | type EditToolMessageItem struct
  function NewEditToolMessageItem (line 167) | func NewEditToolMessageItem(
  type EditToolRenderContext (line 177) | type EditToolRenderContext struct
    method RenderTool (line 180) | func (e *EditToolRenderContext) RenderTool(sty *styles.Styles, width i...
  type MultiEditToolMessageItem (line 223) | type MultiEditToolMessageItem struct
  function NewMultiEditToolMessageItem (line 230) | func NewMultiEditToolMessageItem(
  type MultiEditToolRenderContext (line 240) | type MultiEditToolRenderContext struct
    method RenderTool (line 243) | func (m *MultiEditToolRenderContext) RenderTool(sty *styles.Styles, wi...
  type DownloadToolMessageItem (line 291) | type DownloadToolMessageItem struct
  function NewDownloadToolMessageItem (line 298) | func NewDownloadToolMessageItem(
  type DownloadToolRenderContext (line 308) | type DownloadToolRenderContext struct
    method RenderTool (line 311) | func (d *DownloadToolRenderContext) RenderTool(sty *styles.Styles, wid...

FILE: internal/ui/chat/generic.go
  type GenericToolMessageItem (line 13) | type GenericToolMessageItem struct
  function NewGenericToolMessageItem (line 20) | func NewGenericToolMessageItem(
  type GenericToolRenderContext (line 30) | type GenericToolRenderContext struct
    method RenderTool (line 33) | func (g *GenericToolRenderContext) RenderTool(sty *styles.Styles, widt...
  function genericPrettyName (line 94) | func genericPrettyName(name string) string {

FILE: internal/ui/chat/lsp_restart.go
  type LSPRestartToolMessageItem (line 12) | type LSPRestartToolMessageItem struct
  function NewLSPRestartToolMessageItem (line 19) | func NewLSPRestartToolMessageItem(
  type LSPRestartToolRenderContext (line 29) | type LSPRestartToolRenderContext struct
    method RenderTool (line 32) | func (r *LSPRestartToolRenderContext) RenderTool(sty *styles.Styles, w...

FILE: internal/ui/chat/mcp.go
  type MCPToolMessageItem (line 14) | type MCPToolMessageItem struct
  function NewMCPToolMessageItem (line 21) | func NewMCPToolMessageItem(
  type MCPToolRenderContext (line 31) | type MCPToolRenderContext struct
    method RenderTool (line 34) | func (b *MCPToolRenderContext) RenderTool(sty *styles.Styles, width in...
  function prettyName (line 95) | func prettyName(name string) string {
  function looksLikeMarkdown (line 103) | func looksLikeMarkdown(content string) bool {

FILE: internal/ui/chat/messages.go
  constant MessageLeftPaddingTotal (line 23) | MessageLeftPaddingTotal = 2
  constant maxTextWidth (line 26) | maxTextWidth = 120
  type Identifiable (line 29) | type Identifiable interface
  type Animatable (line 34) | type Animatable interface
  type Expandable (line 40) | type Expandable interface
  type KeyEventHandler (line 47) | type KeyEventHandler interface
  type MessageItem (line 53) | type MessageItem interface
  type HighlightableMessageItem (line 60) | type HighlightableMessageItem interface
  type FocusableMessageItem (line 66) | type FocusableMessageItem interface
  type SendMsg (line 72) | type SendMsg struct
  type highlightableMessageItem (line 77) | type highlightableMessageItem struct
    method isHighlighted (line 88) | func (h *highlightableMessageItem) isHighlighted() bool {
    method renderHighlighted (line 93) | func (h *highlightableMessageItem) renderHighlighted(content string, w...
    method SetHighlight (line 102) | func (h *highlightableMessageItem) SetHighlight(startLine int, startCo...
    method Highlight (line 117) | func (h *highlightableMessageItem) Highlight() (startLine int, startCo...
  function defaultHighlighter (line 121) | func defaultHighlighter(sty *styles.Styles) *highlightableMessageItem {
  type cachedMessageItem (line 137) | type cachedMessageItem struct
    method getCachedRender (line 146) | func (c *cachedMessageItem) getCachedRender(width int) (string, int, b...
    method setCachedRender (line 154) | func (c *cachedMessageItem) setCachedRender(rendered string, width, he...
    method clearCache (line 161) | func (c *cachedMessageItem) clearCache() {
  type focusableMessageItem (line 168) | type focusableMessageItem struct
    method SetFocused (line 173) | func (f *focusableMessageItem) SetFocused(focused bool) {
  function AssistantInfoID (line 178) | func AssistantInfoID(messageID string) string {
  type AssistantInfoItem (line 183) | type AssistantInfoItem struct
    method ID (line 206) | func (a *AssistantInfoItem) ID() string {
    method RawRender (line 211) | func (a *AssistantInfoItem) RawRender(width int) string {
    method Render (line 223) | func (a *AssistantInfoItem) Render(width int) string {
    method renderContent (line 232) | func (a *AssistantInfoItem) renderContent(width int) string {
  function NewAssistantInfoItem (line 194) | func NewAssistantInfoItem(sty *styles.Styles, message *message.Message, ...
  function cappedMessageWidth (line 256) | func cappedMessageWidth(availableWidth int) int {
  function ExtractMessageItems (line 265) | func ExtractMessageItems(sty *styles.Styles, msg *message.Message, toolR...
  function ShouldRenderAssistantMessage (line 302) | func ShouldRenderAssistantMessage(msg *message.Message) bool {
  function BuildToolResultMap (line 314) | func BuildToolResultMap(messages []*message.Message) map[string]message....

FILE: internal/ui/chat/references.go
  type ReferencesToolMessageItem (line 13) | type ReferencesToolMessageItem struct
  function NewReferencesToolMessageItem (line 20) | func NewReferencesToolMessageItem(
  type ReferencesToolRenderContext (line 30) | type ReferencesToolRenderContext struct
    method RenderTool (line 33) | func (r *ReferencesToolRenderContext) RenderTool(sty *styles.Styles, w...

FILE: internal/ui/chat/search.go
  type GlobToolMessageItem (line 17) | type GlobToolMessageItem struct
  function NewGlobToolMessageItem (line 24) | func NewGlobToolMessageItem(
  type GlobToolRenderContext (line 34) | type GlobToolRenderContext struct
    method RenderTool (line 37) | func (g *GlobToolRenderContext) RenderTool(sty *styles.Styles, width i...
  type GrepToolMessageItem (line 76) | type GrepToolMessageItem struct
  function NewGrepToolMessageItem (line 83) | func NewGrepToolMessageItem(
  type GrepToolRenderContext (line 93) | type GrepToolRenderContext struct
    method RenderTool (line 96) | func (g *GrepToolRenderContext) RenderTool(sty *styles.Styles, width i...
  type LSToolMessageItem (line 141) | type LSToolMessageItem struct
  function NewLSToolMessageItem (line 148) | func NewLSToolMessageItem(
  type LSToolRenderContext (line 158) | type LSToolRenderContext struct
    method RenderTool (line 161) | func (l *LSToolRenderContext) RenderTool(sty *styles.Styles, width int...
  type SourcegraphToolMessageItem (line 201) | type SourcegraphToolMessageItem struct
  function NewSourcegraphToolMessageItem (line 208) | func NewSourcegraphToolMessageItem(
  type SourcegraphToolRenderContext (line 218) | type SourcegraphToolRenderContext struct
    method RenderTool (line 221) | func (s *SourcegraphToolRenderContext) RenderTool(sty *styles.Styles, ...

FILE: internal/ui/chat/todos.go
  type TodosToolMessageItem (line 21) | type TodosToolMessageItem struct
  function NewTodosToolMessageItem (line 28) | func NewTodosToolMessageItem(
  type TodosToolRenderContext (line 38) | type TodosToolRenderContext struct
    method RenderTool (line 41) | func (t *TodosToolRenderContext) RenderTool(sty *styles.Styles, width ...
  function FormatTodosList (line 139) | func FormatTodosList(sty *styles.Styles, todos []session.Todo, inProgres...
  function sortTodos (line 176) | func sortTodos(todos []session.Todo) {
  function statusOrder (line 183) | func statusOrder(s session.TodoStatus) int {

FILE: internal/ui/chat/tools.go
  constant responseContextHeight (line 26) | responseContextHeight = 10
  constant toolBodyLeftPaddingTotal (line 29) | toolBodyLeftPaddingTotal = 2
  type ToolStatus (line 32) | type ToolStatus
  constant ToolStatusAwaitingPermission (line 35) | ToolStatusAwaitingPermission ToolStatus = iota
  constant ToolStatusRunning (line 36) | ToolStatusRunning
  constant ToolStatusSuccess (line 37) | ToolStatusSuccess
  constant ToolStatusError (line 38) | ToolStatusError
  constant ToolStatusCanceled (line 39) | ToolStatusCanceled
  type ToolMessageItem (line 43) | type ToolMessageItem interface
  type Compactable (line 57) | type Compactable interface
  type SpinningState (line 62) | type SpinningState struct
    method IsCanceled (line 69) | func (s *SpinningState) IsCanceled() bool {
    method HasResult (line 74) | func (s *SpinningState) HasResult() bool {
  type SpinningFunc (line 80) | type SpinningFunc
  type DefaultToolRenderContext (line 83) | type DefaultToolRenderContext struct
    method RenderTool (line 86) | func (d *DefaultToolRenderContext) RenderTool(sty *styles.Styles, widt...
  type ToolRenderOpts (line 91) | type ToolRenderOpts struct
    method IsPending (line 103) | func (o *ToolRenderOpts) IsPending() bool {
    method IsCanceled (line 108) | func (o *ToolRenderOpts) IsCanceled() bool {
    method HasResult (line 113) | func (o *ToolRenderOpts) HasResult() bool {
    method HasEmptyResult (line 118) | func (o *ToolRenderOpts) HasEmptyResult() bool {
  type ToolRenderer (line 123) | type ToolRenderer interface
  type ToolRendererFunc (line 128) | type ToolRendererFunc
    method RenderTool (line 131) | func (f ToolRendererFunc) RenderTool(sty *styles.Styles, width int, op...
  type baseToolMessageItem (line 136) | type baseToolMessageItem struct
    method SetCompact (line 271) | func (t *baseToolMessageItem) SetCompact(compact bool) {
    method ID (line 277) | func (t *baseToolMessageItem) ID() string {
    method StartAnimation (line 282) | func (t *baseToolMessageItem) StartAnimation() tea.Cmd {
    method Animate (line 290) | func (t *baseToolMessageItem) Animate(msg anim.StepMsg) tea.Cmd {
    method RawRender (line 298) | func (t *baseToolMessageItem) RawRender(width int) string {
    method Render (line 325) | func (t *baseToolMessageItem) Render(width int) string {
    method ToolCall (line 342) | func (t *baseToolMessageItem) ToolCall() message.ToolCall {
    method SetToolCall (line 347) | func (t *baseToolMessageItem) SetToolCall(tc message.ToolCall) {
    method SetResult (line 353) | func (t *baseToolMessageItem) SetResult(res *message.ToolResult) {
    method MessageID (line 359) | func (t *baseToolMessageItem) MessageID() string {
    method SetMessageID (line 364) | func (t *baseToolMessageItem) SetMessageID(id string) {
    method SetStatus (line 369) | func (t *baseToolMessageItem) SetStatus(status ToolStatus) {
    method Status (line 375) | func (t *baseToolMessageItem) Status() ToolStatus {
    method computeStatus (line 380) | func (t *baseToolMessageItem) computeStatus() ToolStatus {
    method isSpinning (line 391) | func (t *baseToolMessageItem) isSpinning() bool {
    method SetSpinningFunc (line 403) | func (t *baseToolMessageItem) SetSpinningFunc(fn SpinningFunc) {
    method ToggleExpanded (line 408) | func (t *baseToolMessageItem) ToggleExpanded() bool {
    method HandleMouseClick (line 415) | func (t *baseToolMessageItem) HandleMouseClick(btn ansi.MouseButton, x...
    method HandleKeyEvent (line 420) | func (t *baseToolMessageItem) HandleKeyEvent(key tea.KeyMsg) (bool, te...
    method formatToolForCopy (line 833) | func (t *baseToolMessageItem) formatToolForCopy() string {
    method formatParametersForCopy (line 870) | func (t *baseToolMessageItem) formatParametersForCopy() string {
    method formatResultForCopy (line 1025) | func (t *baseToolMessageItem) formatResultForCopy() string {
    method formatBashResultForCopy (line 1064) | func (t *baseToolMessageItem) formatBashResultForCopy() string {
    method formatViewResultForCopy (line 1087) | func (t *baseToolMessageItem) formatViewResultForCopy() string {
    method formatEditResultForCopy (line 1151) | func (t *baseToolMessageItem) formatEditResultForCopy() string {
    method formatMultiEditResultForCopy (line 1186) | func (t *baseToolMessageItem) formatMultiEditResultForCopy() string {
    method formatWriteResultForCopy (line 1220) | func (t *baseToolMessageItem) formatWriteResultForCopy() string {
    method formatFetchResultForCopy (line 1281) | func (t *baseToolMessageItem) formatFetchResultForCopy() string {
    method formatAgenticFetchResultForCopy (line 1309) | func (t *baseToolMessageItem) formatAgenticFetchResultForCopy() string {
    method formatWebFetchResultForCopy (line 1335) | func (t *baseToolMessageItem) formatWebFetchResultForCopy() string {
    method formatAgentResultForCopy (line 1355) | func (t *baseToolMessageItem) formatAgentResultForCopy() string {
  function newBaseToolMessageItem (line 163) | func newBaseToolMessageItem(
  function NewToolMessageItem (line 206) | func NewToolMessageItem(
  function pendingTool (line 429) | func pendingTool(sty *styles.Styles, name string, anim *anim.Anim, neste...
  function toolEarlyStateContent (line 447) | func toolEarlyStateContent(sty *styles.Styles, opts *ToolRenderOpts, wid...
  function toolErrorContent (line 465) | func toolErrorContent(sty *styles.Styles, result *message.ToolResult, wi...
  function toolIcon (line 478) | func toolIcon(sty *styles.Styles, status ToolStatus) string {
  function toolParamList (line 493) | func toolParamList(sty *styles.Styles, params []string, width int) string {
  function toolHeader (line 527) | func toolHeader(sty *styles.Styles, status ToolStatus, name string, widt...
  function toolOutputPlainContent (line 542) | func toolOutputPlainContent(sty *styles.Styles, content string, width in...
  function toolOutputCodeContent (line 575) | func toolOutputCodeContent(sty *styles.Styles, path, content string, off...
  function toolOutputImageContent (line 628) | func toolOutputImageContent(sty *styles.Styles, data, mediaType string) ...
  function toolOutputSkillContent (line 642) | func toolOutputSkillContent(sty *styles.Styles, name, description string...
  function getDigits (line 653) | func getDigits(n int) int {
  function formatSize (line 669) | func formatSize(bytes int) string {
  function toolOutputDiffContent (line 685) | func toolOutputDiffContent(sty *styles.Styles, file, oldContent, newCont...
  function formatTimeout (line 719) | func formatTimeout(timeout int) string {
  function formatNonZero (line 727) | func formatNonZero(value int) string {
  function toolOutputMultiEditDiffContent (line 735) | func toolOutputMultiEditDiffContent(sty *styles.Styles, file string, met...
  function roundedEnumerator (line 776) | func roundedEnumerator(lPadding, width int) tree.Enumerator {
  function toolOutputMarkdownContent (line 794) | func toolOutputMarkdownContent(sty *styles.Styles, content string, width...
  function prettifyToolName (line 1370) | func prettifyToolName(name string) string {

FILE: internal/ui/chat/user.go
  type UserMessageItem (line 15) | type UserMessageItem struct
    method RawRender (line 38) | func (m *UserMessageItem) RawRender(width int) string {
    method Render (line 72) | func (m *UserMessageItem) Render(width int) string {
    method ID (line 87) | func (m *UserMessageItem) ID() string {
    method renderAttachments (line 92) | func (m *UserMessageItem) renderAttachments(width int) string {
    method HandleKeyEvent (line 104) | func (m *UserMessageItem) HandleKeyEvent(key tea.KeyMsg) (bool, tea.Cm...
  function NewUserMessageItem (line 26) | func NewUserMessageItem(sty *styles.Styles, message *message.Message, at...

FILE: internal/ui/common/button.go
  type ButtonOpts (line 11) | type ButtonOpts struct
  function Button (line 23) | func Button(t *styles.Styles, opts ButtonOpts) string {
  function ButtonGroup (line 54) | func ButtonGroup(t *styles.Styles, buttons []ButtonOpts, spacing string)...

FILE: internal/ui/common/capabilities.go
  type Capabilities (line 15) | type Capabilities struct
    method Update (line 41) | func (c *Capabilities) Update(msg any) {
    method SupportsTrueColor (line 93) | func (c Capabilities) SupportsTrueColor() bool {
    method SupportsKittyGraphics (line 98) | func (c Capabilities) SupportsKittyGraphics() bool {
    method SupportsSixelGraphics (line 103) | func (c Capabilities) SupportsSixelGraphics() bool {
    method CellSize (line 108) | func (c Capabilities) CellSize() (width, height int) {
  function QueryCmd (line 71) | func QueryCmd(env uv.Environ) tea.Cmd {
  function modeSupported (line 115) | func modeSupported(v ansi.ModeSetting) bool {
  function shouldQueryCapabilities (line 122) | func shouldQueryCapabilities(env uv.Environ) bool {

FILE: internal/ui/common/common.go
  constant MaxAttachmentSize (line 18) | MaxAttachmentSize = int64(5 * 1024 * 1024)
  type Common (line 24) | type Common struct
    method Config (line 30) | func (c *Common) Config() *config.Config {
    method Store (line 35) | func (c *Common) Store() *config.ConfigStore {
  function DefaultCommon (line 40) | func DefaultCommon(app *app.App) *Common {
  function CenterRect (line 50) | func CenterRect(area uv.Rectangle, width, height int) uv.Rectangle {
  function BottomLeftRect (line 62) | func BottomLeftRect(area uv.Rectangle, width, height int) uv.Rectangle {
  function IsFileTooBig (line 72) | func IsFileTooBig(filePath string, sizeLimit int64) (bool, error) {
  function CopyToClipboard (line 88) | func CopyToClipboard(text, successMessage string) tea.Cmd {
  function CopyToClipboardWithCallback (line 95) | func CopyToClipboardWithCallback(text, successMessage string, callback t...

FILE: internal/ui/common/diff.go
  function DiffFormatter (line 11) | func DiffFormatter(s *styles.Styles) *diffview.DiffView {

FILE: internal/ui/common/elements.go
  function PrettyPath (line 19) | func PrettyPath(t *styles.Styles, path string, width int) string {
  function FormatReasoningEffort (line 25) | func FormatReasoningEffort(effort string) string {
  type ModelContextInfo (line 33) | type ModelContextInfo struct
  function ModelInfo (line 41) | func ModelInfo(t *styles.Styles, modelName, providerName, reasoningInfo ...
  function formatTokensAndCost (line 86) | func formatTokensAndCost(t *styles.Styles, tokens, contextWindow int64, ...
  type StatusOpts (line 120) | type StatusOpts struct
  function Status (line 131) | func Status(t *styles.Styles, opts StatusOpts, width int) string {
  function Section (line 167) | func Section(t *styles.Styles, text string, width int, info ...string) s...
  function DialogTitle (line 190) | func DialogTitle(t *styles.Styles, title string, width int, fromColor, t...

FILE: internal/ui/common/highlight.go
  function SyntaxHighlight (line 17) | func SyntaxHighlight(st *styles.Styles, source, fileName string, bg colo...

FILE: internal/ui/common/interface.go
  type Model (line 8) | type Model interface

FILE: internal/ui/common/markdown.go
  function MarkdownRenderer (line 10) | func MarkdownRenderer(sty *styles.Styles, width int) *glamour.TermRender...
  function PlainMarkdownRenderer (line 20) | func PlainMarkdownRenderer(sty *styles.Styles, width int) *glamour.TermR...

FILE: internal/ui/common/scrollbar.go
  function Scrollbar (line 11) | func Scrollbar(s *styles.Styles, height, contentSize, viewportSize, offs...

FILE: internal/ui/completions/completions.go
  constant minHeight (line 20) | minHeight = 1
  constant maxHeight (line 21) | maxHeight = 10
  constant minWidth (line 22) | minWidth  = 10
  constant maxWidth (line 23) | maxWidth  = 100
  type SelectionMsg (line 27) | type SelectionMsg struct
  type ClosedMsg (line 33) | type ClosedMsg struct
  type CompletionItemsLoadedMsg (line 36) | type CompletionItemsLoadedMsg struct
  type Completions (line 42) | type Completions struct
    method IsOpen (line 79) | func (c *Completions) IsOpen() bool {
    method Query (line 84) | func (c *Completions) Query() string {
    method Size (line 89) | func (c *Completions) Size() (width, height int) {
    method KeyMap (line 95) | func (c *Completions) KeyMap() KeyMap {
    method Open (line 100) | func (c *Completions) Open(depth, limit int) tea.Cmd {
    method SetItems (line 116) | func (c *Completions) SetItems(files []FileCompletionValue, resources ...
    method Close (line 159) | func (c *Completions) Close() {
    method Filter (line 164) | func (c *Completions) Filter(query string) {
    method updateSize (line 179) | func (c *Completions) updateSize() {
    method HasItems (line 199) | func (c *Completions) HasItems() bool {
    method Update (line 204) | func (c *Completions) Update(msg tea.KeyPressMsg) (tea.Msg, bool) {
    method selectPrev (line 238) | func (c *Completions) selectPrev() {
    method selectNext (line 250) | func (c *Completions) selectNext() {
    method selectCurrent (line 262) | func (c *Completions) selectCurrent(keepOpen bool) tea.Msg {
    method Render (line 299) | func (c *Completions) Render() string {
  function New (line 64) | func New(normalStyle, focusedStyle, matchStyle lipgloss.Style) *Completi...
  function loadFiles (line 312) | func loadFiles(depth, limit int) []FileCompletionValue {
  function loadMCPResources (line 324) | func loadMCPResources() []ResourceCompletionValue {

FILE: internal/ui/completions/item.go
  type FileCompletionValue (line 12) | type FileCompletionValue struct
  type ResourceCompletionValue (line 17) | type ResourceCompletionValue struct
  type CompletionItem (line 25) | type CompletionItem struct
    method Text (line 50) | func (c *CompletionItem) Text() string {
    method Value (line 55) | func (c *CompletionItem) Value() any {
    method Filter (line 60) | func (c *CompletionItem) Filter() string {
    method SetMatch (line 65) | func (c *CompletionItem) SetMatch(m fuzzy.Match) {
    method SetFocused (line 71) | func (c *CompletionItem) SetFocused(focused bool) {
    method Render (line 79) | func (c *CompletionItem) Render(width int) string {
  function NewCompletionItem (line 39) | func NewCompletionItem(text string, value any, normalStyle, focusedStyle...
  function renderItem (line 92) | func renderItem(
  function matchedRanges (line 142) | func matchedRanges(in []int) [][2]int {
  function bytePosToVisibleCharPos (line 164) | func bytePosToVisibleCharPos(str string, rng [2]int) (int, int) {

FILE: internal/ui/completions/keys.go
  type KeyMap (line 8) | type KeyMap struct
    method KeyBindings (line 48) | func (k KeyMap) KeyBindings() []key.Binding {
    method FullHelp (line 58) | func (k KeyMap) FullHelp() [][]key.Binding {
    method ShortHelp (line 69) | func (k KeyMap) ShortHelp() []key.Binding {
  function DefaultKeyMap (line 18) | func DefaultKeyMap() KeyMap {

FILE: internal/ui/dialog/actions.go
  type ActionClose (line 22) | type ActionClose struct
  type ActionOpenDialog (line 28) | type ActionOpenDialog struct
  type ActionSelectSession (line 33) | type ActionSelectSession struct
  type ActionSelectModel (line 38) | type ActionSelectModel struct
  type ActionNewSession (line 47) | type ActionNewSession struct
  type ActionToggleHelp (line 48) | type ActionToggleHelp struct
  type ActionToggleCompactMode (line 49) | type ActionToggleCompactMode struct
  type ActionToggleThinking (line 50) | type ActionToggleThinking struct
  type ActionTogglePills (line 51) | type ActionTogglePills struct
  type ActionExternalEditor (line 52) | type ActionExternalEditor struct
  type ActionToggleYoloMode (line 53) | type ActionToggleYoloMode struct
  type ActionToggleNotifications (line 54) | type ActionToggleNotifications struct
  type ActionToggleTransparentBackground (line 55) | type ActionToggleTransparentBackground struct
  type ActionInitializeProject (line 56) | type ActionInitializeProject struct
  type ActionSummarize (line 57) | type ActionSummarize struct
  type ActionSelectReasoningEffort (line 62) | type ActionSelectReasoningEffort struct
  type ActionPermissionResponse (line 65) | type ActionPermissionResponse struct
  type ActionRunCustomCommand (line 70) | type ActionRunCustomCommand struct
  type ActionRunMCPPrompt (line 76) | type ActionRunMCPPrompt struct
  type ActionEnableDockerMCP (line 85) | type ActionEnableDockerMCP struct
  type ActionDisableDockerMCP (line 87) | type ActionDisableDockerMCP struct
  type ActionChangeAPIKeyState (line 92) | type ActionChangeAPIKeyState struct
  type ActionInitiateOAuth (line 101) | type ActionInitiateOAuth struct
  type ActionCompleteOAuth (line 110) | type ActionCompleteOAuth struct
  type ActionOAuthErrored (line 115) | type ActionOAuthErrored struct
  type ActionCmd (line 122) | type ActionCmd struct
  type ActionFilePickerSelected (line 128) | type ActionFilePickerSelected struct
    method Cmd (line 134) | func (a ActionFilePickerSelected) Cmd() tea.Cmd {

FILE: internal/ui/dialog/api_key_input.go
  type APIKeyInputState (line 22) | type APIKeyInputState
  constant APIKeyInputStateInitial (line 25) | APIKeyInputStateInitial APIKeyInputState = iota
  constant APIKeyInputStateVerifying (line 26) | APIKeyInputStateVerifying
  constant APIKeyInputStateVerified (line 27) | APIKeyInputStateVerified
  constant APIKeyInputStateError (line 28) | APIKeyInputStateError
  constant APIKeyInputID (line 32) | APIKeyInputID = "api_key_input"
  type APIKeyInput (line 35) | type APIKeyInput struct
    method ID (line 102) | func (m *APIKeyInput) ID() string {
    method HandleMsg (line 107) | func (m *APIKeyInput) HandleMsg(msg tea.Msg) Action {
    method Draw (line 161) | func (m *APIKeyInput) Draw(scr uv.Screen, area uv.Rectangle) *tea.Curs...
    method headerView (line 199) | func (m *APIKeyInput) headerView() string {
    method dialogTitle (line 213) | func (m *APIKeyInput) dialogTitle() string {
    method inputView (line 233) | func (m *APIKeyInput) inputView() string {
    method Cursor (line 267) | func (m *APIKeyInput) Cursor() *tea.Cursor {
    method FullHelp (line 272) | func (m *APIKeyInput) FullHelp() [][]key.Binding {
    method ShortHelp (line 282) | func (m *APIKeyInput) ShortHelp() []key.Binding {
    method verifyAPIKey (line 289) | func (m *APIKeyInput) verifyAPIKey() tea.Msg {
    method saveKeyAndContinue (line 314) | func (m *APIKeyInput) saveKeyAndContinue() Action {
  function NewAPIKeyInput (line 58) | func NewAPIKeyInput(

FILE: internal/ui/dialog/arguments.go
  constant ArgumentsID (line 24) | ArgumentsID = "arguments"
  constant maxInputWidth (line 28) | maxInputWidth        = 120
  constant minInputWidth (line 29) | minInputWidth        = 30
  constant maxViewportHeight (line 30) | maxViewportHeight    = 20
  constant argumentsFieldHeight (line 31) | argumentsFieldHeight = 3
  type Arguments (line 35) | type Arguments struct
    method ID (line 120) | func (a *Arguments) ID() string {
    method focusInput (line 125) | func (a *Arguments) focusInput(newIndex int) {
    method isFieldVisible (line 139) | func (a *Arguments) isFieldVisible(fieldIndex int) bool {
    method ensureFieldVisible (line 149) | func (a *Arguments) ensureFieldVisible(fieldIndex int) {
    method findVisibleFieldByOffset (line 172) | func (a *Arguments) findVisibleFieldByOffset(fromTop bool) int {
    method HandleMsg (line 186) | func (a *Arguments) HandleMsg(msg tea.Msg) Action {
    method Cursor (line 249) | func (a *Arguments) Cursor(descriptionHeight int) *tea.Cursor {
    method Draw (line 259) | func (a *Arguments) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor {
    method StartLoading (line 369) | func (a *Arguments) StartLoading() tea.Cmd {
    method StopLoading (line 378) | func (a *Arguments) StopLoading() {
    method ShortHelp (line 383) | func (a *Arguments) ShortHelp() []key.Binding {
    method FullHelp (line 392) | func (a *Arguments) FullHelp() [][]key.Binding {
  function NewArguments (line 63) | func NewArguments(com *common.Common, title, description string, argumen...

FILE: internal/ui/dialog/commands.go
  constant CommandsID (line 21) | CommandsID = "commands"
  type CommandType (line 24) | type CommandType
    method String (line 27) | func (c CommandType) String() string { return []string{"System", "User...
  constant sidebarCompactModeBreakpoint (line 30) | sidebarCompactModeBreakpoint = 120
  constant SystemCommands (line 34) | SystemCommands CommandType = iota
  constant UserCommands (line 35) | UserCommands
  constant MCPPrompts (line 36) | MCPPrompts
  type dockerMCPAvailabilityCheckedMsg (line 40) | type dockerMCPAvailabilityCheckedMsg struct
  type Commands (line 44) | type Commands struct
    method ID (line 152) | func (c *Commands) ID() string {
    method HandleMsg (line 157) | func (c *Commands) HandleMsg(msg tea.Msg) Action {
    method InitialCmd (line 234) | func (c *Commands) InitialCmd() tea.Cmd {
    method Cursor (line 243) | func (c *Commands) Cursor() *tea.Cursor {
    method Draw (line 275) | func (c *Commands) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor {
    method ShortHelp (line 318) | func (c *Commands) ShortHelp() []key.Binding {
    method FullHelp (line 328) | func (c *Commands) FullHelp() [][]key.Binding {
    method nextCommandType (line 336) | func (c *Commands) nextCommandType() CommandType {
    method previousCommandType (line 359) | func (c *Commands) previousCommandType() CommandType {
    method setCommandItems (line 382) | func (c *Commands) setCommandItems(commandType CommandType) {
    method defaultCommands (line 420) | func (c *Commands) defaultCommands() []*CommandItem {
    method SetCustomCommands (line 534) | func (c *Commands) SetCustomCommands(customCommands []commands.CustomC...
    method SetMCPPrompts (line 542) | func (c *Commands) SetMCPPrompts(mcpPrompts []commands.MCPPrompt) {
    method StartLoading (line 550) | func (a *Commands) StartLoading() tea.Cmd {
    method StopLoading (line 559) | func (a *Commands) StopLoading() {
  function NewCommands (line 81) | func NewCommands(com *common.Common, sessionID string, hasSession, hasTo...
  function checkDockerMCPAvailabilityCmd (line 228) | func checkDockerMCPAvailabilityCmd() tea.Cmd {
  function commandsRadioView (line 248) | func commandsRadioView(sty *styles.Styles, selected CommandType, hasUser...

FILE: internal/ui/dialog/commands_item.go
  type CommandItem (line 9) | type CommandItem struct
    method Filter (line 34) | func (c *CommandItem) Filter() string {
    method ID (line 39) | func (c *CommandItem) ID() string {
    method SetFocused (line 44) | func (c *CommandItem) SetFocused(focused bool) {
    method SetMatch (line 52) | func (c *CommandItem) SetMatch(m fuzzy.Match) {
    method Action (line 58) | func (c *CommandItem) Action() Action {
    method Shortcut (line 63) | func (c *CommandItem) Shortcut() string {
    method Render (line 68) | func (c *CommandItem) Render(width int) string {
  function NewCommandItem (line 23) | func NewCommandItem(t *styles.Styles, id, title, shortcut string, action...

FILE: internal/ui/dialog/common.go
  function InputCursor (line 15) | func InputCursor(t *styles.Styles, cur *tea.Cursor) *tea.Cursor {
  type RenderContext (line 43) | type RenderContext struct
    method AddPart (line 91) | func (rc *RenderContext) AddPart(part string) {
    method Render (line 98) | func (rc *RenderContext) Render() string {
  function NewRenderContext (line 78) | func NewRenderContext(t *styles.Styles, width int) *RenderContext {

FILE: internal/ui/dialog/dialog.go
  constant defaultDialogMaxWidth (line 14) | defaultDialogMaxWidth = 70
  constant defaultDialogHeight (line 16) | defaultDialogHeight = 20
  constant titleContentHeight (line 18) | titleContentHeight = 1
  constant inputContentHeight (line 20) | inputContentHeight = 1
  type Action (line 30) | type Action
  type Dialog (line 33) | type Dialog interface
  type LoadingDialog (line 45) | type LoadingDialog interface
  type Overlay (line 51) | type Overlay struct
    method HasDialogs (line 63) | func (d *Overlay) HasDialogs() bool {
    method ContainsDialog (line 68) | func (d *Overlay) ContainsDialog(dialogID string) bool {
    method OpenDialog (line 78) | func (d *Overlay) OpenDialog(dialog Dialog) {
    method CloseDialog (line 83) | func (d *Overlay) CloseDialog(dialogID string) {
    method CloseFrontDialog (line 93) | func (d *Overlay) CloseFrontDialog() {
    method Dialog (line 101) | func (d *Overlay) Dialog(dialogID string) Dialog {
    method DialogLast (line 111) | func (d *Overlay) DialogLast() Dialog {
    method BringToFront (line 119) | func (d *Overlay) BringToFront(dialogID string) {
    method Update (line 131) | func (d *Overlay) Update(msg tea.Msg) tea.Msg {
    method StartLoading (line 147) | func (d *Overlay) StartLoading() tea.Cmd {
    method StopLoading (line 157) | func (d *Overlay) StopLoading() {
    method Draw (line 199) | func (d *Overlay) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor {
    method removeDialog (line 208) | func (d *Overlay) removeDialog(idx int) {
  function NewOverlay (line 56) | func NewOverlay(dialogs ...Dialog) *Overlay {
  function DrawCenterCursor (line 166) | func DrawCenterCursor(scr uv.Screen, area uv.Rectangle, view string, cur...
  function DrawCenter (line 177) | func DrawCenter(scr uv.Screen, area uv.Rectangle, view string) {
  function DrawOnboarding (line 182) | func DrawOnboarding(scr uv.Screen, area uv.Rectangle, view string) {
  function DrawOnboardingCursor (line 188) | func DrawOnboardingCursor(scr uv.Screen, area uv.Rectangle, view string,...

FILE: internal/ui/dialog/filepicker.go
  constant FilePickerID (line 24) | FilePickerID = "filepicker"
  type FilePicker (line 27) | type FilePicker struct
    method CellSize (line 51) | func (f *FilePicker) CellSize() fimage.CellSize {
    method SetImageCapabilities (line 114) | func (f *FilePicker) SetImageCapabilities(caps *common.Capabilities) {
    method WorkingDir (line 125) | func (f *FilePicker) WorkingDir() string {
    method ShortHelp (line 140) | func (f *FilePicker) ShortHelp() []key.Binding {
    method FullHelp (line 149) | func (f *FilePicker) FullHelp() [][]key.Binding {
    method ID (line 165) | func (f *FilePicker) ID() string {
    method HandleMsg (line 170) | func (f *FilePicker) HandleMsg(msg tea.Msg) Action {
    method Draw (line 223) | func (f *FilePicker) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor {
    method imagePreview (line 264) | func (f *FilePicker) imagePreview(imgPrevWidth, imgPrevHeight int) str...
  function NewFilePicker (line 61) | func NewFilePicker(com *common.Common) (*FilePicker, tea.Cmd) {
  constant filePickerMinWidth (line 218) | filePickerMinWidth  = 70
  constant filePickerMinHeight (line 219) | filePickerMinHeight = 10
  function loadImage (line 299) | func loadImage(path string) (img image.Image, err error) {

FILE: internal/ui/dialog/models.go
  type ModelType (line 20) | type ModelType
    method String (line 28) | func (mt ModelType) String() string {
    method Config (line 40) | func (mt ModelType) Config() config.SelectedModelType {
    method Placeholder (line 52) | func (mt ModelType) Placeholder() string {
  constant ModelTypeLarge (line 23) | ModelTypeLarge ModelType = iota
  constant ModelTypeSmall (line 24) | ModelTypeSmall
  constant onboardingModelInputPlaceholder (line 64) | onboardingModelInputPlaceholder = "Find your fave"
  constant largeModelInputPlaceholder (line 65) | largeModelInputPlaceholder      = "Choose a model for large, complex tasks"
  constant smallModelInputPlaceholder (line 66) | smallModelInputPlaceholder      = "Choose a model for small, simple tasks"
  constant ModelsID (line 70) | ModelsID = "models"
  constant defaultModelsDialogMaxWidth (line 72) | defaultModelsDialogMaxWidth = 73
  type Models (line 75) | type Models struct
    method ID (line 159) | func (m *Models) ID() string {
    method HandleMsg (line 164) | func (m *Models) HandleMsg(msg tea.Msg) Action {
    method Cursor (line 232) | func (m *Models) Cursor() *tea.Cursor {
    method modelTypeRadioView (line 237) | func (m *Models) modelTypeRadioView() string {
    method Draw (line 257) | func (m *Models) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor {
    method ShortHelp (line 310) | func (m *Models) ShortHelp() []key.Binding {
    method FullHelp (line 330) | func (m *Models) FullHelp() [][]key.Binding {
    method isSelectedConfigured (line 334) | func (m *Models) isSelectedConfigured() bool {
    method setProviderItems (line 349) | func (m *Models) setProviderItems() error {
  function NewModels (line 99) | func NewModels(com *common.Common, isOnboarding bool) (*Models, error) {
  function modelKey (line 516) | func modelKey(providerID, modelID string) string {

FILE: internal/ui/dialog/models_item.go
  type ModelGroup (line 14) | type ModelGro
Copy disabled (too large) Download .json
Condensed preview — 788 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (13,759K chars).
[
  {
    "path": ".gitattributes",
    "chars": 212,
    "preview": "*.golden linguist-generated=true -text\n.github/crush-schema.json linguist-generated=true\ninternal/agent/hyper/provider.j"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 29,
    "preview": "*.go @charmbracelet/everyone\n"
  },
  {
    "path": ".github/cla-signatures.json",
    "chars": 32611,
    "preview": "{\n  \"signedContributors\": [\n    {\n      \"name\": \"caarlos0\",\n      \"id\": 245435,\n      \"comment_id\": 3133376230,\n      \"c"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 908,
    "preview": "version: 2\n\nupdates:\n  - package-ecosystem: \"gomod\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n      day:"
  },
  {
    "path": ".github/entitlements.plist",
    "chars": 274,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": ".github/labeler.yml",
    "chars": 1682,
    "preview": "# NOTE(@andreynering): We should have a single entry per label, because if we\n# have multiple the action would only appl"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 718,
    "preview": "name: build\non: [push, pull_request]\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: build-${{ github.event.pull_r"
  },
  {
    "path": ".github/workflows/cla.yml",
    "chars": 1637,
    "preview": "name: \"CLA Assistant\"\n\non:\n  issue_comment:\n    types: [created]\n  pull_request_target:\n    types: [opened, closed, sync"
  },
  {
    "path": ".github/workflows/labeler.yml",
    "chars": 749,
    "preview": "name: labeler\n\non:\n  issues:\n    types: [opened]\n  pull_request_target:\n    types: [opened]\n  workflow_dispatch:\n    inp"
  },
  {
    "path": ".github/workflows/lint-sync.yml",
    "chars": 277,
    "preview": "name: lint-sync\non:\n  # schedule:\n  #   # every Sunday at midnight\n  #   - cron: \"0 0 * * 0\"\n  workflow_dispatch: # allo"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 209,
    "preview": "name: lint\non:\n  push:\n  pull_request:\n\njobs:\n  lint:\n    uses: charmbracelet/meta/.github/workflows/lint.yml@main\n    w"
  },
  {
    "path": ".github/workflows/nightly.yml",
    "chars": 920,
    "preview": "name: nightly\n\non:\n  schedule:\n    - cron: \"0 0 * * *\" # every day at midnight\n  workflow_dispatch: # allows manual trig"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1226,
    "preview": "# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json\n\nname: goreleaser\n\non:\n  push:\n    tag"
  },
  {
    "path": ".github/workflows/schema-update.yml",
    "chars": 935,
    "preview": "name: Update files\n\non:\n  push:\n    branches: [main]\n    paths:\n      - \"internal/config/**\"\n      - \"internal/agent/hyp"
  },
  {
    "path": ".github/workflows/security.yml",
    "chars": 2912,
    "preview": "name: \"security\"\n\non:\n  pull_request:\n  push:\n    branches: [main]\n  schedule:\n    - cron: \"0 2 * * *\"\n\npermissions:\n  c"
  },
  {
    "path": ".github/workflows/snapshot.yml",
    "chars": 874,
    "preview": "name: snapshot\n\non:\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: snapshot-${"
  },
  {
    "path": ".gitignore",
    "chars": 629,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Ou"
  },
  {
    "path": ".golangci.yml",
    "chars": 790,
    "preview": "version: \"2\"\nlinters:\n  enable:\n    - bodyclose\n    # - exhaustive\n    # - goconst\n    # - godot\n    # - godox\n    # - g"
  },
  {
    "path": ".goreleaser.yml",
    "chars": 10737,
    "preview": "# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json\n# vim: set ts=2 sw=2 tw=0 fo=jcroql\nversio"
  },
  {
    "path": "AGENTS.md",
    "chars": 7405,
    "preview": "# Crush Development Guide\n\n## Project Overview\n\nCrush is a terminal-based AI coding assistant built in Go by\n[Charm](htt"
  },
  {
    "path": "CLA.md",
    "chars": 6503,
    "preview": "# Contributor License Agreement\n\nThank you for your interest in the open source project(s) managed by Charmbracelet, Inc"
  },
  {
    "path": "LICENSE.md",
    "chars": 5318,
    "preview": "# Functional Source License, Version 1.1, MIT Future License\n\n## Abbreviation\n\nFSL-1.1-MIT\n\n## Notice\n\nCopyright 2025-20"
  },
  {
    "path": "README.md",
    "chars": 23536,
    "preview": "# Crush\n\n<p align=\"center\">\n    <a href=\"https://stuff.charm.sh/crush/charm-crush.png\"><img width=\"450\" alt=\"Charm Crush"
  },
  {
    "path": "Taskfile.yaml",
    "chars": 5273,
    "preview": "# https://taskfile.dev\n\nversion: \"3\"\n\nvars:\n  VERSION:\n    sh: git describe --long 2>/dev/null || echo \"\"\n  RACE:\n    sh"
  },
  {
    "path": "crush.json",
    "chars": 978,
    "preview": "{\n  \"$schema\": \"https://charm.land/crush.json\",\n  \"lsp\": {\n    \"gopls\": {\n      \"options\": {\n        \"gofumpt\": true,\n  "
  },
  {
    "path": "go.mod",
    "chars": 9797,
    "preview": "module github.com/charmbracelet/crush\n\ngo 1.26.1\n\nrequire (\n\tcharm.land/bubbles/v2 v2.0.0\n\tcharm.land/bubbletea/v2 v2.0."
  },
  {
    "path": "go.sum",
    "chars": 53166,
    "preview": "charm.land/bubbles/v2 v2.0.0 h1:tE3eK/pHjmtrDiRdoC9uGNLgpopOd8fjhEe31B/ai5s=\ncharm.land/bubbles/v2 v2.0.0/go.mod h1:rCHo"
  },
  {
    "path": "internal/agent/agent.go",
    "chars": 38643,
    "preview": "// Package agent is the core orchestration layer for Crush AI agents.\n//\n// It provides session-based AI agent functiona"
  },
  {
    "path": "internal/agent/agent_test.go",
    "chars": 18916,
    "preview": "package agent\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"charm.land/fantasy\"\n\t\"charm.la"
  },
  {
    "path": "internal/agent/agent_tool.go",
    "chars": 1755,
    "preview": "package agent\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"errors\"\n\n\t\"charm.land/fantasy\"\n\n\t\"github.com/charmbracelet/crush/interna"
  },
  {
    "path": "internal/agent/agentic_fetch_tool.go",
    "chars": 6873,
    "preview": "package agent\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n\n\t\"charm.land/fantasy\"\n\n\t\"githu"
  },
  {
    "path": "internal/agent/common_test.go",
    "chars": 7215,
    "preview": "package agent\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t\"charm.land/catwalk/pkg/catwa"
  },
  {
    "path": "internal/agent/coordinator.go",
    "chars": 32561,
    "preview": "package agent\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"maps\"\n\t\"net/htt"
  },
  {
    "path": "internal/agent/coordinator_test.go",
    "chars": 12519,
    "preview": "package agent\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"testing\"\n\n\t\"charm.land/catwalk/pkg/catwalk\"\n\t\"charm.land/fantasy\"\n\t\"githu"
  },
  {
    "path": "internal/agent/errors.go",
    "chars": 299,
    "preview": "package agent\n\nimport \"errors\"\n\nvar (\n\tErrRequestCancelled = errors.New(\"request canceled by user\")\n\tErrSessionBusy     "
  },
  {
    "path": "internal/agent/event.go",
    "chars": 1306,
    "preview": "package agent\n\nimport (\n\t\"time\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charmbracelet/crush/internal/event\"\n)\n\nfunc (a *sess"
  },
  {
    "path": "internal/agent/hyper/provider.go",
    "chars": 8897,
    "preview": "// Package hyper provides a fantasy.Provider that proxies requests to Hyper.\npackage hyper\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t"
  },
  {
    "path": "internal/agent/hyper/provider.json",
    "chars": 7732,
    "preview": "{\"name\":\"Charm Hyper\",\"id\":\"hyper\",\"api_endpoint\":\"https://hyper.charm.land/api/v1/fantasy\",\"type\":\"hyper\",\"default_larg"
  },
  {
    "path": "internal/agent/loop_detection.go",
    "chars": 2483,
    "preview": "package agent\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"io\"\n\n\t\"charm.land/fantasy\"\n)\n\nconst (\n\tloopDetectionWindowSiz"
  },
  {
    "path": "internal/agent/loop_detection_test.go",
    "chars": 6888,
    "preview": "package agent\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"charm.land/fantasy\"\n)\n\n// makeStep creates a StepResult with the given tool"
  },
  {
    "path": "internal/agent/notify/notify.go",
    "chars": 543,
    "preview": "// Package notify defines domain notification types for agent events.\n// These types are decoupled from UI concerns so t"
  },
  {
    "path": "internal/agent/prompt/prompt.go",
    "chars": 6152,
    "preview": "package prompt\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"text/template\"\n\t\"time\"\n"
  },
  {
    "path": "internal/agent/prompts.go",
    "chars": 1026,
    "preview": "package agent\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\n\t\"github.com/charmbracelet/crush/internal/agent/prompt\"\n\t\"github.com/char"
  },
  {
    "path": "internal/agent/templates/agent_tool.md",
    "chars": 1743,
    "preview": "Launch a new agent that has access to the following tools: GlobTool, GrepTool, LS, View. When you are searching for a ke"
  },
  {
    "path": "internal/agent/templates/agentic_fetch.md",
    "chars": 2924,
    "preview": "Fetches content from a URL or searches the web, then processes it using an AI model to extract information or answer que"
  },
  {
    "path": "internal/agent/templates/agentic_fetch_prompt.md.tpl",
    "chars": 4004,
    "preview": "You are a web content analysis agent for Crush. Your task is to analyze web content, search results, or web pages to ext"
  },
  {
    "path": "internal/agent/templates/coder.md.tpl",
    "chars": 17675,
    "preview": "You are Crush, a powerful AI Assistant that runs in the CLI.\n\n<critical_rules>\nThese rules override everything else. Fol"
  },
  {
    "path": "internal/agent/templates/initialize.md.tpl",
    "chars": 1646,
    "preview": "Analyze this codebase and create/update **{{.Config.Options.InitializeAs}}** to help future agents work effectively in t"
  },
  {
    "path": "internal/agent/templates/summary.md",
    "chars": 1752,
    "preview": "You are summarizing a conversation to preserve context for continuing work later.\n\n**Critical**: This summary will be th"
  },
  {
    "path": "internal/agent/templates/task.md.tpl",
    "chars": 977,
    "preview": "You are an agent for Crush. Given the user's prompt, you should use the tools available to you to answer the user's ques"
  },
  {
    "path": "internal/agent/templates/title.md",
    "chars": 398,
    "preview": "you will generate a short title based on the first message a user begins a conversation with\n\n<rules>\n- ensure it is not"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/bash_tool.yaml",
    "chars": 121021,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/download_tool.yaml",
    "chars": 125219,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/fetch_tool.yaml",
    "chars": 262637,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/glob_tool.yaml",
    "chars": 118931,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/grep_tool.yaml",
    "chars": 120060,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/ls_tool.yaml",
    "chars": 117976,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/multiedit_tool.yaml",
    "chars": 184866,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/parallel_tool_calls.yaml",
    "chars": 121536,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/read_a_file.yaml",
    "chars": 178683,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/simple_test.yaml",
    "chars": 59838,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/sourcegraph_tool.yaml",
    "chars": 148113,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/update_a_file.yaml",
    "chars": 241372,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/anthropic-sonnet/write_tool.yaml",
    "chars": 121629,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/bash_tool.yaml",
    "chars": 122758,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/download_tool.yaml",
    "chars": 133858,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/fetch_tool.yaml",
    "chars": 266065,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/glob_tool.yaml",
    "chars": 123833,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/grep_tool.yaml",
    "chars": 135528,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/ls_tool.yaml",
    "chars": 126899,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/multiedit_tool.yaml",
    "chars": 346434,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/parallel_tool_calls.yaml",
    "chars": 134573,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/read_a_file.yaml",
    "chars": 190174,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/simple_test.yaml",
    "chars": 58410,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/sourcegraph_tool.yaml",
    "chars": 231417,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/update_a_file.yaml",
    "chars": 339864,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openai-gpt-5/write_tool.yaml",
    "chars": 130654,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/bash_tool.yaml",
    "chars": 123638,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/download_tool.yaml",
    "chars": 128754,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/fetch_tool.yaml",
    "chars": 268110,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/glob_tool.yaml",
    "chars": 126889,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/grep_tool.yaml",
    "chars": 128641,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/ls_tool.yaml",
    "chars": 123739,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/multiedit_tool.yaml",
    "chars": 304912,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/parallel_tool_calls.yaml",
    "chars": 134741,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/read_a_file.yaml",
    "chars": 126722,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/simple_test.yaml",
    "chars": 57797,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/sourcegraph_tool.yaml",
    "chars": 174448,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/update_a_file.yaml",
    "chars": 200674,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/write_tool.yaml",
    "chars": 131594,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/bash_tool.yaml",
    "chars": 142330,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/download_tool.yaml",
    "chars": 143218,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/fetch_tool.yaml",
    "chars": 300824,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/glob_tool.yaml",
    "chars": 136548,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/grep_tool.yaml",
    "chars": 141424,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/ls_tool.yaml",
    "chars": 136105,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/multiedit_tool.yaml",
    "chars": 293649,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/parallel_tool_calls.yaml",
    "chars": 130320,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/read_a_file.yaml",
    "chars": 197128,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/simple_test.yaml",
    "chars": 69536,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/sourcegraph_tool.yaml",
    "chars": 192329,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/update_a_file.yaml",
    "chars": 192005,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/testdata/TestCoderAgent/zai-glm4.6/write_tool.yaml",
    "chars": 142668,
    "preview": "---\nversion: 2\ninteractions:\n- id: 0\n  request:\n    proto: HTTP/1.1\n    proto_major: 1\n    proto_minor: 1\n    content_le"
  },
  {
    "path": "internal/agent/tools/bash.go",
    "chars": 13746,
    "preview": "package tools\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"stri"
  },
  {
    "path": "internal/agent/tools/bash.tpl",
    "chars": 5482,
    "preview": "Executes bash commands with automatic background conversion for long-running tasks.\n\n<cross_platform>\nUses mvdan/sh inte"
  },
  {
    "path": "internal/agent/tools/bash_test.go",
    "chars": 3240,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charmbracelet/crush/i"
  },
  {
    "path": "internal/agent/tools/context_test.go",
    "chars": 5397,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\n// Test-specific context key types to avoid collisions\ntype (\n\ttestStri"
  },
  {
    "path": "internal/agent/tools/diagnostics.go",
    "chars": 6408,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"charm.land/fantas"
  },
  {
    "path": "internal/agent/tools/diagnostics.md",
    "chars": 679,
    "preview": "Get diagnostics for file and/or project.\n\n<usage>\n- Provide file path to get diagnostics for that file\n- Leave path empt"
  },
  {
    "path": "internal/agent/tools/download.go",
    "chars": 4663,
    "preview": "package tools\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n"
  },
  {
    "path": "internal/agent/tools/download.md",
    "chars": 812,
    "preview": "Downloads binary data from URL and saves to local file.\n\n<usage>\n- Provide URL to download from\n- Specify local file pat"
  },
  {
    "path": "internal/agent/tools/edit.go",
    "chars": 14096,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"charm.land"
  },
  {
    "path": "internal/agent/tools/edit.md",
    "chars": 5009,
    "preview": "Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edi"
  },
  {
    "path": "internal/agent/tools/fetch.go",
    "chars": 5754,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode/utf8\"\n\n\t\"charm.land/"
  },
  {
    "path": "internal/agent/tools/fetch.md",
    "chars": 1584,
    "preview": "Fetches raw content from URL and returns it in specified format without any AI processing.\n\n<when_to_use>\nUse this tool "
  },
  {
    "path": "internal/agent/tools/fetch_helpers.go",
    "chars": 4667,
    "preview": "package tools\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"regexp\"\n\t\"strings\"\n\t\"u"
  },
  {
    "path": "internal/agent/tools/fetch_types.go",
    "chars": 2101,
    "preview": "package tools\n\n// AgenticFetchToolName is the name of the agentic fetch tool.\nconst AgenticFetchToolName = \"agentic_fetc"
  },
  {
    "path": "internal/agent/tools/glob.go",
    "chars": 3020,
    "preview": "package tools\n\nimport (\n\t\"bytes\"\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"s"
  },
  {
    "path": "internal/agent/tools/glob.md",
    "chars": 1439,
    "preview": "Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest fi"
  },
  {
    "path": "internal/agent/tools/grep.go",
    "chars": 10589,
    "preview": "package tools\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t"
  },
  {
    "path": "internal/agent/tools/grep.md",
    "chars": 1899,
    "preview": "Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modifica"
  },
  {
    "path": "internal/agent/tools/grep_test.go",
    "chars": 11186,
    "preview": "package tools\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test"
  },
  {
    "path": "internal/agent/tools/job_kill.go",
    "chars": 1511,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charmbracelet/crush/internal/sh"
  },
  {
    "path": "internal/agent/tools/job_kill.md",
    "chars": 494,
    "preview": "Terminates a background shell process.\n\n<usage>\n- Provide the shell ID returned from a background bash execution\n- Cance"
  },
  {
    "path": "internal/agent/tools/job_output.go",
    "chars": 2334,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charmbracelet/crush/"
  },
  {
    "path": "internal/agent/tools/job_output.md",
    "chars": 833,
    "preview": "Retrieves the current output from a background shell.\n\n<usage>\n- Provide the shell ID returned from a background bash ex"
  },
  {
    "path": "internal/agent/tools/job_test.go",
    "chars": 8536,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/crush/internal/shell\"\n\t\"git"
  },
  {
    "path": "internal/agent/tools/list_mcp_resources.go",
    "chars": 2915,
    "preview": "package tools\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charm"
  },
  {
    "path": "internal/agent/tools/list_mcp_resources.md",
    "chars": 379,
    "preview": "Lists available resources from an MCP server.\n\n<when_to_use>\nUse this tool to discover which resources are available bef"
  },
  {
    "path": "internal/agent/tools/ls.go",
    "chars": 6818,
    "preview": "package tools\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"charm.land/fantasy\"\n\t\"g"
  },
  {
    "path": "internal/agent/tools/ls.md",
    "chars": 1129,
    "preview": "Shows files and subdirectories in tree structure for exploring project organization.\n\n<usage>\n- Provide path to list (de"
  },
  {
    "path": "internal/agent/tools/lsp_restart.go",
    "chars": 2128,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"maps\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"charm.land/fantasy\"\n\t\"git"
  },
  {
    "path": "internal/agent/tools/lsp_restart.md",
    "chars": 779,
    "preview": "Restart LSP (Language Server Protocol) clients.\n\n<usage>\n- Restart all running LSP clients or a specific LSP client by n"
  },
  {
    "path": "internal/agent/tools/mcp/init.go",
    "chars": 13383,
    "preview": "// Package mcp provides functionality for managing Model Context Protocol (MCP)\n// clients within the Crush application."
  },
  {
    "path": "internal/agent/tools/mcp/init_test.go",
    "chars": 1008,
    "preview": "package mcp\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n\t\"github.com/stretchr/testify"
  },
  {
    "path": "internal/agent/tools/mcp/prompts.go",
    "chars": 2170,
    "preview": "package mcp\n\nimport (\n\t\"context\"\n\t\"iter\"\n\t\"log/slog\"\n\n\t\"github.com/charmbracelet/crush/internal/config\"\n\t\"github.com/cha"
  },
  {
    "path": "internal/agent/tools/mcp/resources.go",
    "chars": 3035,
    "preview": "package mcp\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"iter\"\n\t\"log/slog\"\n\n\t\"github.com/charmbracelet/crush/internal/config\"\n\t\"gith"
  },
  {
    "path": "internal/agent/tools/mcp/tools.go",
    "chars": 5704,
    "preview": "package mcp\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"iter\"\n\t\"log/slog\"\n\t\"slices\"\n\t\"strings\"\n\n\t\""
  },
  {
    "path": "internal/agent/tools/mcp/tools_test.go",
    "chars": 2733,
    "preview": "package mcp\n\nimport (\n\t\"encoding/base64\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestEnsureBase64(t *"
  },
  {
    "path": "internal/agent/tools/mcp-tools.go",
    "chars": 3978,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"slices\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charmbracelet/crush/internal/age"
  },
  {
    "path": "internal/agent/tools/multiedit.go",
    "chars": 14232,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"charm.land"
  },
  {
    "path": "internal/agent/tools/multiedit.md",
    "chars": 5093,
    "preview": "Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace opera"
  },
  {
    "path": "internal/agent/tools/multiedit_test.go",
    "chars": 5918,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/crush/internal/history\""
  },
  {
    "path": "internal/agent/tools/read_mcp_resource.go",
    "chars": 2953,
    "preview": "package tools\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"strings\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/c"
  },
  {
    "path": "internal/agent/tools/read_mcp_resource.md",
    "chars": 483,
    "preview": "Reads a resource from an MCP server and returns its contents.\n\n<when_to_use>\nUse this tool to fetch a specific resource "
  },
  {
    "path": "internal/agent/tools/references.go",
    "chars": 5723,
    "preview": "package tools\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t_ \"embed\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"maps\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"s"
  },
  {
    "path": "internal/agent/tools/references.md",
    "chars": 1049,
    "preview": "Find all references to/usage of a symbol by name using the Language Server Protocol (LSP).\n\n<usage>\n- Provide symbol nam"
  },
  {
    "path": "internal/agent/tools/rg.go",
    "chars": 1207,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"log/slog\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/charmbracele"
  },
  {
    "path": "internal/agent/tools/safe.go",
    "chars": 857,
    "preview": "package tools\n\nimport \"runtime\"\n\nvar safeCommands = []string{\n\t// Bash builtins and core utils\n\t\"cal\",\n\t\"date\",\n\t\"df\",\n\t"
  },
  {
    "path": "internal/agent/tools/search.go",
    "chars": 6495,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand/v2\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"ti"
  },
  {
    "path": "internal/agent/tools/sourcegraph.go",
    "chars": 7792,
    "preview": "package tools\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"c"
  },
  {
    "path": "internal/agent/tools/sourcegraph.md",
    "chars": 2004,
    "preview": "Search code across public repositories using Sourcegraph's GraphQL API.\n\n<usage>\n- Provide search query using Sourcegrap"
  },
  {
    "path": "internal/agent/tools/testdata/grep.txt",
    "chars": 70,
    "preview": "test file for grep\nI wanna grep THIS particular word\nand nothing else\n"
  },
  {
    "path": "internal/agent/tools/todos.go",
    "chars": 3996,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\n\t\"charm.land/fantasy\"\n\t\"github.com/charmbracelet/crush/internal/se"
  },
  {
    "path": "internal/agent/tools/todos.md",
    "chars": 2898,
    "preview": "Creates and manages a structured task list for tracking progress on complex, multi-step coding tasks.\n\n<when_to_use>\nUse"
  },
  {
    "path": "internal/agent/tools/tools.go",
    "chars": 1854,
    "preview": "package tools\n\nimport (\n\t\"context\"\n)\n\ntype (\n\tsessionIDContextKey string\n\tmessageIDContextKey string\n\tsupportsImagesKey "
  },
  {
    "path": "internal/agent/tools/view.go",
    "chars": 10491,
    "preview": "package tools\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t_ \"embed\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\""
  },
  {
    "path": "internal/agent/tools/view.md",
    "chars": 1243,
    "preview": "Reads and displays file contents with line numbers for examining code, logs, or text data.\n\n<usage>\n- Provide file path "
  },
  {
    "path": "internal/agent/tools/view_test.go",
    "chars": 1927,
    "preview": "package tools\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nf"
  },
  {
    "path": "internal/agent/tools/web_fetch.go",
    "chars": 2226,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"charm.land/fantasy\"\n)\n\n//go"
  },
  {
    "path": "internal/agent/tools/web_fetch.md",
    "chars": 970,
    "preview": "Fetches content from a web URL (for use by sub-agents).\n\n<usage>\n- Provide a URL to fetch\n- The tool fetches the content"
  },
  {
    "path": "internal/agent/tools/web_search.go",
    "chars": 1416,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"log/slog\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"charm.land/fantasy\"\n)\n\n//go:embed web_s"
  },
  {
    "path": "internal/agent/tools/web_search.md",
    "chars": 647,
    "preview": "Searches the web using DuckDuckGo and returns search results.\n\n<usage>\n- Provide a search query to find information on t"
  },
  {
    "path": "internal/agent/tools/write.go",
    "chars": 5445,
    "preview": "package tools\n\nimport (\n\t\"context\"\n\t_ \"embed\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"charm.land"
  },
  {
    "path": "internal/agent/tools/write.md",
    "chars": 886,
    "preview": "Creates or updates files in filesystem for saving/modifying text content.\n\n<usage>\n- Provide file path to write\n- Includ"
  },
  {
    "path": "internal/ansiext/ansi.go",
    "chars": 539,
    "preview": "package ansiext\n\nimport (\n\t\"strings\"\n\n\t\"github.com/charmbracelet/x/ansi\"\n)\n\n// Escape replaces control characters with t"
  },
  {
    "path": "internal/app/app.go",
    "chars": 19263,
    "preview": "// Package app wires together services, coordinates agents, and manages\n// application lifecycle.\npackage app\n\nimport (\n"
  },
  {
    "path": "internal/app/app_test.go",
    "chars": 3423,
    "preview": "package app\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"testing\"\n\t\"testing/synctest\"\n\t\"time\"\n\n\ttea \"charm.land/bubbletea/v2\"\n\t\"github"
  },
  {
    "path": "internal/app/lsp_events.go",
    "chars": 2737,
    "preview": "package app\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/crush/internal/csync\"\n\t\"github.com/charmbracelet/cr"
  },
  {
    "path": "internal/app/provider.go",
    "chars": 3056,
    "preview": "package app\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/crush/internal/config\"\n\txstrings \"github.com/charmbr"
  },
  {
    "path": "internal/app/provider_test.go",
    "chars": 5587,
    "preview": "package app\n\nimport (\n\t\"testing\"\n\n\t\"charm.land/catwalk/pkg/catwalk\"\n\t\"github.com/charmbracelet/crush/internal/config\"\n\t\""
  },
  {
    "path": "internal/app/resolve_session_test.go",
    "chars": 4819,
    "preview": "package app\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/crush/internal"
  },
  {
    "path": "internal/cmd/dirs.go",
    "chars": 1677,
    "preview": "package cmd\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"charm.land/lipgloss/v2/table\"\n\t\"github.com/cha"
  },
  {
    "path": "internal/cmd/dirs_test.go",
    "chars": 1170,
    "preview": "package cmd\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc init() "
  },
  {
    "path": "internal/cmd/login.go",
    "chars": 5455,
    "preview": "package cmd\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"github.com/atotto/clipboa"
  },
  {
    "path": "internal/cmd/logs.go",
    "chars": 5000,
    "preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"time\"\n\n\t\"charm.land/lo"
  },
  {
    "path": "internal/cmd/models.go",
    "chars": 2595,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"charm.land/catwalk/pkg/catwalk\"\n\t\"charm.land/lipgloss"
  },
  {
    "path": "internal/cmd/projects.go",
    "chars": 1724,
    "preview": "package cmd\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"charm.land/lipgloss/v2/table\"\n\t\"github.com/cha"
  },
  {
    "path": "internal/cmd/projects_test.go",
    "chars": 1374,
    "preview": "package cmd\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/crush/internal/projects\"\n\t\"github"
  },
  {
    "path": "internal/cmd/root.go",
    "chars": 8917,
    "preview": "package cmd\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings"
  },
  {
    "path": "internal/cmd/run.go",
    "chars": 3305,
    "preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\n\t\"charm.land/log/v2\"\n\t\"github.com/cha"
  },
  {
    "path": "internal/cmd/schema.go",
    "chars": 644,
    "preview": "package cmd\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/charmbracelet/crush/internal/config\"\n\t\"github.com/invopop/js"
  },
  {
    "path": "internal/cmd/session.go",
    "chars": 18264,
    "preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"strings\"\n\t\"syscal"
  },
  {
    "path": "internal/cmd/stats/AGENTS.md",
    "chars": 78,
    "preview": "# General Guidelines\n\n- always format CSS, HTML, and JS files with `prettier`\n"
  },
  {
    "path": "internal/cmd/stats/index.css",
    "chars": 4257,
    "preview": ":root {\n  /* Dark mode colors - charmtone dark palette */\n  --bg: #201f26;\n  --bg-secondary: #2d2c35;\n  --text: #fffaf1;"
  },
  {
    "path": "internal/cmd/stats/index.html",
    "chars": 4039,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-w"
  },
  {
    "path": "internal/cmd/stats/index.js",
    "chars": 10344,
    "preview": "// Get all charmtone colors once from computed styles\nconst rootStyles = getComputedStyle(document.documentElement);\ncon"
  },
  {
    "path": "internal/cmd/stats.go",
    "chars": 10459,
    "preview": "package cmd\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"os\"\n\t\"os"
  },
  {
    "path": "internal/cmd/update_providers.go",
    "chars": 2204,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\n\t\"charm.land/lipgloss/v2\"\n\t\"github.com/charmbracelet/crush/internal/config\"\n\t\""
  },
  {
    "path": "internal/commands/commands.go",
    "chars": 5545,
    "preview": "package commands\n\nimport (\n\t\"context\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/c"
  },
  {
    "path": "internal/config/agent_id_test.go",
    "chars": 700,
    "preview": "package config\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfun"
  },
  {
    "path": "internal/config/attribution_migration_test.go",
    "chars": 1941,
    "preview": "package config\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestAttributionMigration(t *testing."
  },
  {
    "path": "internal/config/catwalk.go",
    "chars": 1870,
    "preview": "package config\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"log/slog\"\n\t\"sync\"\n\t\"sync/atomic\"\n\n\t\"charm.land/catwalk/pkg/catwalk\"\n\t\"ch"
  },
  {
    "path": "internal/config/catwalk_test.go",
    "chars": 5298,
    "preview": "package config\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"os\"\n\t\"testing\"\n\n\t\"charm.land/catwalk/pkg/catwalk\"\n\t\"git"
  },
  {
    "path": "internal/config/config.go",
    "chars": 26178,
    "preview": "package config\n\nimport (\n\t\"cmp\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"maps\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"slices\"\n\t\"strin"
  },
  {
    "path": "internal/config/copilot.go",
    "chars": 15,
    "preview": "package config\n"
  },
  {
    "path": "internal/config/docker_mcp.go",
    "chars": 3759,
    "preview": "package config\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar dockerMCPVersionRunner = func(ctx context.C"
  },
  {
    "path": "internal/config/docker_mcp_test.go",
    "chars": 4627,
    "preview": "package config\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/crush/intern"
  },
  {
    "path": "internal/config/hyper.go",
    "chars": 2812,
    "preview": "package config\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"net/http\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"t"
  },
  {
    "path": "internal/config/hyper_test.go",
    "chars": 4583,
    "preview": "package config\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"os\"\n\t\"testing\"\n\n\t\"charm.land/catwalk/pkg/catwalk\"\n\t\"git"
  }
]

// ... and 588 more files (download for full content)

About this extraction

This page contains the full source code of the charmbracelet/crush GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 788 files (11.6 MB), approximately 3.1M tokens, and a symbol index with 2878 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!