diff --git a/.gooseignore b/.gooseignore new file mode 100644 index 000000000..ff92a713c --- /dev/null +++ b/.gooseignore @@ -0,0 +1,8 @@ +# Ignore environment files +.env + +# Ignore sensitive configuration files +config/secrets.yaml + +# Ignore all files in the private directory +private/ diff --git a/crates/goose-cli/src/commands/configure.rs b/crates/goose-cli/src/commands/configure.rs index 24f786b9d..8951ced90 100644 --- a/crates/goose-cli/src/commands/configure.rs +++ b/crates/goose-cli/src/commands/configure.rs @@ -8,6 +8,9 @@ use mcp_core::Tool; use serde_json::{json, Value}; use std::collections::HashMap; use std::error::Error; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; pub async fn handle_configure() -> Result<(), Box> { let config = Config::global(); @@ -548,3 +551,20 @@ pub fn configure_extensions_dialog() -> Result<(), Box> { Ok(()) } + +/// Read the .gooseignore file and return a list of ignored paths +fn read_gooseignore() -> Result, Box> { + let path = Path::new(".gooseignore"); + let file = File::open(path)?; + let reader = io::BufReader::new(file); + + let mut ignored_paths = Vec::new(); + for line in reader.lines() { + let line = line?; + if !line.trim().is_empty() && !line.starts_with('#') { + ignored_paths.push(line); + } + } + + Ok(ignored_paths) +} diff --git a/crates/goose/src/config/extensions.rs b/crates/goose/src/config/extensions.rs index ffbc955aa..69d431e4a 100644 --- a/crates/goose/src/config/extensions.rs +++ b/crates/goose/src/config/extensions.rs @@ -3,6 +3,9 @@ use crate::agents::ExtensionConfig; use anyhow::Result; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; const DEFAULT_EXTENSION: &str = "developer"; @@ -41,8 +44,11 @@ impl ExtensionManager { Err(e) => return Err(e.into()), }; + // Read the .gooseignore file and get the list of ignored paths + let ignored_paths = read_gooseignore().unwrap_or_default(); + Ok(extensions.get(name).and_then(|entry| { - if entry.enabled { + if entry.enabled && !ignored_paths.contains(&name.to_string()) { Some(entry.config.clone()) } else { None @@ -113,6 +119,24 @@ impl ExtensionManager { Ok(extensions.get(name).map(|e| e.enabled).unwrap_or(false)) } } + +/// Read the .gooseignore file and return a list of ignored paths +fn read_gooseignore() -> Result, Box> { + let path = Path::new(".gooseignore"); + let file = File::open(path)?; + let reader = io::BufReader::new(file); + + let mut ignored_paths = Vec::new(); + for line in reader.lines() { + let line = line?; + if !line.trim().is_empty() && !line.starts_with('#') { + ignored_paths.push(line); + } + } + + Ok(ignored_paths) +} + fn get_keys(entries: HashMap) -> Vec { entries.into_keys().collect() } diff --git a/documentation/docs/guides/file-management.md b/documentation/docs/guides/file-management.md index 3aeb5471c..635a19e17 100644 --- a/documentation/docs/guides/file-management.md +++ b/documentation/docs/guides/file-management.md @@ -21,4 +21,28 @@ Manually review or use automated code reviews to ensure the quality of generated ### Codebase Organization -Structure your codebase into well-defined modules or subdirectories to manage them efficiently. Use a modular approach to isolate parts of the code Goose needs to access. You can also provide specific directories or file paths you want Goose to work on. \ No newline at end of file +Structure your codebase into well-defined modules or subdirectories to manage them efficiently. Use a modular approach to isolate parts of the code Goose needs to access. You can also provide specific directories or file paths you want Goose to work on. + +### Restricting Access with .gooseignore + +To restrict Goose and its extensions from accessing specific files or paths, you can use a `.gooseignore` file. This file works similarly to a `.gitignore` file and allows you to specify files and directories that should be ignored. + +#### Creating a .gooseignore File + +1. Create a file named `.gooseignore` in the root directory of your project. +2. Add the paths of the files or directories you want to ignore, one per line. + +#### Example .gooseignore File + +``` +# Ignore environment files +.env + +# Ignore sensitive configuration files +config/secrets.yaml + +# Ignore all files in the private directory +private/ +``` + +By using a `.gooseignore` file, you can ensure that Goose and its extensions do not access or modify sensitive files or directories in your project.