Managing goose Configurations Across Multiple Projects

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

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

My API Testing & Postman Automation Journey with Gradific API

Related Posts