refactor: rename ConfigService() to Config() throughout

Kujtim Hoxha created

Rename App.ConfigService() to App.Config(), Common.ConfigService()
to Common.Config(), and app.configService field to app.cfg.

🐾 Generated with Crush

Assisted-by: Claude Opus 4.6 via Crush <crush@charm.land>

Change summary

internal/app/app.go                 | 26 ++++++++--------
internal/app/lsp.go                 | 12 +++---
internal/cmd/login.go               |  4 +-
internal/cmd/root.go                |  2 
internal/cmd/run.go                 |  2 
internal/ui/common/common.go        |  6 +-
internal/ui/dialog/api_key_input.go |  4 +-
internal/ui/dialog/commands.go      |  4 +-
internal/ui/dialog/filepicker.go    |  2 
internal/ui/dialog/models.go        |  6 +-
internal/ui/dialog/oauth.go         |  2 
internal/ui/dialog/reasoning.go     |  2 
internal/ui/model/header.go         |  6 +-
internal/ui/model/landing.go        |  2 
internal/ui/model/mcp.go            |  2 
internal/ui/model/onboarding.go     |  8 ++--
internal/ui/model/sidebar.go        |  6 +-
internal/ui/model/ui.go             | 50 +++++++++++++++---------------
18 files changed, 73 insertions(+), 73 deletions(-)

Detailed changes

internal/app/app.go 🔗

