Upstream Inheritance
⚠️ Experimental — Squad is alpha software. APIs, commands, and behavior may change between releases.
Upstream inheritance allows you to declare external Squad sources—from other repositories, local directories, or exports—and automatically inherit their context (skills, decisions, wisdom, casting policy, routing) at session start. This enables knowledge sharing across teams, organizations, and projects without duplicating Squad configuration.
Why Upstream Inheritance Matters
When you have multiple teams using Squad in an organization, you need a way to share common practices, agent definitions, and decision-making frameworks. Upstream inheritance solves this without creating dependency trees:
- Org-level guidance flows down to team repos and individual projects
- Platform team standards propagate to all consuming teams
- Shared methodologies scale across client projects or service offerings
- Domain models stay consistent across multiple services
Instead of copying configuration, you point to it—and at session start, the coordinator reads all declared upstreams and makes their context available to every spawned agent.
Core Concepts
Three Source Types
Upstreams can come from three places:
| Type | Example | Use Case |
|---|---|---|
| local | ../org-practices/.squad/ | Sibling repo on disk, shared drive, monorepo package |
| git | https://github.com/acme/platform-squad.git | Public org repository or private team repo (with proper credentials) |
| export | ./exports/squad-export.json | Snapshot for offline use or version pinning |
Hierarchy and Resolution
Squad follows a closest-wins principle:
Org-level upstream
↓
Team-level upstream
↓
Repository config (local upstream.json)
↓
My agent instance
The resolver reads upstreams in the order they appear in upstream.json, and later entries override earlier ones for the same content type. This means you can layer upstreams from org → team → repo, with each level adding or overriding as needed.
What Gets Inherited
When you add an upstream, the coordinator reads all of these from its .squad/ directory:
- Skills — all
.squad/skills/*/SKILL.mdfiles - Decisions —
.squad/decisions.md - Wisdom —
.squad/identity/wisdom.md - Casting Policy —
.squad/casting/policy.json - Routing —
.squad/routing.md
If a resource doesn’t exist in an upstream, it’s skipped (no error). This allows upstreams to provide partial context.
Getting Started
Quick Start: Local Upstream
If you have a sibling repository with Squad configuration:
# Add a local upstream from a nearby directory
squad upstream add ../org-practices/.squad
# The coordinator infers the name: "org-practices"
Check it:
squad upstream list
# Output:
# org-practices → local: /path/to/org-practices/.squad (never synced)
The coordinator reads from this path live at session start—no sync needed.
Quick Start: Git Upstream
For a remote repository:
# Add from a public GitHub repo
squad upstream add https://github.com/acme/platform-squad.git --name platform
# Or specify a branch
squad upstream add https://github.com/acme/platform-squad.git --name platform --ref develop
On first add, Squad clones the repo to .squad/_upstream_repos/platform. Keep this directory in .gitignore:
# Already done by squad upstream add
cat .gitignore
# .squad/_upstream_repos/
Update it later:
squad upstream sync platform
Or sync all:
squad upstream sync
Quick Start: Export Snapshot
For offline or pinned versions:
# Export an existing Squad config
squad export-config --output ./exports/snapshot.json
# Add it as an upstream
squad upstream add ./exports/snapshot.json --name snapshot
CLI Reference
squad upstream add <source>
Add a new upstream source.
Signature:
squad upstream add <source> [--name <name>] [--ref <branch>]
Arguments:
<source>— File path, git URL, or export JSON file. Squad auto-detects the type.
Options:
--name <name>— Display name (optional; defaults to repo/dir name)--ref <branch>— Git branch/tag (only for git sources; defaults tomain)
Examples:
Local directory:
squad upstream add ../shared-squad --name shared
Git repository:
squad upstream add https://github.com/acme/platform-squad.git --name platform --ref main
Export file:
squad upstream add ./exports/org-snapshot.json --name org-snapshot
What happens:
- Reads
upstream.jsonfrom.squad/ - Detects source type (local, git, export)
- For git sources: auto-clones to
.squad/_upstream_repos/{name} - Adds entry to
.squad/upstream.json - For local/export: coordinator reads live at session start (no sync needed)
squad upstream remove <name>
Remove an upstream by name.
Signature:
squad upstream remove <name>
Examples:
squad upstream remove platform
What happens:
- Removes entry from
.squad/upstream.json - Deletes cached clone from
.squad/_upstream_repos/{name}if it exists
squad upstream list
Show all configured upstreams.
Signature:
squad upstream list
Output example:
Configured upstreams:
platform → git: https://github.com/acme/platform-squad.git (ref: main) (synced 2026-02-22)
shared → local: /home/alice/shared-squad (never synced)
snapshot → export: ./exports/org-snapshot.json (synced 2026-02-22)
squad upstream sync [name]
Update cached clones for git upstreams, or validate paths for local/export upstreams.
Signature:
squad upstream sync [name]
Examples:
Sync all:
squad upstream sync
Sync one:
squad upstream sync platform
What happens:
- For git sources:
git pull --ff-onlyon the cached clone, or re-clones if needed - For local sources: validates that the path exists
- For export sources: validates that the file exists
- Updates
last_syncedtimestamp inupstream.json
SDK API Reference
The upstream module provides resolver functions for programmatic use.
Types
UpstreamType
type UpstreamType = 'local' | 'git' | 'export';
UpstreamSource
A declared upstream from upstream.json:
interface UpstreamSource {
name: string; // Display name (e.g., "platform")
type: UpstreamType; // How to access it
source: string; // Path, URL, or export file location
ref?: string; // Git ref (only for type: "git")
added_at: string; // ISO timestamp
last_synced: string | null; // Last successful sync
}
UpstreamConfig
The upstream.json file format:
interface UpstreamConfig {
upstreams: UpstreamSource[];
}
ResolvedUpstream
Resolved content from a single upstream:
interface ResolvedUpstream {
name: string;
type: UpstreamType;
skills: Array<{ name: string; content: string }>;
decisions: string | null;
wisdom: string | null;
castingPolicy: Record<string, unknown> | null;
routing: string | null;
}
UpstreamResolution
Result of resolving all upstreams:
interface UpstreamResolution {
upstreams: ResolvedUpstream[];
}
Functions
readUpstreamConfig(squadDir: string): UpstreamConfig | null
Read and parse upstream.json from a squad directory.
Returns: null if file doesn’t exist or is invalid.
Example:
import { readUpstreamConfig } from '@bradygaster/squad-sdk';
const config = readUpstreamConfig('.squad');
if (config) {
console.log(`Found ${config.upstreams.length} upstreams`);
}
resolveUpstreams(squadDir: string): UpstreamResolution | null
Resolve all upstream sources declared in upstream.json.
For each upstream:
- local: reads directly from the source’s
.squad/ - git: reads from
.squad/_upstream_repos/{name}/(must be cloned first) - export: reads from the JSON file
Returns: null if no upstream.json exists. If a source can’t be reached, that upstream is included with empty content (no error thrown).
Example:
import { resolveUpstreams } from '@bradygaster/squad-sdk';
const resolution = resolveUpstreams('.squad');
if (resolution) {
for (const upstream of resolution.upstreams) {
console.log(`${upstream.name}: ${upstream.skills.length} skills`);
}
}
buildInheritedContextBlock(resolution: UpstreamResolution | null): string
Build a text block summarizing inherited context (for agent prompts).
Returns: Empty string if no resolution or upstreams.
Example output:
INHERITED CONTEXT:
platform: skills (3), decisions ✓, casting ✓
shared: skills (5), routing ✓
snapshot: (empty)
Usage: The coordinator includes this in agent spawn prompts to signal what context is available.
buildSessionDisplay(resolution: UpstreamResolution | null): string
Build a user-facing display for session start greeting.
Returns: Empty string if no resolution or upstreams.
Example output:
📡 Inherited context:
platform (git) — 3 skills, decisions, casting
shared (local) — 5 skills, routing
⚠️ snapshot (export) — source not reachable
Usage: Shown in the session greeting to confirm what upstreams are available.
End-to-End Scenarios
Scenario 1: Platform Team at Scale
Setting: Your organization has a platform team that defines shared agent definitions, decisions, and casting policy for all product teams.
Structure:
acme/
platform-squad (platform team repo)
.squad/
decisions.md (org-level decisions)
casting/policy.json (standard casting)
skills/
platform-engineer/SKILL.md
backend-engineer/SKILL.md
product-a (product team repo)
.squad/
upstream.json
[other files]
product-b (product team repo)
.squad/
upstream.json
[other files]
Setup in product-a:
cd product-a
# Add platform team's Squad as upstream
squad upstream add https://github.com/acme/platform-squad.git \
--name platform \
--ref main
# Optionally add product-specific decisions
# (platform decisions are already inherited)
What happens at session start:
- Coordinator reads
.squad/upstream.jsonin product-a - Resolves
platform→ clones/pulls from GitHub - Loads platform’s decisions, casting policy, and skills
- When an agent spawns, it has access to platform’s casting rules and decision framework
- Product team can override by adding their own skills or decisions
Benefit: The platform team updates their practices in one place; all product teams see the changes at their next session start (after squad upstream sync).
Scenario 2: Open-Source Framework with Community Plugins
Setting: You maintain an open-source framework. Community members contribute agent skills and methodologies. You want them to inherit your framework’s core practices without forking.
Structure:
acme-framework (public repo)
.squad/
decisions.md (framework principles)
skills/
framework-engineer/SKILL.md
wisdom.md (philosophy)
routing.md (traffic rules)
community-plugin-a (contributor repo)
.squad/
upstream.json (points to acme-framework)
skills/
plugin-specialization/SKILL.md
[other files]
community-plugin-b (contributor repo)
.squad/
upstream.json (points to acme-framework)
skills/
plugin-other/SKILL.md
[other files]
Setup in community-plugin-a:
squad upstream add https://github.com/acme/acme-framework.git \
--name framework
What happens:
- Plugin developers inherit framework’s decisions, wisdom, and core skills
- Their own skills layer on top
- When the framework publishes new principles, plugins see them at next sync
- Plugins can add or override routing without touching the framework
Benefit: Framework governance scales across a community; contributors stay aligned without central control.
Scenario 3: Consultancy Methodology Across Client Projects
Setting: You’re a consultancy. All client projects should follow your engagement methodology (decisions, casting, methodologies). Each project has unique domain skills.
Structure:
consultancy-methodology (internal repo)
.squad/
decisions.md (client engagement decision framework)
casting/policy.json (role definitions)
wisdom.md (consulting philosophy)
routing.md (internal routing rules)
client-a-project (client repo)
.squad/
upstream.json (points to methodology)
skills/
client-a-domain-expert/SKILL.md
[other files]
client-b-project (client repo)
.squad/
upstream.json (points to methodology)
skills/
client-b-domain-expert/SKILL.md
[other files]
Setup in client-a-project:
squad upstream add https://github.internal/consultancy/methodology.git \
--name consultancy \
--ref main
(Or use SSH/PAT for private repos.)
What happens:
- Every agent spawned in the client project inherits consultancy’s methodology
- Client-specific skills (domain expertise) are layered on top
- Consultancy updates methodology; all active projects pull at next sync
- Each client project remains independent (no shared git history)
Benefit: Quality control at scale; consistent methodology; easy knowledge transfer.
Scenario 4: Multi-Team Shared Domain Model
Setting: Three teams work on different services that share a domain model (e.g., user, order, payment). You want a single source of truth for how to work with that model.
Structure:
shared-domain (shared repo, not a full product)
.squad/
skills/
domain-modeler/SKILL.md (DDD practices)
database-engineer/SKILL.md (schema design)
decisions.md (data governance)
routing.md (domain event routing)
user-service (team repo)
.squad/
upstream.json (points to shared-domain)
[business logic]
order-service (team repo)
.squad/
upstream.json (points to shared-domain)
[business logic]
payment-service (team repo)
.squad/
upstream.json (points to shared-domain)
[business logic]
Setup in user-service:
squad upstream add https://github.com/acme/shared-domain.git --name domain
What happens:
- All agents spawned across the three services have access to shared domain skills
- If domain conventions change, the shared-domain repo is updated once
- Each team pulls the change independently
- Services stay decoupled (no cross-repo deployments)
Benefit: DDD governance; single source of truth; isolation with consistency.
Scenario 5: Post-Acquisition Engineering Convergence
Setting: After acquiring another company, you need to converge engineering practices across two organizations. They have different frameworks, but you want a unified way forward without forcing a rewrite.
Structure:
acme-unified-practices (new shared repo)
.squad/
decisions.md (merged decision framework)
casting/policy.json (unified roles)
skills/
acme-engineer/SKILL.md (original practices)
acquired-engineer/SKILL.md (acquired practices)
routing.md (unified routing)
acme-product (original product repo)
.squad/
upstream.json (points to unified-practices)
[business logic]
acquired-product (acquired product repo)
.squad/
upstream.json (points to unified-practices)
[business logic]
Setup in acquired-product:
squad upstream add https://github.com/acme/acme-unified-practices.git --name unified
What happens:
- Both products inherit the merged practices
- Agents understand both organizations’ traditions (skills for both)
- Decisions reflect the merged framework
- Teams can work independently while being culturally aligned
Benefit: Smooth integration without painful rewrites; shared culture; gradual convergence.
Scenario 6: Enterprise Application Modernization
Setting: You’re migrating a monolith to microservices. You want to maintain architectural consistency across new services while honoring legacy patterns.
Structure:
modernization-playbook (central guidance repo)
.squad/
decisions.md (architecture decisions, API patterns)
skills/
microservice-engineer/SKILL.md (cloud-native practices)
legacy-translator/SKILL.md (backward compatibility)
wisdom.md (migration philosophy)
routing.md (inter-service routing)
legacy-monolith (old codebase)
.squad/
upstream.json (points to playbook)
[monolith code]
billing-service (new microservice)
.squad/
upstream.json (points to playbook)
[business logic]
inventory-service (new microservice)
.squad/
upstream.json (points to playbook)
[business logic]
shipping-service (new microservice)
.squad/
upstream.json (points to playbook)
[business logic]
Setup in billing-service:
squad upstream add https://github.com/acme/modernization-playbook.git \
--name playbook
What happens:
- All new services inherit architectural guidance
- The legacy monolith inherits it too (preparing for extraction)
- Playbook defines how services communicate, handle transactions, manage state
- When a pattern is learned, it goes into the playbook once; all services benefit
Benefit: Architectural coherence; faster service extraction; knowledge base grows with the migration.
Troubleshooting
Git Clone or Sync Fails
Problem: git clone times out or fails with authentication errors.
Solutions:
- Ensure the URL is correct:
https://github.com/owner/repo.git - For private repos, use SSH (
git@github.com:owner/repo.git) and ensure your SSH key is in ssh-agent - Or use a GitHub PAT with
https://[PAT]@github.com/owner/repo.git(less secure; prefer SSH) - Check network:
git clone --depth 1 --branch main <url>from the command line first - If
squad upstream syncfails, cached clone is stale; run again later
Local Upstream Not Found
Problem: squad upstream add ../shared/.squad fails with “Cannot determine source type”.
Solutions:
- Ensure the path exists:
ls -la ../shared/.squad - Ensure it contains a
.squad/directory (not a.squadfile) - Use absolute path if relative paths are ambiguous:
squad upstream add /full/path/to/shared/.squad - Verify the other repo is actually a Squad repo (has
.squad/directory)
Export File Invalid
Problem: squad upstream add ./export.json fails or doesn’t load skills.
Solutions:
- Verify the file is valid JSON:
jq . ./export.json - Ensure it was created by
squad export-config(has the right schema) - Check that skills array is present:
jq .skills ./export.json - If manually created, the structure should be:
{ "version": "1.0", "skills": ["<skill content 1>", "<skill content 2>", ...], "casting": { "policy": { ... } } }
Agents Don’t See Inherited Context
Problem: Spawned agents don’t have access to upstream skills/decisions.
Solutions:
- Verify upstreams are configured:
squad upstream list - Verify sources are reachable:
squad upstream sync(should not warn) - Check the session display when you start the session (should show
📡 Inherited context:) - For git upstreams, ensure they’ve been cloned: check
.squad/_upstream_repos/{name} - For local upstreams, ensure the path still exists
- Restart your session (upstream resolution happens at session start)
Cached Clone Gets Out of Date
Problem: You know the upstream repo changed, but agents still see old content.
Solution:
squad upstream sync <name>
For all upstreams:
squad upstream sync
This updates git clones and validates local/export paths. Then start a new session.
Order Matters
Problem: Upstream A and Upstream B define conflicting decisions or skills.
Note: Later entries in upstream.json override earlier ones. The resolver reads in order and the last definition wins.
Solution:
Order matters. Check squad upstream list to see the order, and use remove + add to reorder if needed.
Next Steps
- Read more: See
docs/guide/casting.mdfor how inherited casting policy shapes agent behavior - Set up: Run
squad upstream add <source>to add your first upstream - Share: Export your Squad config with
squad export-configfor others to inherit - Iterate: Update your upstream and run
squad upstream syncto pull changes across all consuming projects