diff --git a/README.md b/README.md index e94c6cb..add3e59 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,20 @@ You can configure OpenCode using environment variables: } ``` +### Context Paths +By default, OpenCode loads a set of built-in context files (e.g. `.github/copilot-instructions.md`, `.cursor/rules/`, `OPENCODE.md`, etc.) to provide additional guidance to the AI assistant. You can extend or override these by adding a `contextPaths` array to your configuration: +```json +{ + "contextPaths": [ + "docs/context.md", + "./project-instructions.md", + "/some/absolute/global-instructions.md" + ] +} +``` +Relative paths (those not starting with `/`) are resolved against the configured working directory, while absolute paths are used as-is. Duplicate entries are automatically removed. + + ## Supported AI Models OpenCode supports a variety of AI models from different providers: diff --git a/internal/config/config.go b/internal/config/config.go index c825805..02c6abf 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -140,6 +140,9 @@ func Load(workingDir string, debug bool) (*Config, error) { setProviderDefaults() + // Process and normalize context paths + processContextPaths() + // Apply configuration to the struct if err := viper.Unmarshal(cfg); err != nil { return cfg, fmt.Errorf("failed to unmarshal config: %w", err) @@ -324,6 +327,40 @@ func setProviderDefaults() { } } +// processContextPaths merges built-in defaults and user-specified context paths, +// normalizes both relative and absolute paths, and deduplicates the final list. +func processContextPaths() { + // Combine built-in defaults with any user-specified context paths + userPaths := viper.GetStringSlice("contextPaths") + paths := append(defaultContextPaths, userPaths...) + + normalized := make([]string, 0, len(paths)) + seen := make(map[string]bool) + + for _, p := range paths { + var absPath string + var err error + + if filepath.IsAbs(p) { + absPath = p + } else { + absPath, err = filepath.Abs(filepath.Join(cfg.WorkingDir, p)) + if err != nil { + logging.Warn("failed to resolve context path", "path", p, "error", err) + continue + } + } + + if !seen[absPath] { + seen[absPath] = true + normalized = append(normalized, absPath) + } + } + + // Update viper with normalized paths + viper.Set("contextPaths", normalized) +} + // hasAWSCredentials checks if AWS credentials are available in the environment. func hasAWSCredentials() bool { // Check for explicit AWS credentials @@ -708,6 +745,13 @@ func WorkingDirectory() string { } return cfg.WorkingDir } +// ContextPaths returns the list of configured and normalized context paths. +func ContextPaths() []string { + if cfg == nil { + panic("config not loaded") + } + return cfg.ContextPaths +} func UpdateAgentModel(agentName AgentName, modelID models.ModelID) error { if cfg == nil {