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