@@ -61,7 +61,7 @@ type App struct {
 
 	LSPClients *csync.Map[string, *lsp.Client]
 
-	configService *config.Service
+	cfg *config.Service
 
 	serviceEventsWG *sync.WaitGroup
 	eventsCtx       context.Context
@@ -96,7 +96,7 @@ func New(ctx context.Context, conn *sql.DB, cfgSvc *config.Service) (*App, error
 
 		globalCtx: ctx,
 
-		configService: cfgSvc,
+		cfg: cfgSvc,
 
 		events:          make(chan tea.Msg, 100),
 		serviceEventsWG: &sync.WaitGroup{},
@@ -127,9 +127,9 @@ func New(ctx context.Context, conn *sql.DB, cfgSvc *config.Service) (*App, error
 	return app, nil
 }
 
-// ConfigService returns the config service.
-func (app *App) ConfigService() *config.Service {
-	return app.configService
+// Config returns the config service.
+func (app *App) Config() *config.Service {
+	return app.cfg
 }
 
 // RunNonInteractive runs the application in non-interactive mode with the
@@ -159,7 +159,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt,
 	}
 	stderrTTY = term.IsTerminal(os.Stderr.Fd())
 	stdinTTY = term.IsTerminal(os.Stdin.Fd())
-	progress = app.configService.Progress() == nil || *app.configService.Progress()
+	progress = app.cfg.Progress() == nil || *app.cfg.Progress()
 
 	if !hideSpinner && stderrTTY {
 		t := styles.DefaultStyles()
@@ -322,7 +322,7 @@ func (app *App) UpdateAgentModel(ctx context.Context) error {
 // If largeModel is provided but smallModel is not, the small model defaults to
 // the provider's default small model.
 func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel, smallModel string) error {
-	providers := maps.Clone(app.configService.AllProviders())
+	providers := maps.Clone(app.cfg.AllProviders())
 
 	largeMatches, smallMatches, err := findModels(providers, largeModel, smallModel)
 	if err != nil {
@@ -339,7 +339,7 @@ func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel,
 		}
 		largeProviderID = found.provider
 		slog.Info("Overriding large model for non-interactive run", "provider", found.provider, "model", found.modelID)
-		app.configService.OverrideModel(config.SelectedModelTypeLarge, config.SelectedModel{
+		app.cfg.OverrideModel(config.SelectedModelTypeLarge, config.SelectedModel{
 			Provider: found.provider,
 			Model:    found.modelID,
 		})
@@ -353,7 +353,7 @@ func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel,
 			return err
 		}
 		slog.Info("Overriding small model for non-interactive run", "provider", found.provider, "model", found.modelID)
-		app.configService.OverrideModel(config.SelectedModelTypeSmall, config.SelectedModel{
+		app.cfg.OverrideModel(config.SelectedModelTypeSmall, config.SelectedModel{
 			Provider: found.provider,
 			Model:    found.modelID,
 		})
@@ -361,7 +361,7 @@ func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel,
 	case largeModel != "":
 		// No small model specified, but large model was - use provider's default.
 		smallCfg := app.GetDefaultSmallModel(largeProviderID)
-		app.configService.OverrideModel(config.SelectedModelTypeSmall, smallCfg)
+		app.cfg.OverrideModel(config.SelectedModelTypeSmall, smallCfg)
 	}
 
 	return app.AgentCoordinator.UpdateModels(ctx)
@@ -370,7 +370,7 @@ func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel,
 // GetDefaultSmallModel returns the default small model for the given
 // provider. Falls back to the large model if no default is found.
 func (app *App) GetDefaultSmallModel(providerID string) config.SelectedModel {
-	svc := app.configService
+	svc := app.cfg
 	largeModelCfg, _ := svc.SelectedModel(config.SelectedModelTypeLarge)
 
 	// Find the provider in the known providers list to get its default small model.
@@ -457,14 +457,14 @@ func setupSubscriber[T any](
 }
 
 func (app *App) InitCoderAgent(ctx context.Context) error {
-	coderAgentCfg := app.configService.Agents()[config.AgentCoder]
+	coderAgentCfg := app.cfg.Agents()[config.AgentCoder]
 	if coderAgentCfg.ID == "" {
 		return fmt.Errorf("coder agent configuration is missing")
 	}
 	var err error
 	app.AgentCoordinator, err = agent.NewCoordinator(
 		ctx,
-		app.configService,
+		app.cfg,
 		app.Sessions,
 		app.Messages,
 		app.Permissions,

internal/app/lsp.go 🔗

@@ -22,7 +22,7 @@ func (app *App) initLSPClients(ctx context.Context) {
 	manager.LoadDefaults()
 
 	var userConfiguredLSPs []string
-	for name, clientConfig := range app.configService.LSP() {
+	for name, clientConfig := range app.cfg.LSP() {
 		if clientConfig.Disabled {
 			slog.Info("Skipping disabled LSP client", "name", name)
 			manager.RemoveServer(name)
@@ -53,7 +53,7 @@ func (app *App) initLSPClients(ctx context.Context) {
 	}
 
 	servers := manager.GetServers()
-	filtered := lsp.FilterMatching(app.configService.WorkingDir(), servers)
+	filtered := lsp.FilterMatching(app.cfg.WorkingDir(), servers)
 
 	for _, name := range userConfiguredLSPs {
 		if _, ok := filtered[name]; !ok {
@@ -63,14 +63,14 @@ func (app *App) initLSPClients(ctx context.Context) {
 
 	var wg sync.WaitGroup
 	for name, server := range filtered {
-		if app.configService.AutoLSP() != nil && !*app.configService.AutoLSP() && !slices.Contains(userConfiguredLSPs, name) {
+		if app.cfg.AutoLSP() != nil && !*app.cfg.AutoLSP() && !slices.Contains(userConfiguredLSPs, name) {
 			slog.Debug("Ignoring non user-define LSP client due to AutoLSP being disabled", "name", name)
 			continue
 		}
 		wg.Go(func() {
 			app.createAndStartLSPClient(
 				ctx, name,
-				toOurConfig(server, app.configService.LSP()[name]),
+				toOurConfig(server, app.cfg.LSP()[name]),
 				slices.Contains(userConfiguredLSPs, name),
 			)
 		})
@@ -114,7 +114,7 @@ func (app *App) createAndStartLSPClient(ctx context.Context, name string, config
 	updateLSPState(name, lsp.StateStarting, nil, nil, 0)
 
 	// Create LSP client.
-	lspClient, err := lsp.New(ctx, name, config, app.configService.Resolver(), app.configService.DebugLSP())
+	lspClient, err := lsp.New(ctx, name, config, app.cfg.Resolver(), app.cfg.DebugLSP())
 	if err != nil {
 		if !userConfigured {
 			slog.Warn("Default LSP config skipped due to error", "name", name, "error", err)
@@ -134,7 +134,7 @@ func (app *App) createAndStartLSPClient(ctx context.Context, name string, config
 	defer cancel()
 
 	// Initialize LSP client.
-	_, err = lspClient.Initialize(initCtx, app.configService.WorkingDir())
+	_, err = lspClient.Initialize(initCtx, app.cfg.WorkingDir())
 	if err != nil {
 		slog.Error("LSP client initialization failed", "name", name, "error", err)
 		updateLSPState(name, lsp.StateError, err, lspClient, 0)

internal/cmd/login.go 🔗

@@ -52,9 +52,9 @@ crush login copilot
 		}
 		switch provider {
 		case "hyper":
-			return loginHyper(app.ConfigService())
+			return loginHyper(app.Config())
 		case "copilot", "github", "github-copilot":
-			return loginCopilot(app.ConfigService())
+			return loginCopilot(app.Config())
 		default:
 			return fmt.Errorf("unknown platform: %s", args[0])
 		}

internal/cmd/root.go 🔗

@@ -173,7 +173,7 @@ func setupAppWithProgressBar(cmd *cobra.Command) (*app.App, error) {
 	}
 
 	// Check if progress bar is enabled in config (defaults to true if nil)
-	progressEnabled := app.ConfigService().Progress() == nil || *app.ConfigService().Progress()
+	progressEnabled := app.Config().Progress() == nil || *app.Config().Progress()
 	if progressEnabled && supportsProgressBar() {
 		_, _ = fmt.Fprintf(os.Stderr, ansi.SetIndeterminateProgressBar)
 		defer func() { _, _ = fmt.Fprintf(os.Stderr, ansi.ResetProgressBar) }()

internal/cmd/run.go 🔗

@@ -50,7 +50,7 @@ crush run --verbose "Generate a README for this project"
 		}
 		defer app.Shutdown()
 
-		if !app.ConfigService().IsConfigured() {
+		if !app.Config().IsConfigured() {
 			return fmt.Errorf("no providers configured - please run 'crush' to set up a provider interactively")
 		}
 

internal/ui/common/common.go 🔗

@@ -26,9 +26,9 @@ type Common struct {
 	Styles *styles.Styles
 }
 
-// ConfigService returns the config service associated with this [Common] instance.
-func (c *Common) ConfigService() *config.Service {
-	return c.App.ConfigService()
+// Config returns the config service associated with this [Common] instance.
+func (c *Common) Config() *config.Service {
+	return c.App.Config()
 }
 
 // DefaultCommon returns the default common UI configurations.

internal/ui/dialog/api_key_input.go 🔗

@@ -296,7 +296,7 @@ func (m *APIKeyInput) verifyAPIKey() tea.Msg {
 		Type:    m.provider.Type,
 		BaseURL: m.provider.APIEndpoint,
 	}
-	err := providerConfig.TestConnection(m.com.ConfigService().Resolver())
+	err := providerConfig.TestConnection(m.com.Config().Resolver())
 
 	// intentionally wait for at least 750ms to make sure the user sees the spinner
 	elapsed := time.Since(start)
@@ -312,7 +312,7 @@ func (m *APIKeyInput) verifyAPIKey() tea.Msg {
 }
 
 func (m *APIKeyInput) saveKeyAndContinue() Action {
-	err := m.com.ConfigService().SetProviderAPIKey(string(m.provider.ID), m.input.Value())
+	err := m.com.Config().SetProviderAPIKey(string(m.provider.ID), m.input.Value())
 	if err != nil {
 		return ActionCmd{util.ReportError(fmt.Errorf("failed to save API key: %w", err))}
 	}

internal/ui/dialog/commands.go 🔗

@@ -396,7 +396,7 @@ func (c *Commands) defaultCommands() []*CommandItem {
 	}
 
 	// Add reasoning toggle for models that support it
-	svc := c.com.ConfigService()
+	svc := c.com.Config()
 	if agentCfg, ok := svc.Agent(config.AgentCoder); ok {
 		providerCfg := svc.GetProviderForModel(agentCfg.Model)
 		model := svc.GetModelByType(agentCfg.Model)
@@ -425,7 +425,7 @@ func (c *Commands) defaultCommands() []*CommandItem {
 		commands = append(commands, NewCommandItem(c.com.Styles, "toggle_sidebar", "Toggle Sidebar", "", ActionToggleCompactMode{}))
 	}
 	if c.sessionID != "" {
-		svc := c.com.ConfigService()
+		svc := c.com.Config()
 		agentCfg, _ := svc.Agent(config.AgentCoder)
 		model := svc.GetModelByType(agentCfg.Model)
 		if model != nil && model.SupportsImages {

internal/ui/dialog/filepicker.go 🔗

@@ -123,7 +123,7 @@ func (f *FilePicker) SetImageCapabilities(caps *common.Capabilities) {
 
 // WorkingDir returns the current working directory of the [FilePicker].
 func (f *FilePicker) WorkingDir() string {
-	wd := f.com.ConfigService().WorkingDir()
+	wd := f.com.Config().WorkingDir()
 	if len(wd) > 0 {
 		return wd
 	}

internal/ui/dialog/models.go 🔗

@@ -138,7 +138,7 @@ func NewModels(com *common.Common, isOnboarding bool) (*Models, error) {
 	)
 	m.keyMap.Close = CloseKey
 
-	providers, err := getFilteredProviders(com.ConfigService())
+	providers, err := getFilteredProviders(com.Config())
 	if err != nil {
 		return nil, fmt.Errorf("failed to get providers: %w", err)
 	}
@@ -335,7 +335,7 @@ func (m *Models) FullHelp() [][]key.Binding {
 // setProviderItems sets the provider items in the list.
 func (m *Models) setProviderItems() error {
 	t := m.com.Styles
-	svc := m.com.ConfigService()
+	svc := m.com.Config()
 
 	var selectedItemID string
 	selectedType := m.modelType.Config()
@@ -482,7 +482,7 @@ func (m *Models) setProviderItems() error {
 
 		if len(validRecentItems) != len(recentItems) {
 			// FIXME: Does this need to be here? Is it mutating the config during a read?
-			if err := m.com.ConfigService().SetConfigField(fmt.Sprintf("recent_models.%s", selectedType), validRecentItems); err != nil {
+			if err := m.com.Config().SetConfigField(fmt.Sprintf("recent_models.%s", selectedType), validRecentItems); err != nil {
 				return fmt.Errorf("failed to update recent models: %w", err)
 			}
 		}

internal/ui/dialog/oauth.go 🔗

@@ -373,7 +373,7 @@ func (d *OAuth) copyCodeAndOpenURL() tea.Cmd {
 }
 
 func (m *OAuth) saveKeyAndContinue() Action {
-	err := m.com.ConfigService().SetProviderAPIKey(string(m.provider.ID), m.token)
+	err := m.com.Config().SetProviderAPIKey(string(m.provider.ID), m.token)
 	if err != nil {
 		return ActionCmd{util.ReportError(fmt.Errorf("failed to save API key: %w", err))}
 	}

internal/ui/dialog/reasoning.go 🔗

@@ -220,7 +220,7 @@ func (r *Reasoning) FullHelp() [][]key.Binding {
 }
 
 func (r *Reasoning) setReasoningItems() error {
-	svc := r.com.ConfigService()
+	svc := r.com.Config()
 	agentCfg, ok := svc.Agent(config.AgentCoder)
 	if !ok {
 		return errors.New("agent configuration not found")

internal/ui/model/header.go 🔗

@@ -117,8 +117,8 @@ func renderHeaderDetails(
 		parts = append(parts, t.LSP.ErrorDiagnostic.Render(fmt.Sprintf("%s%d", styles.LSPErrorIcon, errorCount)))
 	}
 
-	agentCfg := com.ConfigService().Agents()[config.AgentCoder]
-	model := com.ConfigService().GetModelByType(agentCfg.Model)
+	agentCfg := com.Config().Agents()[config.AgentCoder]
+	model := com.Config().GetModelByType(agentCfg.Model)
 	percentage := (float64(session.CompletionTokens+session.PromptTokens) / float64(model.ContextWindow)) * 100
 	formattedPercentage := t.Header.Percentage.Render(fmt.Sprintf("%d%%", int(percentage)))
 	parts = append(parts, formattedPercentage)
@@ -135,7 +135,7 @@ func renderHeaderDetails(
 	metadata = dot + metadata
 
 	const dirTrimLimit = 4
-	cwd := fsext.DirTrim(fsext.PrettyPath(com.ConfigService().WorkingDir()), dirTrimLimit)
+	cwd := fsext.DirTrim(fsext.PrettyPath(com.Config().WorkingDir()), dirTrimLimit)
 	cwd = ansi.Truncate(cwd, max(0, availWidth-lipgloss.Width(metadata)), "…")
 	cwd = t.Header.WorkingDir.Render(cwd)
 

internal/ui/model/landing.go 🔗

@@ -22,7 +22,7 @@ func (m *UI) selectedLargeModel() *agent.Model {
 func (m *UI) landingView() string {
 	t := m.com.Styles
 	width := m.layout.main.Dx()
-	cwd := common.PrettyPath(t, m.com.ConfigService().WorkingDir(), width)
+	cwd := common.PrettyPath(t, m.com.Config().WorkingDir(), width)
 
 	parts := []string{
 		cwd,

internal/ui/model/mcp.go 🔗

@@ -16,7 +16,7 @@ func (m *UI) mcpInfo(width, maxItems int, isSection bool) string {
 	var mcps []mcp.ClientInfo
 	t := m.com.Styles
 
-	for _, mcp := range m.com.ConfigService().MCP().Sorted() {
+	for _, mcp := range m.com.Config().MCP().Sorted() {
 		if state, ok := m.mcpStates[mcp.Name]; ok {
 			mcps = append(mcps, state)
 		}

internal/ui/model/onboarding.go 🔗

@@ -19,7 +19,7 @@ import (
 // markProjectInitialized marks the current project as initialized in the config.
 func (m *UI) markProjectInitialized() tea.Msg {
 	// TODO: handle error so we show it in the tui footer
-	err := config.MarkProjectInitialized(m.com.ConfigService())
+	err := config.MarkProjectInitialized(m.com.Config())
 	if err != nil {
 		slog.Error(err.Error())
 	}
@@ -52,7 +52,7 @@ func (m *UI) initializeProject() tea.Cmd {
 	if cmd := m.newSession(); cmd != nil {
 		cmds = append(cmds, cmd)
 	}
-	svc := m.com.ConfigService()
+	svc := m.com.Config()
 
 	initialize := func() tea.Msg {
 		initPrompt, err := agent.InitializePrompt(svc)
@@ -77,9 +77,9 @@ func (m *UI) skipInitializeProject() tea.Cmd {
 
 // initializeView renders the project initialization prompt with Yes/No buttons.
 func (m *UI) initializeView() string {
-	cfg := m.com.ConfigService()
+	cfg := m.com.Config()
 	s := m.com.Styles.Initialize
-	cwd := home.Short(m.com.ConfigService().WorkingDir())
+	cwd := home.Short(m.com.Config().WorkingDir())
 	initFile := cfg.InitializeAs()
 
 	header := s.Header.Render("Would you like to initialize this project?")

internal/ui/model/sidebar.go 🔗

@@ -21,7 +21,7 @@ func (m *UI) modelInfo(width int) string {
 
 	if model != nil {
 		// Get provider name first
-		providerConfig, ok := m.com.ConfigService().Provider(model.ModelCfg.Provider)
+		providerConfig, ok := m.com.Config().Provider(model.ModelCfg.Provider)
 		if ok {
 			providerName = providerConfig.Name
 
@@ -114,7 +114,7 @@ func (m *UI) drawSidebar(scr uv.Screen, area uv.Rectangle) {
 	height := area.Dy()
 
 	title := t.Muted.Width(width).MaxHeight(2).Render(m.session.Title)
-	cwd := common.PrettyPath(t, m.com.ConfigService().WorkingDir(), width)
+	cwd := common.PrettyPath(t, m.com.Config().WorkingDir(), width)
 	sidebarLogo := m.sidebarLogo
 	if height < logoHeightBreakpoint {
 		sidebarLogo = logo.SmallRender(m.com.Styles, width)
@@ -140,7 +140,7 @@ func (m *UI) drawSidebar(scr uv.Screen, area uv.Rectangle) {
 
 	lspSection := m.lspInfo(width, maxLSPs, true)
 	mcpSection := m.mcpInfo(width, maxMCPs, true)
-	filesSection := m.filesInfo(m.com.ConfigService().WorkingDir(), width, maxFiles, true)
+	filesSection := m.filesInfo(m.com.Config().WorkingDir(), width, maxFiles, true)
 
 	uv.NewStyledString(
 		lipgloss.NewStyle().

internal/ui/model/ui.go 🔗

@@ -289,23 +289,23 @@ func New(com *common.Common) *UI {
 	ui.status = status
 
 	// Initialize compact mode from config
-	ui.forceCompactMode = com.ConfigService().Options().TUI.CompactMode
+	ui.forceCompactMode = com.Config().Options().TUI.CompactMode
 
 	// set onboarding state defaults
 	ui.onboarding.yesInitializeSelected = true
 
 	desiredState := uiLanding
 	desiredFocus := uiFocusEditor
-	if !com.ConfigService().IsConfigured() {
+	if !com.Config().IsConfigured() {
 		desiredState = uiOnboarding
-	} else if n, _ := config.ProjectNeedsInitialization(com.ConfigService()); n {
+	} else if n, _ := config.ProjectNeedsInitialization(com.Config()); n {
 		desiredState = uiInitialize
 	}
 
 	// set initial state
 	ui.setState(desiredState, desiredFocus)
 
-	opts := com.ConfigService().Options()
+	opts := com.Config().Options()
 
 	// disable indeterminate progress bar
 	ui.progressBarEnabled = opts.Progress == nil || *opts.Progress
@@ -345,7 +345,7 @@ func (m *UI) setState(state uiState, focus uiFocusState) {
 // loadCustomCommands loads the custom commands asynchronously.
 func (m *UI) loadCustomCommands() tea.Cmd {
 	return func() tea.Msg {
-		customCommands, err := commands.LoadCustomCommands(m.com.ConfigService())
+		customCommands, err := commands.LoadCustomCommands(m.com.Config())
 		if err != nil {
 			slog.Error("Failed to load custom commands", "error", err)
 		}
@@ -776,7 +776,7 @@ func (m *UI) setSessionMessages(msgs []message.Message) tea.Cmd {
 		case message.Assistant:
 			items = append(items, chat.ExtractMessageItems(m.com.Styles, msg, toolResultMap)...)
 			if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
-				infoItem := chat.NewAssistantInfoItem(m.com.Styles, msg, m.com.ConfigService(), time.Unix(m.lastUserMessageTime, 0))
+				infoItem := chat.NewAssistantInfoItem(m.com.Styles, msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0))
 				items = append(items, infoItem)
 			}
 		default:
@@ -906,7 +906,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
 			}
 		}
 		if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
-			infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.ConfigService(), time.Unix(m.lastUserMessageTime, 0))
+			infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0))
 			m.chat.AppendMessages(infoItem)
 			if atBottom {
 				if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
@@ -977,7 +977,7 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
 
 	if shouldRenderAssistant && msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
 		if infoItem := m.chat.MessageItem(chat.AssistantInfoID(msg.ID)); infoItem == nil {
-			newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.ConfigService(), time.Unix(m.lastUserMessageTime, 0))
+			newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0))
 			m.chat.AppendMessages(newInfoItem)
 		}
 	}
@@ -1196,19 +1196,19 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 		m.dialog.CloseDialog(dialog.CommandsID)
 	case dialog.ActionToggleThinking:
 		cmds = append(cmds, func() tea.Msg {
-			cfg := m.com.ConfigService()
+			cfg := m.com.Config()
 			if cfg == nil {
 				return util.ReportError(errors.New("configuration not found"))()
 			}
 
-			agentCfg, ok := m.com.ConfigService().Agent(config.AgentCoder)
+			agentCfg, ok := m.com.Config().Agent(config.AgentCoder)
 			if !ok {
 				return util.ReportError(errors.New("agent configuration not found"))()
 			}
 
 			currentModel, _ := cfg.SelectedModel(agentCfg.Model)
 			currentModel.Think = !currentModel.Think
-			if err := m.com.ConfigService().UpdatePreferredModel(agentCfg.Model, currentModel); err != nil {
+			if err := m.com.Config().UpdatePreferredModel(agentCfg.Model, currentModel); err != nil {
 				return util.ReportError(err)()
 			}
 			m.com.App.UpdateAgentModel(context.TODO())
@@ -1235,7 +1235,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 			break
 		}
 
-		cfg := m.com.ConfigService()
+		cfg := m.com.Config()
 		if cfg == nil {
 			cmds = append(cmds, util.ReportError(errors.New("configuration not found")))
 			break
@@ -1249,7 +1249,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 
 		// Attempt to import GitHub Copilot tokens from VSCode if available.
 		if isCopilot && !isConfigured() {
-			m.com.ConfigService().ImportCopilot()
+			m.com.Config().ImportCopilot()
 		}
 
 		if !isConfigured() {
@@ -1260,12 +1260,12 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 			break
 		}
 
-		if err := m.com.ConfigService().UpdatePreferredModel(msg.ModelType, msg.Model); err != nil {
+		if err := m.com.Config().UpdatePreferredModel(msg.ModelType, msg.Model); err != nil {
 			cmds = append(cmds, util.ReportError(err))
 		} else if _, ok := cfg.SelectedModel(config.SelectedModelTypeSmall); !ok {
 			// Ensure small model is set is unset.
 			smallModel := m.com.App.GetDefaultSmallModel(providerID)
-			if err := m.com.ConfigService().UpdatePreferredModel(config.SelectedModelTypeSmall, smallModel); err != nil {
+			if err := m.com.Config().UpdatePreferredModel(config.SelectedModelTypeSmall, smallModel); err != nil {
 				cmds = append(cmds, util.ReportError(err))
 			}
 		}
@@ -1286,7 +1286,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 
 		if isOnboarding {
 			m.setState(uiLanding, uiFocusEditor)
-			m.com.ConfigService().SetupAgents()
+			m.com.Config().SetupAgents()
 			if err := m.com.App.InitCoderAgent(context.TODO()); err != nil {
 				cmds = append(cmds, util.ReportError(err))
 			}
@@ -1297,13 +1297,13 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 			break
 		}
 
-		cfg := m.com.ConfigService()
+		cfg := m.com.Config()
 		if cfg == nil {
 			cmds = append(cmds, util.ReportError(errors.New("configuration not found")))
 			break
 		}
 
-		agentCfg, ok := m.com.ConfigService().Agent(config.AgentCoder)
+		agentCfg, ok := m.com.Config().Agent(config.AgentCoder)
 		if !ok {
 			cmds = append(cmds, util.ReportError(errors.New("agent configuration not found")))
 			break
@@ -1311,7 +1311,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
 
 		currentModel, _ := cfg.SelectedModel(agentCfg.Model)
 		currentModel.ReasoningEffort = msg.Effort
-		if err := m.com.ConfigService().UpdatePreferredModel(agentCfg.Model, currentModel); err != nil {
+		if err := m.com.Config().UpdatePreferredModel(agentCfg.Model, currentModel); err != nil {
 			cmds = append(cmds, util.ReportError(err))
 			break
 		}
@@ -1635,7 +1635,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
 						m.completionsQuery = ""
 						m.completionsStartIndex = curIdx
 						m.completionsPositionStart = m.completionsPosition()
-						depth, limit := m.com.ConfigService().Options().TUI.Completions.Limits()
+						depth, limit := m.com.Config().Options().TUI.Completions.Limits()
 						cmds = append(cmds, m.completions.OpenWithFiles(depth, limit))
 					}
 				}
@@ -1920,7 +1920,7 @@ func (m *UI) View() tea.View {
 		v.BackgroundColor = m.com.Styles.Background
 	}
 	v.MouseMode = tea.MouseModeCellMotion
-	v.WindowTitle = "crush " + home.Short(m.com.ConfigService().WorkingDir())
+	v.WindowTitle = "crush " + home.Short(m.com.Config().WorkingDir())
 
 	canvas := uv.NewScreenBuffer(m.width, m.height)
 	v.Cursor = m.Draw(canvas, canvas.Bounds())
@@ -2157,7 +2157,7 @@ func (m *UI) FullHelp() [][]key.Binding {
 func (m *UI) toggleCompactMode() tea.Cmd {
 	m.forceCompactMode = !m.forceCompactMode
 
-	err := m.com.ConfigService().SetCompactMode(m.forceCompactMode)
+	err := m.com.Config().SetCompactMode(m.forceCompactMode)
 	if err != nil {
 		return util.ReportError(err)
 	}
@@ -2848,7 +2848,7 @@ func (m *UI) openPermissionsDialog(perm permission.PermissionRequest) tea.Cmd {
 
 	// Get diff mode from config.
 	var opts []dialog.PermissionsOption
-	if diffMode := m.com.ConfigService().Options().TUI.DiffMode; diffMode != "" {
+	if diffMode := m.com.Config().Options().TUI.DiffMode; diffMode != "" {
 		opts = append(opts, dialog.WithDiffMode(diffMode == "split"))
 	}
 
@@ -3045,7 +3045,7 @@ func (m *UI) drawSessionDetails(scr uv.Screen, area uv.Rectangle) {
 
 	lspSection := m.lspInfo(sectionWidth, maxItemsPerSection, false)
 	mcpSection := m.mcpInfo(sectionWidth, maxItemsPerSection, false)
-	filesSection := m.filesInfo(m.com.ConfigService().WorkingDir(), sectionWidth, maxItemsPerSection, false)
+	filesSection := m.filesInfo(m.com.Config().WorkingDir(), sectionWidth, maxItemsPerSection, false)
 	sections := lipgloss.JoinHorizontal(lipgloss.Top, filesSection, " ", lspSection, " ", mcpSection)
 	uv.NewStyledString(
 		s.CompactDetails.View.
@@ -3063,7 +3063,7 @@ func (m *UI) drawSessionDetails(scr uv.Screen, area uv.Rectangle) {
 
 func (m *UI) runMCPPrompt(clientID, promptID string, arguments map[string]string) tea.Cmd {
 	load := func() tea.Msg {
-		prompt, err := commands.GetMCPPrompt(m.com.ConfigService(), clientID, promptID, arguments)
+		prompt, err := commands.GetMCPPrompt(m.com.Config(), clientID, promptID, arguments)
 		if err != nil {
 			// TODO: make this better
 			return util.ReportError(err)()