As development teams scale their use of goose across multiple projects, a new challenge emerges: how do you maintain consistent configurations while adapting to each project’s unique needs? In my previous post on team environments, we explored shared workflows within a single project. Now, let’s tackle the multi-project configuration challenge.
The Multi-Project Configuration Problem
When working with goose across multiple projects, teams often face:
- Configuration drift between projects leading to inconsistent behavior
- Duplicated configuration that becomes painful to maintain
- Context switching overhead when moving between projects
- Onboarding friction as team members learn different configurations for each project
The goal is to establish a scalable configuration strategy that maintains consistency where needed while allowing project-specific customization.
Configuration Hierarchy Strategy
The most effective approach uses a three-tier configuration hierarchy:
1. Global Base Configuration
Create a shared base configuration that defines organization-wide standards:
# ~/.config/goose/profiles.yaml (global)
default:
provider: openai
processor: gpt-4
accelerator: gpt-4
moderator: truncate
organization-standards:
provider: openai
processor: gpt-4
accelerator: gpt-4
moderator: truncate
toolkits:
- name: developer
- name: github
requires:
GITHUB_TOKEN: github-token
This global configuration serves as your baseline, ensuring all projects start with consistent standards.
2. Project-Specific Configuration
Each project maintains its own .goose/profiles.yaml that extends or overrides the base:
# project-a/.goose/profiles.yaml
default:
provider: openai
processor: gpt-4
accelerator: gpt-4
moderator: truncate
toolkits:
- name: developer
- name: github
requires:
GITHUB_TOKEN: github-token
- name: repo_context
requires:
path: .
backend-dev:
extends: default
toolkits:
- name: docker
- name: database
3. Personal Overrides
Individual developers can customize further with local overrides:
# project-a/.goose/profiles.local.yaml (gitignored)
default:
provider: anthropic # Personal preference
processor: claude-sonnet-4.5
## Practical Implementation Strategies
### Strategy 1: Configuration Templates Repository
Create a dedicated repository for configuration templates:
goose-configs/
├── README.md
├── templates/
│ ├── base/
│ │ └── profiles.yaml
│ ├── web-app/
│ │ └── profiles.yaml
│ ├── api-service/
│ │ └── profiles.yaml
│ └── data-pipeline/
│ └── profiles.yaml
└── scripts/
├── init-project.sh
└── sync-config.sh
init-project.sh example:
#!/bin/bash
# Initialize Goose config for a new project
PROJECT_TYPE=$1
TEMPLATE_PATH="templates/${PROJECT_TYPE}/profiles.yaml"
if [ ! -f "$TEMPLATE_PATH" ]; then
echo "Unknown project type: $PROJECT_TYPE"
echo "Available types: base, web-app, api-service, data-pipeline"
exit 1
fi
mkdir -p .goose
cp "$TEMPLATE_PATH" .goose/profiles.yaml
echo "✓ Goose configuration initialized for $PROJECT_TYPE"
echo "Next steps:"
echo "1. Review .goose/profiles.yaml"
echo "2. Add .goose/profiles.local.yaml to .gitignore"
echo "3. Commit .goose/profiles.yaml to version control"
Strategy 2: Configuration as Code with Validation
Implement configuration validation to catch issues early:
# .goose/profiles.yaml with schema validation
default:
provider: openai
processor: gpt-4
accelerator: gpt-4
moderator: truncate
# Validation metadata
_metadata:
schema_version: "1.0"
required_env_vars:
- OPENAI_API_KEY
- GITHUB_TOKEN
team: "platform-team"
last_updated: "2025-10-30"
Create a validation script:
# scripts/validate-goose-config.py
import yaml
import os
import sys
def validate_config(config_path):
"""Validate Goose configuration file"""
errors = []
with open(config_path) as f:
config = yaml.safe_load(f)
# Check required environment variables
metadata = config.get('default', {}).get('_metadata', {})
required_vars = metadata.get('required_env_vars', [])
for var in required_vars:
if not os.getenv(var):
errors.append(f"Missing required environment variable: {var}")
# Validate profile structure
for profile_name, profile in config.items():
if profile_name.startswith('_'):
continue
if 'provider' not in profile:
errors.append(f"Profile '{profile_name}' missing required 'provider' field")
return errors
if __name__ == '__main__':
errors = validate_config('.goose/profiles.yaml')
if errors:
print("❌ Configuration validation failed:")
for error in errors:
print(f" - {error}")
sys.exit(1)
else:
print("✓ Configuration valid")
Strategy 3: Environment-Specific Profiles
Structure profiles to handle different environments:
# .goose/profiles.yaml
default:
provider: openai
processor: gpt-4
accelerator: gpt-4
moderator: truncate
toolkits:
- name: developer
development:
extends: default
toolkits:
- name: developer
- name: github
- name: docker
requires:
DOCKER_HOST: "unix:///var/run/docker.sock"
staging:
extends: default
toolkits:
- name: developer
- name: github
- name: kubernetes
requires:
KUBE_CONFIG: staging-config
production:
extends: default
toolkits:
- name: developer
- name: github
- name: kubernetes
requires:
KUBE_CONFIG: production-config
# More restrictive settings for production
moderator: conservative
Syncing Configurations Across Projects
Automated Sync Script
#!/bin/bash
# scripts/sync-goose-configs.sh
# Sync base configuration across all projects
CONFIG_REPO="git@github.com:your-org/goose-configs.git"
TEMP_DIR=$(mktemp -d)
# Clone config repository
git clone "$CONFIG_REPO" "$TEMP_DIR"
# Find all projects with Goose configs
find ~/projects -name ".goose" -type d | while read goose_dir; do
project_dir=$(dirname "$goose_dir")
project_name=$(basename "$project_dir")
echo "Syncing config for $project_name..."
# Backup existing config
cp "$goose_dir/profiles.yaml" "$goose_dir/profiles.yaml.bak"
# Merge base config with project-specific settings
python3 "$TEMP_DIR/scripts/merge-configs.py"
"$TEMP_DIR/templates/base/profiles.yaml"
"$goose_dir/profiles.yaml"
> "$goose_dir/profiles.yaml.new"
# Replace if merge successful
if [ $? -eq 0 ]; then
mv "$goose_dir/profiles.yaml.new" "$goose_dir/profiles.yaml"
echo "✓ Updated $project_name"
else
echo "✗ Failed to update $project_name"
rm "$goose_dir/profiles.yaml.new"
fi
done
# Cleanup
rm -rf "$TEMP_DIR"
Best Practices for Multi-Project Management
1. Document Your Configuration Strategy
Create a clear README in your configuration repository:
# Goose Configuration Standards
## Configuration Hierarchy
1. **Global base** (~/.config/goose/profiles.yaml)
2. **Project-specific** (.goose/profiles.yaml) - Committed to git
3. **Personal overrides** (.goose/profiles.local.yaml) - Gitignored
## Project Types and Templates
- **web-app**: Frontend applications (React, Vue, Angular)
- **api-service**: Backend APIs and microservices
- **data-pipeline**: ETL and data processing projects
- **infrastructure**: Terraform, Kubernetes configurations
## Adding a New Project
`./scripts/init-project.sh `
## Updating Configurations
Run monthly to sync base configurations:
`./scripts/sync-goose-configs.sh`
2. Version Control Strategy
DO commit to git:
.goose/profiles.yaml (project configuration)
.goose/toolkit-configs/ (shared toolkit settings)
Documentation about configuration choices
DO NOT commit to git:
.goose/profiles.local.yaml (personal overrides)
.goose/sessions/ (session history)
API keys or secrets
Add to .gitignore:
# Goose personal configurations and sessions
.goose/profiles.local.yaml
.goose/sessions/
.goose/**/*.log
3. Toolkit Management Across Projects
Standardize commonly used toolkits:
# Standard toolkit configurations
default:
toolkits:
# Core toolkits - always included
- name: developer
# Version control - most projects
- name: github
requires:
GITHUB_TOKEN: github-token
# Project-specific toolkits added per project
# Examples: docker, kubernetes, database, etc.
4. Environment Variable Management
Use a consistent approach for environment variables across projects:
Option A: .env files (per project)
# .env.goose (gitignored)
GOOSE_PROVIDER=openai
OPENAI_API_KEY=sk-...
GITHUB_TOKEN=ghp_...
Option B: Shared secrets manager
# Use tools like 1Password, AWS Secrets Manager, or HashiCorp Vault
export OPENAI_API_KEY=$(op read "op://Development/Goose/OPENAI_API_KEY")
5. Testing Configuration Changes
Before rolling out configuration changes, test in a sandbox:
# Test configuration in a sandbox project
mkdir -p /tmp/goose-config-test
cd /tmp/goose-config-test
cp -r ~/goose-configs/templates/base/.goose .
goose session start --profile default
# Verify configuration loaded correctly
# Test key workflows
# Check for errors or warnings
## Advanced Patterns
### Pattern 1: Monorepo Configuration
For monorepos with multiple sub-projects:
monorepo/
├── .goose/
│ └── profiles.yaml # Root configuration
├── packages/
│ ├── frontend/
│ │ └── .goose/
│ │ └── profiles.yaml # Frontend-specific
│ ├── backend/
│ │ └── .goose/
│ │ └── profiles.yaml # Backend-specific
│ └── shared/
│ └── .goose/
│ └── profiles.yaml # Shared library config
Pattern 2: Dynamic Profile Selection
Use shell aliases to quickly switch contexts:
# ~/.bashrc or ~/.zshrc
alias goose-fe='cd ~/projects/myapp/frontend && goose session start --profile frontend'
alias goose-be='cd ~/projects/myapp/backend && goose session start --profile backend'
alias goose-infra='cd ~/projects/myapp/infra && goose session start --profile infrastructure'
Pattern 3: Configuration Inheritance Chain
# Complex inheritance for specialized needs
base:
provider: openai
processor: gpt-4
python-base:
extends: base
toolkits:
- name: developer
- name: python
django-app:
extends: python-base
toolkits:
- name: database
- name: docker
ml-pipeline:
extends: python-base
toolkits:
- name: jupyter
- name: data-science
Monitoring and Maintenance
Configuration Drift Detection
Create a script to identify configuration drift:
# scripts/detect-config-drift.py
import yaml
import os
from pathlib import Path
def compare_configs(base_config, project_config):
"""Compare project config against base and report differences"""
differences = []
# Compare provider settings
if project_config.get('provider') != base_config.get('provider'):
differences.append(
f"Provider mismatch: {project_config.get('provider')} vs {base_config.get('provider')}"
)
# Add more comparison logic
return differences
# Scan all projects
projects_dir = Path.home() / 'projects'
for goose_config in projects_dir.glob('**/.goose/profiles.yaml'):
# Load and compare...
pass
Regular Maintenance Schedule
Establish a maintenance routine:
- Weekly: Review new toolkit releases and compatibility
- Monthly: Audit configurations across projects for drift
- Quarterly: Update base templates and roll out to projects
- Annually: Review and refactor configuration strategy
Troubleshooting Common Issues
Issue 1: Configuration Not Loading
Problem: Goose not picking up project configuration
Solution: Check configuration precedence
# Debug which config is being used
goose config show --verbose
# Verify file exists and is valid YAML
cat .goose/profiles.yaml | python -m yaml
Issue 2: Toolkit Conflicts
Problem: Toolkits behaving differently across projects
Solution: Standardize toolkit versions and dependencies
default:
toolkits:
- name: developer
version: "1.0.0" # Pin versions when possible
Issue 3: Environment Variable Confusion
Problem: Different projects expecting different environment variables
Solution: Use project-specific .env files and document clearly
# Add to project README
## Required Environment Variables
- GOOSE_PROVIDER: OpenAI or Anthropic
- OPENAI_API_KEY: Your OpenAI API key
- GITHUB_TOKEN: GitHub personal access token
Conclusion
Managing goose configurations across multiple projects requires a thoughtful strategy that balances consistency with flexibility. By implementing a configuration hierarchy, using templates, automating synchronization, and following best practices, you can scale goose across your organization without sacrificing maintainability.
Key takeaways
- Establish a clear hierarchy: Global base → Project-specific → Personal overrides
- Use configuration templates: Create reusable templates for common project types
- Automate where possible: Scripts for initialization, validation, and synchronization
- Version control strategically: Commit shared configs, ignore personal overrides
- Document thoroughly: Make it easy for team members to understand and follow standards
- Monitor for drift: Regularly audit configurations to maintain consistency.
As your team grows and adopts goose more widely, these strategies will help you maintain a scalable, consistent configuration management approach that empowers developers rather than constrains them.
Do you have questions about managing Goose across your projects? Drop a comment below