on main help sign in
refactor: remove global config (#2132)

* refactor: remove global config from ui * refactor: remove global config from lsp * refactor: remove global config

commit2c9670a890c216626e5f9212fe9cf7099525b2da authorKujtim Hoxha <kujtimii.h@gmail.com> dateFri 6 Feb 2026, 11:57 (8 months ago) parentef1ba40
18 files changed+64−75
internal/agent/coordinator.go+1−1 internal/agent/tools/mcp-tools.go+5−2 internal/agent/tools/mcp/init.go+2−3 internal/agent/tools/mcp/prompts.go+3−2 internal/agent/tools/mcp/tools.go+7−8 internal/app/lsp.go+1−1 internal/cmd/login.go+4−6 internal/cmd/root.go+3−3 internal/commands/commands.go+2−2 internal/config/init.go+8−17 internal/lsp/client.go+12−10 internal/lsp/client_test.go+1−1 internal/lsp/handlers.go−6 internal/ui/chat/messages.go+5−3 internal/ui/dialog/api_key_input.go+1−1 internal/ui/model/header.go+2−2 internal/ui/model/onboarding.go+1−1 internal/ui/model/ui.go+6−6
internal/agent/coordinator.go+1−1
@@ -446,7 +446,7 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
446446 }
447447 }
448448
449− for _, tool := range tools.GetMCPTools(c.permissions, c.cfg.WorkingDir()) {
449+ for _, tool := range tools.GetMCPTools(c.permissions, c.cfg, c.cfg.WorkingDir()) {
450450 if agent.AllowedMCP == nil {
451451 // No MCP restrictions
452452 filteredTools = append(filteredTools, tool)
internal/agent/tools/mcp-tools.go+5−2
@@ -6,11 +6,12 @@ import (
66
77 "charm.land/fantasy"
88 "github.com/charmbracelet/crush/internal/agent/tools/mcp"
9+ "github.com/charmbracelet/crush/internal/config"
910 "github.com/charmbracelet/crush/internal/permission"
1011)
1112
1213// GetMCPTools gets all the currently available MCP tools.
13−func GetMCPTools(permissions permission.Service, wd string) []*Tool {
14+func GetMCPTools(permissions permission.Service, cfg *config.Config, wd string) []*Tool {
1415 var result []*Tool
1516 for mcpName, tools := range mcp.Tools() {
1617 for _, tool := range tools {
@@ -19,6 +20,7 @@ func GetMCPTools(permissions permission.Service, wd string) []*Tool {
1920 tool: tool,
2021 permissions: permissions,
2122 workingDir: wd,
23+ cfg: cfg,
2224 })
2325 }
2426 }
@@ -29,6 +31,7 @@ func GetMCPTools(permissions permission.Service, wd string) []*Tool {
2931type Tool struct {
3032 mcpName string
3133 tool *mcp.Tool
34+ cfg *config.Config
3235 permissions permission.Service
3336 workingDir string
3437 providerOptions fantasy.ProviderOptions
@@ -107,7 +110,7 @@ func (m *Tool) Run(ctx context.Context, params fantasy.ToolCall) (fantasy.ToolRe
107110 return fantasy.ToolResponse{}, permission.ErrorPermissionDenied
108111 }
109112
110− result, err := mcp.RunTool(ctx, m.mcpName, m.tool.Name, params.Input)
113+ result, err := mcp.RunTool(ctx, m.cfg, m.mcpName, m.tool.Name, params.Input)
111114 if err != nil {
112115 return fantasy.NewTextErrorResponse(err.Error()), nil
113116 }
internal/agent/tools/mcp/init.go+2−3
@@ -189,7 +189,7 @@ func Initialize(ctx context.Context, permissions permission.Service, cfg *config
189189 return
190190 }
191191
192− toolCount := updateTools(name, tools)
192+ toolCount := updateTools(cfg, name, tools)
193193 updatePrompts(name, prompts)
194194 sessions.Set(name, session)
195195
@@ -214,13 +214,12 @@ func WaitForInit(ctx context.Context) error {
214214 }
215215}
216216
217−func getOrRenewClient(ctx context.Context, name string) (*mcp.ClientSession, error) {
217+func getOrRenewClient(ctx context.Context, cfg *config.Config, name string) (*mcp.ClientSession, error) {
218218 sess, ok := sessions.Get(name)
219219 if !ok {
220220 return nil, fmt.Errorf("mcp '%s' not available", name)
221221 }
222222
223− cfg := config.Get()
224223 m := cfg.MCP[name]
225224 state, _ := states.Get(name)
226225
internal/agent/tools/mcp/prompts.go+3−2
@@ -5,6 +5,7 @@ import (
55 "iter"
66 "log/slog"
77
8+ "github.com/charmbracelet/crush/internal/config"
89 "github.com/charmbracelet/crush/internal/csync"
910 "github.com/modelcontextprotocol/go-sdk/mcp"
1011)
@@ -19,8 +20,8 @@ func Prompts() iter.Seq2[string, []*Prompt] {
1920}
2021
2122// GetPromptMessages retrieves the content of an MCP prompt with the given arguments.
22−func GetPromptMessages(ctx context.Context, clientName, promptName string, args map[string]string) ([]string, error) {
23− c, err := getOrRenewClient(ctx, clientName)
23+func GetPromptMessages(ctx context.Context, cfg *config.Config, clientName, promptName string, args map[string]string) ([]string, error) {
24+ c, err := getOrRenewClient(ctx, cfg, clientName)
2425 if err != nil {
2526 return nil, err
2627 }
internal/agent/tools/mcp/tools.go+7−8
@@ -32,13 +32,13 @@ func Tools() iter.Seq2[string, []*Tool] {
3232}
3333
3434// RunTool runs an MCP tool with the given input parameters.
35−func RunTool(ctx context.Context, name, toolName string, input string) (ToolResult, error) {
35+func RunTool(ctx context.Context, cfg *config.Config, name, toolName string, input string) (ToolResult, error) {
3636 var args map[string]any
3737 if err := json.Unmarshal([]byte(input), &args); err != nil {
3838 return ToolResult{}, fmt.Errorf("error parsing parameters: %s", err)
3939 }
4040
41− c, err := getOrRenewClient(ctx, name)
41+ c, err := getOrRenewClient(ctx, cfg, name)
4242 if err != nil {
4343 return ToolResult{}, err
4444 }
@@ -108,7 +108,7 @@ func RunTool(ctx context.Context, name, toolName string, input string) (ToolResu
108108
109109// RefreshTools gets the updated list of tools from the MCP and updates the
110110// global state.
111−func RefreshTools(ctx context.Context, name string) {
111+func RefreshTools(ctx context.Context, cfg *config.Config, name string) {
112112 session, ok := sessions.Get(name)
113113 if !ok {
114114 slog.Warn("Refresh tools: no session", "name", name)
@@ -121,7 +121,7 @@ func RefreshTools(ctx context.Context, name string) {
121121 return
122122 }
123123
124− toolCount := updateTools(name, tools)
124+ toolCount := updateTools(cfg, name, tools)
125125
126126 prev, _ := states.Get(name)
127127 prev.Counts.Tools = toolCount
@@ -139,8 +139,8 @@ func getTools(ctx context.Context, session *mcp.ClientSession) ([]*Tool, error)
139139 return result.Tools, nil
140140}
141141
142−func updateTools(name string, tools []*Tool) int {
143− tools = filterDisabledTools(name, tools)
142+func updateTools(cfg *config.Config, name string, tools []*Tool) int {
143+ tools = filterDisabledTools(cfg, name, tools)
144144 if len(tools) == 0 {
145145 allTools.Del(name)
146146 return 0
@@ -150,8 +150,7 @@ func updateTools(name string, tools []*Tool) int {
150150}
151151
152152// filterDisabledTools removes tools that are disabled via config.
153−func filterDisabledTools(mcpName string, tools []*Tool) []*Tool {
154− cfg := config.Get()
153+func filterDisabledTools(cfg *config.Config, mcpName string, tools []*Tool) []*Tool {
155154 mcpCfg, ok := cfg.MCP[mcpName]
156155 if !ok || len(mcpCfg.DisabledTools) == 0 {
157156 return tools
internal/app/lsp.go+1−1
@@ -114,7 +114,7 @@ func (app *App) createAndStartLSPClient(ctx context.Context, name string, config
114114 updateLSPState(name, lsp.StateStarting, nil, nil, 0)
115115
116116 // Create LSP client.
117− lspClient, err := lsp.New(ctx, name, config, app.config.Resolver())
117+ lspClient, err := lsp.New(ctx, name, config, app.config.Resolver(), app.config.Options.DebugLSP)
118118 if err != nil {
119119 if !userConfigured {
120120 slog.Warn("Default LSP config skipped due to error", "name", name, "error", err)
internal/cmd/login.go+4−6
@@ -52,17 +52,16 @@ crush login copilot
5252 }
5353 switch provider {
5454 case "hyper":
55− return loginHyper()
55+ return loginHyper(app.Config())
5656 case "copilot", "github", "github-copilot":
57− return loginCopilot()
57+ return loginCopilot(app.Config())
5858 default:
5959 return fmt.Errorf("unknown platform: %s", args[0])
6060 }
6161 },
6262}
6363
64−func loginHyper() error {
65− cfg := config.Get()
64+func loginHyper(cfg *config.Config) error {
6665 if !hyperp.Enabled() {
6766 return fmt.Errorf("hyper not enabled")
6867 }
@@ -124,10 +123,9 @@ func loginHyper() error {
124123 return nil
125124}
126125
127−func loginCopilot() error {
126+func loginCopilot(cfg *config.Config) error {
128127 ctx := getLoginContext()
129128
130− cfg := config.Get()
131129 if cfg.HasConfigField("providers.copilot.oauth") {
132130 fmt.Println("You are already logged in to GitHub Copilot.")
133131 return nil
internal/cmd/root.go+3−3
@@ -227,21 +227,21 @@ func setupApp(cmd *cobra.Command) (*app.App, error) {
227227 return nil, err
228228 }
229229
230− if shouldEnableMetrics() {
230+ if shouldEnableMetrics(cfg) {
231231 event.Init()
232232 }
233233
234234 return appInstance, nil
235235}
236236
237−func shouldEnableMetrics() bool {
237+func shouldEnableMetrics(cfg *config.Config) bool {
238238 if v, _ := strconv.ParseBool(os.Getenv("CRUSH_DISABLE_METRICS")); v {
239239 return false
240240 }
241241 if v, _ := strconv.ParseBool(os.Getenv("DO_NOT_TRACK")); v {
242242 return false
243243 }
244− if config.Get().Options.DisableMetrics {
244+ if cfg.Options.DisableMetrics {
245245 return false
246246 }
247247 return true
internal/commands/commands.go+2−2
@@ -227,9 +227,9 @@ func isMarkdownFile(name string) bool {
227227 return strings.HasSuffix(strings.ToLower(name), ".md")
228228}
229229
230−func GetMCPPrompt(clientID, promptID string, args map[string]string) (string, error) {
230+func GetMCPPrompt(cfg *config.Config, clientID, promptID string, args map[string]string) (string, error) {
231231 // TODO: we should pass the context down
232− result, err := mcp.GetPromptMessages(context.Background(), clientID, promptID, args)
232+ result, err := mcp.GetPromptMessages(context.Background(), cfg, clientID, promptID, args)
233233 if err != nil {
234234 return "", err
235235 }
internal/config/init.go+8−17
@@ -6,7 +6,6 @@ import (
66 "path/filepath"
77 "slices"
88 "strings"
9− "sync/atomic"
109
1110 "github.com/charmbracelet/crush/internal/fsext"
1211)
@@ -19,25 +18,15 @@ type ProjectInitFlag struct {
1918 Initialized bool `json:"initialized"`
2019}
2120
22−// TODO: we need to remove the global config instance keeping it now just until everything is migrated
23−var instance atomic.Pointer[Config]
24−
2521func Init(workingDir, dataDir string, debug bool) (*Config, error) {
2622 cfg, err := Load(workingDir, dataDir, debug)
2723 if err != nil {
2824 return nil, err
2925 }
30− instance.Store(cfg)
31− return instance.Load(), nil
32−}
33−
34−func Get() *Config {
35− cfg := instance.Load()
36− return cfg
26+ return cfg, nil
3727}
3828
39−func ProjectNeedsInitialization() (bool, error) {
40− cfg := Get()
29+func ProjectNeedsInitialization(cfg *Config) (bool, error) {
4130 if cfg == nil {
4231 return false, fmt.Errorf("config not loaded")
4332 }
@@ -110,8 +99,7 @@ func dirHasNoVisibleFiles(dir string) (bool, error) {
11099 return len(files) == 0, nil
111100}
112101
113−func MarkProjectInitialized() error {
114− cfg := Get()
102+func MarkProjectInitialized(cfg *Config) error {
115103 if cfg == nil {
116104 return fmt.Errorf("config not loaded")
117105 }
@@ -126,10 +114,13 @@ func MarkProjectInitialized() error {
126114 return nil
127115}
128116
129−func HasInitialDataConfig() bool {
117+func HasInitialDataConfig(cfg *Config) bool {
118+ if cfg == nil {
119+ return false
120+ }
130121 cfgPath := GlobalConfigData()
131122 if _, err := os.Stat(cfgPath); err != nil {
132123 return false
133124 }
134− return Get().IsConfigured()
125+ return cfg.IsConfigured()
135126}
internal/lsp/client.go+12−10
@@ -35,6 +35,7 @@ type DiagnosticCounts struct {
3535type Client struct {
3636 client *powernap.Client
3737 name string
38+ debug bool
3839
3940 // Working directory this LSP is scoped to.
4041 workDir string
@@ -68,7 +69,7 @@ type Client struct {
6869}
6970
7071// New creates a new LSP client using the powernap implementation.
71−func New(ctx context.Context, name string, cfg config.LSPConfig, resolver config.VariableResolver) (*Client, error) {
72+func New(ctx context.Context, name string, cfg config.LSPConfig, resolver config.VariableResolver, debug bool) (*Client, error) {
7273 client := &Client{
7374 name: name,
7475 fileTypes: cfg.FileTypes,
@@ -76,6 +77,7 @@ func New(ctx context.Context, name string, cfg config.LSPConfig, resolver config
7677 openFiles: csync.NewMap[string, *OpenFileInfo](),
7778 config: cfg,
7879 ctx: ctx,
80+ debug: debug,
7981 resolver: resolver,
8082 }
8183 client.serverState.Store(StateStarting)
@@ -174,7 +176,11 @@ func (c *Client) registerHandlers() {
174176 c.RegisterServerRequestHandler("workspace/applyEdit", HandleApplyEdit)
175177 c.RegisterServerRequestHandler("workspace/configuration", HandleWorkspaceConfiguration)
176178 c.RegisterServerRequestHandler("client/registerCapability", HandleRegisterCapability)
177− c.RegisterNotificationHandler("window/showMessage", HandleServerMessage)
179+ c.RegisterNotificationHandler("window/showMessage", func(ctx context.Context, method string, params json.RawMessage) {
180+ if c.debug {
181+ HandleServerMessage(ctx, method, params)
182+ }
183+ })
178184 c.RegisterNotificationHandler("textDocument/publishDiagnostics", func(_ context.Context, _ string, params json.RawMessage) {
179185 HandleDiagnostics(c, params)
180186 })
@@ -262,8 +268,6 @@ func (c *Client) SetDiagnosticsCallback(callback func(name string, count int)) {
262268
263269// WaitForServerReady waits for the server to be ready
264270func (c *Client) WaitForServerReady(ctx context.Context) error {
265− cfg := config.Get()
266−
267271 // Set initial state
268272 c.SetServerState(StateStarting)
269273
@@ -275,7 +279,7 @@ func (c *Client) WaitForServerReady(ctx context.Context) error {
275279 ticker := time.NewTicker(500 * time.Millisecond)
276280 defer ticker.Stop()
277281
278− if cfg != nil && cfg.Options.DebugLSP {
282+ if c.debug {
279283 slog.Debug("Waiting for LSP server to be ready...")
280284 }
281285
@@ -289,7 +293,7 @@ func (c *Client) WaitForServerReady(ctx context.Context) error {
289293 case <-ticker.C:
290294 // Check if client is running
291295 if !c.client.IsRunning() {
292− if cfg != nil && cfg.Options.DebugLSP {
296+ if c.debug {
293297 slog.Debug("LSP server not ready yet", "server", c.name)
294298 }
295299 continue
@@ -297,7 +301,7 @@ func (c *Client) WaitForServerReady(ctx context.Context) error {
297301
298302 // Server is ready
299303 c.SetServerState(StateReady)
300− if cfg != nil && cfg.Options.DebugLSP {
304+ if c.debug {
301305 slog.Debug("LSP server is ready")
302306 }
303307 return nil
@@ -416,10 +420,8 @@ func (c *Client) IsFileOpen(filepath string) bool {
416420
417421// CloseAllFiles closes all currently open files.
418422func (c *Client) CloseAllFiles(ctx context.Context) {
419− cfg := config.Get()
420− debugLSP := cfg != nil && cfg.Options.DebugLSP
421423 for uri := range c.openFiles.Seq2() {
422− if debugLSP {
424+ if c.debug {
423425 slog.Debug("Closing file", "file", uri)
424426 }
425427 if err := c.client.NotifyDidCloseTextDocument(ctx, uri); err != nil {
internal/lsp/client_test.go+1−1
@@ -23,7 +23,7 @@ func TestClient(t *testing.T) {
2323 // but we can still test the basic structure
2424 client, err := New(ctx, "test", cfg, config.NewEnvironmentVariableResolver(env.NewFromMap(map[string]string{
2525 "THE_CMD": "echo",
26− })))
26+ })), false)
2727 if err != nil {
2828 // Expected to fail with echo command, skip the rest
2929 t.Skipf("Powernap client creation failed as expected with dummy command: %v", err)
internal/lsp/handlers.go−6
@@ -5,7 +5,6 @@ import (
55 "encoding/json"
66 "log/slog"
77
8− "github.com/charmbracelet/crush/internal/config"
98 "github.com/charmbracelet/crush/internal/lsp/util"
109 "github.com/charmbracelet/x/powernap/pkg/lsp/protocol"
1110)
@@ -80,11 +79,6 @@ func notifyFileWatchRegistration(id string, watchers []protocol.FileSystemWatche
8079
8180// HandleServerMessage handles server messages
8281func HandleServerMessage(_ context.Context, method string, params json.RawMessage) {
83− cfg := config.Get()
84− if !cfg.Options.DebugLSP {
85− return
86− }
87−
8882 var msg protocol.ShowMessageParams
8983 if err := json.Unmarshal(params, &msg); err != nil {
9084 slog.Debug("Server message", "type", msg.Type, "message", msg.Message)
internal/ui/chat/messages.go+5−3
@@ -186,16 +186,18 @@ type AssistantInfoItem struct {
186186 id string
187187 message *message.Message
188188 sty *styles.Styles
189+ cfg *config.Config
189190 lastUserMessageTime time.Time
190191}
191192
192193// NewAssistantInfoItem creates a new AssistantInfoItem.
193−func NewAssistantInfoItem(sty *styles.Styles, message *message.Message, lastUserMessageTime time.Time) MessageItem {
194+func NewAssistantInfoItem(sty *styles.Styles, message *message.Message, cfg *config.Config, lastUserMessageTime time.Time) MessageItem {
194195 return &AssistantInfoItem{
195196 cachedMessageItem: &cachedMessageItem{},
196197 id: AssistantInfoID(message.ID),
197198 message: message,
198199 sty: sty,
200+ cfg: cfg,
199201 lastUserMessageTime: lastUserMessageTime,
200202 }
201203}
@@ -231,13 +233,13 @@ func (a *AssistantInfoItem) renderContent(width int) string {
231233 duration := finishTime.Sub(a.lastUserMessageTime)
232234 infoMsg := a.sty.Chat.Message.AssistantInfoDuration.Render(duration.String())
233235 icon := a.sty.Chat.Message.AssistantInfoIcon.Render(styles.ModelIcon)
234− model := config.Get().GetModel(a.message.Provider, a.message.Model)
236+ model := a.cfg.GetModel(a.message.Provider, a.message.Model)
235237 if model == nil {
236238 model = &catwalk.Model{Name: "Unknown Model"}
237239 }
238240 modelFormatted := a.sty.Chat.Message.AssistantInfoModel.Render(model.Name)
239241 providerName := a.message.Provider
240− if providerConfig, ok := config.Get().Providers.Get(a.message.Provider); ok {
242+ if providerConfig, ok := a.cfg.Providers.Get(a.message.Provider); ok {
241243 providerName = providerConfig.Name
242244 }
243245 provider := a.sty.Chat.Message.AssistantInfoProvider.Render(fmt.Sprintf("via %s", providerName))
internal/ui/dialog/api_key_input.go+1−1
@@ -296,7 +296,7 @@ func (m *APIKeyInput) verifyAPIKey() tea.Msg {
296296 Type: m.provider.Type,
297297 BaseURL: m.provider.APIEndpoint,
298298 }
299− err := providerConfig.TestConnection(config.Get().Resolver())
299+ err := providerConfig.TestConnection(m.com.Config().Resolver())
300300
301301 // intentionally wait for at least 750ms to make sure the user sees the spinner
302302 elapsed := time.Since(start)
internal/ui/model/header.go+2−2
@@ -117,8 +117,8 @@ func renderHeaderDetails(
117117 parts = append(parts, t.LSP.ErrorDiagnostic.Render(fmt.Sprintf("%s%d", styles.LSPErrorIcon, errorCount)))
118118 }
119119
120− agentCfg := config.Get().Agents[config.AgentCoder]
121− model := config.Get().GetModelByType(agentCfg.Model)
120+ agentCfg := com.Config().Agents[config.AgentCoder]
121+ model := com.Config().GetModelByType(agentCfg.Model)
122122 percentage := (float64(session.CompletionTokens+session.PromptTokens) / float64(model.ContextWindow)) * 100
123123 formattedPercentage := t.Header.Percentage.Render(fmt.Sprintf("%d%%", int(percentage)))
124124 parts = append(parts, formattedPercentage)
internal/ui/model/onboarding.go+1−1
@@ -19,7 +19,7 @@ import (
1919// markProjectInitialized marks the current project as initialized in the config.
2020func (m *UI) markProjectInitialized() tea.Msg {
2121 // TODO: handle error so we show it in the tui footer
22− err := config.MarkProjectInitialized()
22+ err := config.MarkProjectInitialized(m.com.Config())
2323 if err != nil {
2424 slog.Error(err.Error())
2525 }
internal/ui/model/ui.go+6−6
@@ -298,7 +298,7 @@ func New(com *common.Common) *UI {
298298 desiredFocus := uiFocusEditor
299299 if !com.Config().IsConfigured() {
300300 desiredState = uiOnboarding
301− } else if n, _ := config.ProjectNeedsInitialization(); n {
301+ } else if n, _ := config.ProjectNeedsInitialization(com.Config()); n {
302302 desiredState = uiInitialize
303303 }
304304
@@ -776,7 +776,7 @@ func (m *UI) setSessionMessages(msgs []message.Message) tea.Cmd {
776776 case message.Assistant:
777777 items = append(items, chat.ExtractMessageItems(m.com.Styles, msg, toolResultMap)...)
778778 if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
779− infoItem := chat.NewAssistantInfoItem(m.com.Styles, msg, time.Unix(m.lastUserMessageTime, 0))
779+ infoItem := chat.NewAssistantInfoItem(m.com.Styles, msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0))
780780 items = append(items, infoItem)
781781 }
782782 default:
@@ -906,7 +906,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
906906 }
907907 }
908908 if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
909− infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, time.Unix(m.lastUserMessageTime, 0))
909+ infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0))
910910 m.chat.AppendMessages(infoItem)
911911 if atBottom {
912912 if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
@@ -977,7 +977,7 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
977977
978978 if shouldRenderAssistant && msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
979979 if infoItem := m.chat.MessageItem(chat.AssistantInfoID(msg.ID)); infoItem == nil {
980− newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, time.Unix(m.lastUserMessageTime, 0))
980+ newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0))
981981 m.chat.AppendMessages(newInfoItem)
982982 }
983983 }
@@ -1249,7 +1249,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
12491249
12501250 // Attempt to import GitHub Copilot tokens from VSCode if available.
12511251 if isCopilot && !isConfigured() {
1252− config.Get().ImportCopilot()
1252+ m.com.Config().ImportCopilot()
12531253 }
12541254
12551255 if !isConfigured() {
@@ -3063,7 +3063,7 @@ func (m *UI) drawSessionDetails(scr uv.Screen, area uv.Rectangle) {
30633063
30643064func (m *UI) runMCPPrompt(clientID, promptID string, arguments map[string]string) tea.Cmd {
30653065 load := func() tea.Msg {
3066− prompt, err := commands.GetMCPPrompt(clientID, promptID, arguments)
3066+ prompt, err := commands.GetMCPPrompt(m.com.Config(), clientID, promptID, arguments)
30673067 if err != nil {
30683068 // TODO: make this better
30693069 return util.ReportError(err)()