Skip to main content

vtcode_config/loader/
config.rs

1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3use std::fs;
4use std::path::Path;
5
6use crate::acp::AgentClientProtocolConfig;
7use crate::codex::{FileOpener, HistoryConfig, TuiConfig};
8use crate::context::ContextFeaturesConfig;
9use crate::core::{
10    AgentConfig, AnthropicConfig, AuthConfig, AutomationConfig, CommandsConfig,
11    DotfileProtectionConfig, ModelConfig, OpenAIConfig, PermissionsConfig, PromptCachingConfig,
12    SandboxConfig, SecurityConfig, SkillsConfig, ToolsConfig,
13};
14use crate::debug::DebugConfig;
15use crate::defaults::{self, ConfigDefaultsProvider};
16use crate::hooks::HooksConfig;
17use crate::ide_context::IdeContextConfig;
18use crate::mcp::McpClientConfig;
19use crate::optimization::OptimizationConfig;
20use crate::output_styles::OutputStyleConfig;
21use crate::root::{ChatConfig, PtyConfig, UiConfig};
22use crate::telemetry::TelemetryConfig;
23use crate::timeouts::TimeoutsConfig;
24
25use crate::loader::syntax_highlighting::SyntaxHighlightingConfig;
26
27/// Provider-specific configuration
28#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
29#[derive(Debug, Clone, Deserialize, Serialize, Default)]
30pub struct ProviderConfig {
31    /// OpenAI provider configuration
32    #[serde(default)]
33    pub openai: OpenAIConfig,
34
35    /// Anthropic provider configuration
36    #[serde(default)]
37    pub anthropic: AnthropicConfig,
38}
39
40/// Main configuration structure for VT Code
41#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
42#[derive(Debug, Clone, Deserialize, Serialize, Default)]
43pub struct VTCodeConfig {
44    /// Codex-compatible clickable citation URI scheme.
45    #[serde(default)]
46    pub file_opener: FileOpener,
47
48    /// Codex-compatible project doc byte limit override.
49    #[serde(default)]
50    pub project_doc_max_bytes: Option<usize>,
51
52    /// Codex-compatible fallback filenames for project instructions discovery.
53    #[serde(default)]
54    pub project_doc_fallback_filenames: Vec<String>,
55
56    /// External notification command invoked for supported events.
57    #[serde(default)]
58    pub notify: Vec<String>,
59
60    /// Codex-compatible local history persistence controls.
61    #[serde(default)]
62    pub history: HistoryConfig,
63
64    /// Codex-compatible TUI settings.
65    #[serde(default)]
66    pub tui: TuiConfig,
67
68    /// Agent-wide settings
69    #[serde(default)]
70    pub agent: AgentConfig,
71
72    /// Authentication configuration for OAuth flows
73    #[serde(default)]
74    pub auth: AuthConfig,
75
76    /// Tool execution policies
77    #[serde(default)]
78    pub tools: ToolsConfig,
79
80    /// Unix command permissions
81    #[serde(default)]
82    pub commands: CommandsConfig,
83
84    /// Permission system settings (resolution, audit logging, caching)
85    #[serde(default)]
86    pub permissions: PermissionsConfig,
87
88    /// Security settings
89    #[serde(default)]
90    pub security: SecurityConfig,
91
92    /// Sandbox settings for command execution isolation
93    #[serde(default)]
94    pub sandbox: SandboxConfig,
95
96    /// UI settings
97    #[serde(default)]
98    pub ui: UiConfig,
99
100    /// Chat settings
101    #[serde(default)]
102    pub chat: ChatConfig,
103
104    /// PTY settings
105    #[serde(default)]
106    pub pty: PtyConfig,
107
108    /// Debug and tracing settings
109    #[serde(default)]
110    pub debug: DebugConfig,
111
112    /// Context features (e.g., Decision Ledger)
113    #[serde(default)]
114    pub context: ContextFeaturesConfig,
115
116    /// Telemetry configuration (logging, trajectory)
117    #[serde(default)]
118    pub telemetry: TelemetryConfig,
119
120    /// Performance optimization settings
121    #[serde(default)]
122    pub optimization: OptimizationConfig,
123
124    /// Syntax highlighting configuration
125    #[serde(default)]
126    pub syntax_highlighting: SyntaxHighlightingConfig,
127
128    /// Timeout ceilings and UI warning thresholds
129    #[serde(default)]
130    pub timeouts: TimeoutsConfig,
131
132    /// Automation configuration
133    #[serde(default)]
134    pub automation: AutomationConfig,
135
136    /// Prompt cache configuration (local + provider integration)
137    #[serde(default)]
138    pub prompt_cache: PromptCachingConfig,
139
140    /// Model Context Protocol configuration
141    #[serde(default)]
142    pub mcp: McpClientConfig,
143
144    /// Agent Client Protocol configuration
145    #[serde(default)]
146    pub acp: AgentClientProtocolConfig,
147
148    /// IDE context configuration
149    #[serde(default)]
150    pub ide_context: IdeContextConfig,
151
152    /// Lifecycle hooks configuration
153    #[serde(default)]
154    pub hooks: HooksConfig,
155
156    /// Model-specific behavior configuration
157    #[serde(default)]
158    pub model: ModelConfig,
159
160    /// Provider-specific configuration
161    #[serde(default)]
162    pub provider: ProviderConfig,
163
164    /// Skills system configuration (Agent Skills spec)
165    #[serde(default)]
166    pub skills: SkillsConfig,
167
168    /// Output style configuration
169    #[serde(default)]
170    pub output_style: OutputStyleConfig,
171
172    /// Dotfile protection configuration
173    #[serde(default)]
174    pub dotfile_protection: DotfileProtectionConfig,
175}
176
177impl VTCodeConfig {
178    pub fn apply_compat_defaults(&mut self) {
179        if let Some(max_bytes) = self.project_doc_max_bytes {
180            self.agent.project_doc_max_bytes = max_bytes;
181        }
182
183        if !self.project_doc_fallback_filenames.is_empty() {
184            self.agent.project_doc_fallback_filenames = self.project_doc_fallback_filenames.clone();
185        }
186    }
187
188    pub fn validate(&self) -> Result<()> {
189        self.syntax_highlighting
190            .validate()
191            .context("Invalid syntax_highlighting configuration")?;
192
193        self.context
194            .validate()
195            .context("Invalid context configuration")?;
196
197        self.hooks
198            .validate()
199            .context("Invalid hooks configuration")?;
200
201        self.timeouts
202            .validate()
203            .context("Invalid timeouts configuration")?;
204
205        self.prompt_cache
206            .validate()
207            .context("Invalid prompt_cache configuration")?;
208
209        self.ui
210            .keyboard_protocol
211            .validate()
212            .context("Invalid keyboard_protocol configuration")?;
213
214        self.pty.validate().context("Invalid pty configuration")?;
215
216        Ok(())
217    }
218
219    #[cfg(feature = "bootstrap")]
220    /// Bootstrap project with config + gitignore
221    pub fn bootstrap_project<P: AsRef<Path>>(workspace: P, force: bool) -> Result<Vec<String>> {
222        Self::bootstrap_project_with_options(workspace, force, false)
223    }
224
225    #[cfg(feature = "bootstrap")]
226    /// Bootstrap project with config + gitignore, with option to create in home directory
227    pub fn bootstrap_project_with_options<P: AsRef<Path>>(
228        workspace: P,
229        force: bool,
230        use_home_dir: bool,
231    ) -> Result<Vec<String>> {
232        let workspace = workspace.as_ref().to_path_buf();
233        defaults::with_config_defaults(|provider| {
234            Self::bootstrap_project_with_provider(&workspace, force, use_home_dir, provider)
235        })
236    }
237
238    #[cfg(feature = "bootstrap")]
239    /// Bootstrap project files using the supplied [`ConfigDefaultsProvider`].
240    pub fn bootstrap_project_with_provider<P: AsRef<Path>>(
241        workspace: P,
242        force: bool,
243        use_home_dir: bool,
244        defaults_provider: &dyn ConfigDefaultsProvider,
245    ) -> Result<Vec<String>> {
246        let workspace = workspace.as_ref();
247        let config_file_name = defaults_provider.config_file_name().to_string();
248        let (config_path, gitignore_path) = crate::loader::bootstrap::determine_bootstrap_targets(
249            workspace,
250            use_home_dir,
251            &config_file_name,
252            defaults_provider,
253        )?;
254
255        crate::loader::bootstrap::ensure_parent_dir(&config_path)?;
256        crate::loader::bootstrap::ensure_parent_dir(&gitignore_path)?;
257
258        let mut created_files = Vec::new();
259
260        if !config_path.exists() || force {
261            let config_content = Self::default_vtcode_toml_template();
262
263            fs::write(&config_path, config_content).with_context(|| {
264                format!("Failed to write config file: {}", config_path.display())
265            })?;
266
267            if let Some(file_name) = config_path.file_name().and_then(|name| name.to_str()) {
268                created_files.push(file_name.to_string());
269            }
270        }
271
272        if !gitignore_path.exists() || force {
273            let gitignore_content = Self::default_vtcode_gitignore();
274            fs::write(&gitignore_path, gitignore_content).with_context(|| {
275                format!(
276                    "Failed to write gitignore file: {}",
277                    gitignore_path.display()
278                )
279            })?;
280
281            if let Some(file_name) = gitignore_path.file_name().and_then(|name| name.to_str()) {
282                created_files.push(file_name.to_string());
283            }
284        }
285
286        Ok(created_files)
287    }
288
289    #[cfg(feature = "bootstrap")]
290    /// Generate the default `vtcode.toml` template used by bootstrap helpers.
291    fn default_vtcode_toml_template() -> String {
292        r#"# VT Code Configuration File (Example)
293# Getting-started reference; see docs/config/CONFIGURATION_PRECEDENCE.md for override order.
294# Copy this file to vtcode.toml and customize as needed.
295
296# Clickable file citation URI scheme ("vscode", "cursor", "windsurf", "vscode-insiders", "none")
297file_opener = "none"
298
299# Additional fallback filenames to use when AGENTS.md is absent
300project_doc_fallback_filenames = []
301
302# Optional external command invoked after each completed agent turn
303notify = []
304
305[history]
306# Persist local session transcripts to disk
307persistence = "file"
308
309# Optional max size budget for each persisted session snapshot
310# max_bytes = 104857600
311
312[tui]
313# Enable all built-in TUI notifications, disable them, or restrict to specific event types.
314# notifications = true
315# notifications = ["agent-turn-complete", "approval-requested"]
316
317# Notification transport: "auto", "osc9", or "bel"
318# notification_method = "auto"
319
320# Set to false to reduce shimmer/animation effects
321# animations = true
322
323# Alternate-screen override: "always" or "never"
324# alternate_screen = "never"
325
326# Show onboarding hints on the welcome screen
327# show_tooltips = true
328
329# Core agent behavior; see docs/config/CONFIGURATION_PRECEDENCE.md.
330[agent]
331# Primary LLM provider to use (e.g., "openai", "gemini", "anthropic", "openrouter")
332provider = "openai"
333
334# Environment variable containing the API key for the provider
335api_key_env = "OPENAI_API_KEY"
336
337# Default model to use when no specific model is specified
338default_model = "gpt-5.4"
339
340# Visual theme for the terminal interface
341theme = "ciapre-dark"
342
343# Enable TODO planning helper mode for structured task management
344todo_planning_mode = true
345
346# UI surface to use ("auto", "alternate", "inline")
347ui_surface = "auto"
348
349# Maximum number of conversation turns before rotating context (affects memory usage)
350# Lower values reduce memory footprint but may lose context; higher values preserve context but use more memory
351max_conversation_turns = 150
352
353# Reasoning effort level ("none", "minimal", "low", "medium", "high", "xhigh") - affects model usage and response speed
354reasoning_effort = "none"
355
356# Temperature for main model responses (0.0-1.0)
357temperature = 0.7
358
359# Enable self-review loop to check and improve responses (increases API calls)
360enable_self_review = false
361
362# Maximum number of review passes when self-review is enabled
363max_review_passes = 1
364
365# Enable prompt refinement loop for improved prompt quality (increases processing time)
366refine_prompts_enabled = false
367
368# Maximum passes for prompt refinement when enabled
369refine_prompts_max_passes = 1
370
371# Optional alternate model for refinement (leave empty to use default)
372refine_prompts_model = ""
373
374# Maximum size of project documentation to include in context (in bytes)
375project_doc_max_bytes = 16384
376
377# Maximum size of instruction files to process (in bytes)
378instruction_max_bytes = 16384
379
380# List of additional instruction files to include in context
381instruction_files = []
382
383# Default editing mode on startup: "edit" or "plan"
384# "edit" - Full tool access for file modifications and command execution (default)
385# "plan" - Read-only mode that produces implementation plans without making changes
386# Toggle during session with Shift+Tab or /plan command
387default_editing_mode = "edit"
388
389# Onboarding configuration - Customize the startup experience
390[agent.onboarding]
391# Enable the onboarding welcome message on startup
392enabled = true
393
394# Custom introduction text shown on startup
395intro_text = "Let's get oriented. I preloaded workspace context so we can move fast."
396
397# Include project overview information in welcome
398include_project_overview = true
399
400# Include language summary information in welcome
401include_language_summary = false
402
403# Include key guideline highlights from AGENTS.md
404include_guideline_highlights = true
405
406# Include usage tips in the welcome message
407include_usage_tips_in_welcome = false
408
409# Include recommended actions in the welcome message
410include_recommended_actions_in_welcome = false
411
412# Maximum number of guideline highlights to show
413guideline_highlight_limit = 3
414
415# List of usage tips shown during onboarding
416usage_tips = [
417    "Describe your current coding goal or ask for a quick status overview.",
418    "Reference AGENTS.md guidelines when proposing changes.",
419    "Prefer asking for targeted file reads or diffs before editing.",
420]
421
422# List of recommended actions shown during onboarding
423recommended_actions = [
424    "Review the highlighted guidelines and share the task you want to tackle.",
425    "Ask for a workspace tour if you need more context.",
426]
427
428# Checkpointing configuration for session persistence
429[agent.checkpointing]
430# Enable automatic session checkpointing
431enabled = true
432
433# Maximum number of checkpoints to keep on disk
434max_snapshots = 50
435
436# Maximum age of checkpoints to keep (in days)
437max_age_days = 30
438
439# Tool security configuration
440[tools]
441# Default policy when no specific policy is defined ("allow", "prompt", "deny")
442# "allow" - Execute without confirmation
443# "prompt" - Ask for confirmation
444# "deny" - Block the tool
445default_policy = "prompt"
446
447# Maximum number of tool loops allowed per turn
448# Set to 0 to disable the limit and let other turn safeguards govern termination.
449max_tool_loops = 0
450
451# Maximum number of repeated identical tool calls (prevents stuck loops)
452max_repeated_tool_calls = 2
453
454# Maximum consecutive blocked tool calls before force-breaking the turn
455# Helps prevent high-CPU churn when calls are repeatedly denied/blocked
456max_consecutive_blocked_tool_calls_per_turn = 8
457
458# Maximum sequential spool-chunk reads per turn before nudging targeted extraction/summarization
459max_sequential_spool_chunk_reads = 6
460
461# Specific tool policies - Override default policy for individual tools
462[tools.policies]
463apply_patch = "prompt"            # Apply code patches (requires confirmation)
464request_user_input = "allow"      # Ask focused user questions when the task requires it
465task_tracker = "prompt"           # Create or update explicit task plans
466unified_exec = "prompt"           # Run commands; pipe-first by default, set tty=true for PTY/interactive sessions
467unified_file = "allow"            # Canonical file read/write/edit/move/copy/delete surface
468unified_search = "allow"          # Canonical search/list/intelligence/error surface
469
470# Command security - Define safe and dangerous command patterns
471[commands]
472# Commands that are always allowed without confirmation
473allow_list = [
474    "ls",           # List directory contents
475    "pwd",          # Print working directory
476    "git status",   # Show git status
477    "git diff",     # Show git differences
478    "cargo check",  # Check Rust code
479    "echo",         # Print text
480]
481
482# Commands that are never allowed
483deny_list = [
484    "rm -rf /",        # Delete root directory (dangerous)
485    "rm -rf ~",        # Delete home directory (dangerous)
486    "shutdown",        # Shut down system (dangerous)
487    "reboot",          # Reboot system (dangerous)
488    "sudo *",          # Any sudo command (dangerous)
489    ":(){ :|:& };:",   # Fork bomb (dangerous)
490]
491
492# Command patterns that are allowed (supports glob patterns)
493allow_glob = [
494    "git *",        # All git commands
495    "cargo *",      # All cargo commands
496    "python -m *",  # Python module commands
497]
498
499# Command patterns that are denied (supports glob patterns)
500deny_glob = [
501    "rm *",         # All rm commands
502    "sudo *",       # All sudo commands
503    "chmod *",      # All chmod commands
504    "chown *",      # All chown commands
505    "kubectl *",    # All kubectl commands (admin access)
506]
507
508# Regular expression patterns for allowed commands (if needed)
509allow_regex = []
510
511# Regular expression patterns for denied commands (if needed)
512deny_regex = []
513
514# Security configuration - Safety settings for automated operations
515[security]
516# Require human confirmation for potentially dangerous actions
517human_in_the_loop = true
518
519# Require explicit write tool usage for claims about file modifications
520require_write_tool_for_claims = true
521
522# Auto-apply patches without prompting (DANGEROUS - disable for safety)
523auto_apply_detected_patches = false
524
525# UI configuration - Terminal and display settings
526[ui]
527# Tool output display mode
528# "compact" - Concise tool output
529# "full" - Detailed tool output
530tool_output_mode = "compact"
531
532# Maximum number of lines to display in tool output (prevents transcript flooding)
533# Lines beyond this limit are truncated to a tail preview
534tool_output_max_lines = 600
535
536# Maximum bytes threshold for spooling tool output to disk
537# Output exceeding this size is written to .vtcode/tool-output/*.log
538tool_output_spool_bytes = 200000
539
540# Optional custom directory for spooled tool output logs
541# If not set, defaults to .vtcode/tool-output/
542# tool_output_spool_dir = "/path/to/custom/spool/dir"
543
544# Allow ANSI escape sequences in tool output (enables colors but may cause layout issues)
545allow_tool_ansi = false
546
547# Number of rows to allocate for inline UI viewport
548inline_viewport_rows = 16
549
550# Show elapsed time divider after each completed turn
551show_turn_timer = false
552
553# Show warning/error/fatal diagnostic lines directly in transcript
554# Effective in debug/development builds only
555show_diagnostics_in_transcript = false
556
557# Show timeline navigation panel
558show_timeline_pane = false
559
560# Runtime notification preferences
561[ui.notifications]
562# Master toggle for terminal/desktop notifications
563enabled = true
564
565# Delivery mode: "terminal", "hybrid", or "desktop"
566delivery_mode = "hybrid"
567
568# Suppress notifications while terminal is focused
569suppress_when_focused = true
570
571# Failure/error notifications
572command_failure = false
573tool_failure = false
574error = true
575
576# Completion notifications
577# Legacy master toggle (fallback for split settings when unset)
578completion = true
579completion_success = false
580completion_failure = true
581
582# Human approval/interaction notifications
583hitl = true
584policy_approval = true
585request = false
586
587# Success notifications for tool call results
588tool_success = false
589
590# Repeated notification suppression
591repeat_window_seconds = 30
592max_identical_in_window = 1
593
594# Status line configuration
595[ui.status_line]
596# Status line mode ("auto", "command", "hidden")
597mode = "auto"
598
599# How often to refresh status line (milliseconds)
600refresh_interval_ms = 2000
601
602# Timeout for command execution in status line (milliseconds)
603command_timeout_ms = 200
604
605# Enable Vim-style prompt editing in interactive mode
606vim_mode = false
607
608# PTY (Pseudo Terminal) configuration - For interactive command execution
609[pty]
610# Enable PTY support for interactive commands
611enabled = true
612
613# Default number of terminal rows for PTY sessions
614default_rows = 24
615
616# Default number of terminal columns for PTY sessions
617default_cols = 80
618
619# Maximum number of concurrent PTY sessions
620max_sessions = 10
621
622# Command timeout in seconds (prevents hanging commands)
623command_timeout_seconds = 300
624
625# Number of recent lines to show in PTY output
626stdout_tail_lines = 20
627
628# Total lines to keep in PTY scrollback buffer
629scrollback_lines = 400
630
631# Optional preferred shell for PTY sessions (falls back to $SHELL when unset)
632# preferred_shell = "/bin/zsh"
633
634# Route shell execution through zsh EXEC_WRAPPER intercept hooks (feature-gated)
635shell_zsh_fork = false
636
637# Absolute path to patched zsh used when shell_zsh_fork is enabled
638# zsh_path = "/usr/local/bin/zsh"
639
640# Context management configuration - Controls conversation memory
641[context]
642# Maximum number of tokens to keep in context (affects model cost and performance)
643# Higher values preserve more context but cost more and may hit token limits
644max_context_tokens = 90000
645
646# Percentage to trim context to when it gets too large
647trim_to_percent = 60
648
649# Number of recent conversation turns to always preserve
650preserve_recent_turns = 6
651
652# Decision ledger configuration - Track important decisions
653[context.ledger]
654# Enable decision tracking and persistence
655enabled = true
656
657# Maximum number of decisions to keep in ledger
658max_entries = 12
659
660# Include ledger summary in model prompts
661include_in_prompt = true
662
663# Preserve ledger during context compression
664preserve_in_compression = true
665
666# AI model routing - Intelligent model selection
667# Telemetry and analytics
668[telemetry]
669# Enable trajectory logging for usage analysis
670trajectory_enabled = true
671
672# Syntax highlighting configuration
673[syntax_highlighting]
674# Enable syntax highlighting for code in tool output
675enabled = true
676
677# Theme for syntax highlighting
678theme = "base16-ocean.dark"
679
680# Cache syntax highlighting themes for performance
681cache_themes = true
682
683# Maximum file size for syntax highlighting (in MB)
684max_file_size_mb = 10
685
686# Programming languages to enable syntax highlighting for
687enabled_languages = [
688    "rust",
689    "python",
690    "javascript",
691    "typescript",
692    "go",
693    "java",
694    "bash",
695    "sh",
696    "shell",
697    "zsh",
698    "markdown",
699    "md",
700]
701
702# Timeout for syntax highlighting operations (milliseconds)
703highlight_timeout_ms = 1000
704
705# Automation features - Full-auto mode settings
706[automation.full_auto]
707# Enable full automation mode (DANGEROUS - requires careful oversight)
708enabled = false
709
710# Maximum number of turns before asking for human input
711max_turns = 30
712
713# Tools allowed in full automation mode
714allowed_tools = [
715    "write_file",
716    "read_file",
717    "list_files",
718    "grep_file",
719]
720
721# Require profile acknowledgment before using full auto
722require_profile_ack = true
723
724# Path to full auto profile configuration
725profile_path = "automation/full_auto_profile.toml"
726
727# Prompt caching - Cache model responses for efficiency
728[prompt_cache]
729# Enable prompt caching (reduces API calls for repeated prompts)
730enabled = true
731
732# Directory for cache storage
733cache_dir = "~/.vtcode/cache/prompts"
734
735# Maximum number of cache entries to keep
736max_entries = 1000
737
738# Maximum age of cache entries (in days)
739max_age_days = 30
740
741# Enable automatic cache cleanup
742enable_auto_cleanup = true
743
744# Minimum quality threshold to keep cache entries
745min_quality_threshold = 0.7
746
747# Keep volatile runtime counters at the end of system prompts to improve provider-side prefix cache reuse
748# (enabled by default; disable only if you need legacy prompt layout)
749cache_friendly_prompt_shaping = true
750
751# Prompt cache configuration for OpenAI
752    [prompt_cache.providers.openai]
753    enabled = true
754    min_prefix_tokens = 1024
755    idle_expiration_seconds = 3600
756    surface_metrics = true
757    # Routing key strategy for OpenAI prompt cache locality.
758    # "session" creates one stable key per VT Code conversation.
759    prompt_cache_key_mode = "session"
760    # Optional: server-side prompt cache retention for OpenAI Responses API
761    # Example: "24h" (leave commented out for default behavior)
762    # prompt_cache_retention = "24h"
763
764# Prompt cache configuration for Anthropic
765[prompt_cache.providers.anthropic]
766enabled = true
767default_ttl_seconds = 300
768extended_ttl_seconds = 3600
769max_breakpoints = 4
770cache_system_messages = true
771cache_user_messages = true
772
773# Prompt cache configuration for Gemini
774[prompt_cache.providers.gemini]
775enabled = true
776mode = "implicit"
777min_prefix_tokens = 1024
778explicit_ttl_seconds = 3600
779
780# Prompt cache configuration for OpenRouter
781[prompt_cache.providers.openrouter]
782enabled = true
783propagate_provider_capabilities = true
784report_savings = true
785
786# Prompt cache configuration for Moonshot
787[prompt_cache.providers.moonshot]
788enabled = true
789
790# Prompt cache configuration for DeepSeek
791[prompt_cache.providers.deepseek]
792enabled = true
793surface_metrics = true
794
795# Prompt cache configuration for Z.AI
796[prompt_cache.providers.zai]
797enabled = false
798
799# Model Context Protocol (MCP) - Connect external tools and services
800[mcp]
801# Enable Model Context Protocol (may impact startup time if services unavailable)
802enabled = true
803max_concurrent_connections = 5
804request_timeout_seconds = 30
805retry_attempts = 3
806
807# MCP UI configuration
808[mcp.ui]
809mode = "compact"
810max_events = 50
811show_provider_names = true
812
813# MCP renderer profiles for different services
814[mcp.ui.renderers]
815sequential-thinking = "sequential-thinking"
816context7 = "context7"
817
818# MCP provider configuration - External services that connect via MCP
819[[mcp.providers]]
820name = "time"
821command = "uvx"
822args = ["mcp-server-time"]
823enabled = true
824max_concurrent_requests = 3
825[mcp.providers.env]
826
827# Agent Client Protocol (ACP) - IDE integration
828[acp]
829enabled = true
830
831[acp.zed]
832enabled = true
833transport = "stdio"
834# workspace_trust controls ACP trust mode: "tools_policy" (prompts) or "full_auto" (no prompts)
835workspace_trust = "full_auto"
836
837[acp.zed.tools]
838read_file = true
839list_files = true
840
841# Cross-IDE editor context bridge
842[ide_context]
843enabled = true
844inject_into_prompt = true
845show_in_tui = true
846include_selection_text = true
847provider_mode = "auto"
848
849[ide_context.providers.vscode_compatible]
850enabled = true
851
852[ide_context.providers.zed]
853enabled = true
854
855[ide_context.providers.generic]
856enabled = true"#.to_string()
857    }
858
859    #[cfg(feature = "bootstrap")]
860    fn default_vtcode_gitignore() -> String {
861        r#"# Security-focused exclusions
862.env, .env.local, secrets/, .aws/, .ssh/
863
864# Development artifacts
865target/, build/, dist/, node_modules/, vendor/
866
867# Database files
868*.db, *.sqlite, *.sqlite3
869
870# Binary files
871*.exe, *.dll, *.so, *.dylib, *.bin
872
873# IDE files (comprehensive)
874.vscode/, .idea/, *.swp, *.swo
875"#
876        .to_string()
877    }
878
879    #[cfg(feature = "bootstrap")]
880    /// Create sample configuration file
881    pub fn create_sample_config<P: AsRef<Path>>(output: P) -> Result<()> {
882        let output = output.as_ref();
883        let config_content = Self::default_vtcode_toml_template();
884
885        fs::write(output, config_content)
886            .with_context(|| format!("Failed to write config file: {}", output.display()))?;
887
888        Ok(())
889    }
890}