/ado-pull
Pull latest changes from Azure DevOps (like git pull). Supports increment, project, or full living docs sync.
> /plugin marketplace add anton-abyzov/specweave > /plugin install sw@specweave
How it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/ado-pull
Context preview
What this command does when you run it.
Pull latest changes from Azure DevOps (like git pull). Supports increment, project, or full living docs sync.
Command definition
ado-pull.mddescription: Pull latest changes from Azure DevOps (like git pull). Supports increment, project, or full living docs sync.
ADO Pull Command
**Usage**: `sw-ado:pull [target] [options]`
**Purpose**: Pull latest changes from Azure DevOps (like `git pull`)
---
Quick Start
# Pull for current/active increment (simple mode)
sw-ado:pull
# Pull for specific increment
sw-ado:pull 0005
# Pull ALL changes across ALL projects (living docs sync)
sw-ado:pull --all
# Pull for specific project/board
sw-ado:pull --project clinical-insights
# Pull specific feature hierarchy (Epic → Feature → User Stories)
sw-ado:pull --feature FS-042
---
Sync Modes
Mode 1: Increment Sync (Default)
sw-ado:pull [increment-id]
Syncs ONE increment ↔ ONE linked work item.
Mode 2: Living Docs Sync (Full)
sw-ado:pull --all [--time-range 1M]
Syncs ALL specs across ALL projects/boards:
- Discovers all linked specs in `.specweave/docs/internal/specs/`
- Fetches changes from ADO for each linked item
- Updates User Stories, Features, Epics
- Respects multi-project folder structure
Mode 3: Project-Scoped Sync
sw-ado:pull --project clinical-insights
Syncs all specs within a specific project folder:
specs/clinical-insights/
├── FS-042/us-001.md ← Synced
├── FS-042/us-002.md ← Synced
└── FS-043/us-003.md ← Synced
Mode 4: Feature Hierarchy Sync
sw-ado:pull --feature FS-042
Syncs a specific feature and ALL its children:
ADO Epic #100
└── Feature #200 (FS-042) ← Synced
└── US-001 #201 ← Synced
└── US-002 #202 ← Synced
└── US-003 #203 ← Synced---
What Gets Pulled
| Field | Behavior | |-------|----------| | **Status** | External ALWAYS wins (QA/stakeholder decisions) | | **Priority** | External wins (stakeholder prioritization) | | **Iteration/Sprint** | Updated if changed in ADO | | **Comments** | New team comments imported | | **Assignee** | Updated if changed | | **Parent Links** | Epic → Feature → Story hierarchy preserved |
---
Multi-Project Routing
When pulling with `--all`, the system routes changes to correct folders:
ADO Organization
├── Project: TechCorp
│ ├── Area: Clinical-Insights → specs/techcorp/clinical-insights/
│ └── Area: AI-Platform → specs/techcorp/ai-platform/
└── Project: Infrastructure
└── Area: Core → specs/infrastructure/core/**Routing Priority:** 1. **Explicit mapping** in `config.json` (areaPathMapping) 2. **Board matching** with keyword confidence scoring 3. **Existing folder** structure detection 4. **Ask user** if ambiguous
---
Command Behavior
0. Load Credentials from .env (MANDATORY FIRST)
**CRITICAL**: Read PAT from `.env` file, NOT from shell environment variables.
# Read PAT from .env file
ADO_PAT=$(grep '^AZURE_DEVOPS_PAT=' .env 2>/dev/null | cut -d'=' -f2)
if [ -z "$ADO_PAT" ]; then
echo "ERROR: AZURE_DEVOPS_PAT not found in .env file"
echo "Add to .env: AZURE_DEVOPS_PAT=your-pat-here"
exit 1
fi
For Increment Mode (default):
const incrementId = args.incrementId || await findActiveIncrement();
const metadata = await loadIncrementMetadata(incrementId);
const adoWorkItemId = metadata?.external_sync?.ado?.workItemId;
if (!adoWorkItemId) {
console.log('Not linked to ADO. Run: sw-ado:create');
return;
}
// Pull changes for single work item
await pullFromAdo(incrementId, adoWorkItemId);For Living Docs Mode (--all):
// 1. Discover all specs with ADO links
const allSpecs = await discoverLinkedSpecs({
specsDir: '.specweave/docs/internal/specs/',
provider: 'ado'
});
// 2. Group by project/board for batch API calls
const byProject = groupByAdoProject(allSpecs);
// 3. Pull changes for each project
for (const [projectPath, specs] of byProject) {
console.log(`Pulling ${projectPath}/ (${specs.length} items)...`);
for (const spec of specs) {
const changes = await pullSpecFromAdo(spec);
if (changes.hasChanges) {
await updateSpecFile(spec.path, changes);
console.log(` ✓ ${spec.usId}: ${changes.summary}`);
}
}
}Spec Discovery Logic:
// Find all specs with ADO external links
async function discoverLinkedSpecs(options) {
const specs = [];
// Scan: specs/{project}/{board}/FS-XXX/us-*.md
const pattern = `${options.specsDir}/**/us-*.md`;
const files = await glob(pattern);
for (const file of files) {
const frontmatter = await parseYamlFrontmatter(file);
// Check for ADO link in frontmatter
if (frontmatter.externalLinks?.ado?.workItemId) {
specs.push({
path: file,
usId: frontmatter.id,
workItemId: frontmatter.externalLinks.ado.workItemId,
projectPath: extractProjectPath(file),
lastSynced: frontmatter.externalLinks.ado.syncedAt
});
}
}
return specs;
}---
Conflict Resolution
**CRITICAL**: External tool status ALWAYS wins.
| Scenario | Winner | Reason | |----------|--------|--------| | Status differs | **External** | QA/stakeholder decisions | | Priority differs | **External** | Stakeholder prioritization | | Iteration differs | **External** | Sprint planning decisions | | Content differs | **Timestamp** | More recent wins |
---
Examples
Example 1: Pull Single Increment
User: sw-ado:pull 0005
Claude:
Pulling from ADO...
Increment: 0005-payment-integration
Work Item: #12345
Changes Applied:
Status: in-progress -> implemented (external wins)
Pull complete!
Example 2: Pull All (Living Docs Sync)
User: sw-ado:pull --all
Claude:
Discovering linked specs...
Found 47 specs across 3 projects
Pulling techcorp/clinical-insights/ (18 items)...
✓ US-001: Status updated (In Progress → Done)
✓ US-002: Priority changed (P2 → P1)
✓ US-003: 2 new comments imported
... (15 unchanged)
Pulling techcorp/ai-platform/ (22 items)...
✓ US-010: Iter
Read more
description: Pull latest changes from Azure DevOps (like git pull). Supports increment, project, or full living docs sync.
ADO Pull Command
**Usage**: `sw-ado:pull [target] [options]`
**Purpose**: Pull latest changes from Azure DevOps (like `git pull`)
---
Quick Start
# Pull for current/active increment (simple mode) sw-ado:pull # Pull for specific increment sw-ado:pull 0005 # Pull ALL changes across ALL projects (living docs sync) sw-ado:pull --all # Pull for specific project/board sw-ado:pull --project clinical-insights # Pull specific feature hierarchy (Epic → Feature → User Stories) sw-ado:pull --feature FS-042
---
Sync Modes
Mode 1: Increment Sync (Default)
sw-ado:pull [increment-id]
Syncs ONE increment ↔ ONE linked work item.
Mode 2: Living Docs Sync (Full)
sw-ado:pull --all [--time-range 1M]
Syncs ALL specs across ALL projects/boards:
- Discovers all linked specs in `.specweave/docs/internal/specs/`
- Fetches changes from ADO for each linked item
- Updates User Stories, Features, Epics
- Respects multi-project folder structure
Mode 3: Project-Scoped Sync
sw-ado:pull --project clinical-insights
Syncs all specs within a specific project folder:
specs/clinical-insights/ ├── FS-042/us-001.md ← Synced ├── FS-042/us-002.md ← Synced └── FS-043/us-003.md ← Synced
Mode 4: Feature Hierarchy Sync
sw-ado:pull --feature FS-042
Syncs a specific feature and ALL its children:
ADO Epic #100
└── Feature #200 (FS-042) ← Synced
└── US-001 #201 ← Synced
└── US-002 #202 ← Synced
└── US-003 #203 ← Synced---
What Gets Pulled
| Field | Behavior | |-------|----------| | **Status** | External ALWAYS wins (QA/stakeholder decisions) | | **Priority** | External wins (stakeholder prioritization) | | **Iteration/Sprint** | Updated if changed in ADO | | **Comments** | New team comments imported | | **Assignee** | Updated if changed | | **Parent Links** | Epic → Feature → Story hierarchy preserved |
---
Multi-Project Routing
When pulling with `--all`, the system routes changes to correct folders:
ADO Organization
├── Project: TechCorp
│ ├── Area: Clinical-Insights → specs/techcorp/clinical-insights/
│ └── Area: AI-Platform → specs/techcorp/ai-platform/
└── Project: Infrastructure
└── Area: Core → specs/infrastructure/core/**Routing Priority:** 1. **Explicit mapping** in `config.json` (areaPathMapping) 2. **Board matching** with keyword confidence scoring 3. **Existing folder** structure detection 4. **Ask user** if ambiguous
---
Command Behavior
0. Load Credentials from .env (MANDATORY FIRST)
**CRITICAL**: Read PAT from `.env` file, NOT from shell environment variables.
# Read PAT from .env file ADO_PAT=$(grep '^AZURE_DEVOPS_PAT=' .env 2>/dev/null | cut -d'=' -f2) if [ -z "$ADO_PAT" ]; then echo "ERROR: AZURE_DEVOPS_PAT not found in .env file" echo "Add to .env: AZURE_DEVOPS_PAT=your-pat-here" exit 1 fi
For Increment Mode (default):
const incrementId = args.incrementId || await findActiveIncrement();
const metadata = await loadIncrementMetadata(incrementId);
const adoWorkItemId = metadata?.external_sync?.ado?.workItemId;
if (!adoWorkItemId) {
console.log('Not linked to ADO. Run: sw-ado:create');
return;
}
// Pull changes for single work item
await pullFromAdo(incrementId, adoWorkItemId);For Living Docs Mode (--all):
// 1. Discover all specs with ADO links
const allSpecs = await discoverLinkedSpecs({
specsDir: '.specweave/docs/internal/specs/',
provider: 'ado'
});
// 2. Group by project/board for batch API calls
const byProject = groupByAdoProject(allSpecs);
// 3. Pull changes for each project
for (const [projectPath, specs] of byProject) {
console.log(`Pulling ${projectPath}/ (${specs.length} items)...`);
for (const spec of specs) {
const changes = await pullSpecFromAdo(spec);
if (changes.hasChanges) {
await updateSpecFile(spec.path, changes);
console.log(` ✓ ${spec.usId}: ${changes.summary}`);
}
}
}Spec Discovery Logic:
// Find all specs with ADO external links
async function discoverLinkedSpecs(options) {
const specs = [];
// Scan: specs/{project}/{board}/FS-XXX/us-*.md
const pattern = `${options.specsDir}/**/us-*.md`;
const files = await glob(pattern);
for (const file of files) {
const frontmatter = await parseYamlFrontmatter(file);
// Check for ADO link in frontmatter
if (frontmatter.externalLinks?.ado?.workItemId) {
specs.push({
path: file,
usId: frontmatter.id,
workItemId: frontmatter.externalLinks.ado.workItemId,
projectPath: extractProjectPath(file),
lastSynced: frontmatter.externalLinks.ado.syncedAt
});
}
}
return specs;
}---
Conflict Resolution
**CRITICAL**: External tool status ALWAYS wins.
| Scenario | Winner | Reason | |----------|--------|--------| | Status differs | **External** | QA/stakeholder decisions | | Priority differs | **External** | Stakeholder prioritization | | Iteration differs | **External** | Sprint planning decisions | | Content differs | **Timestamp** | More recent wins |
---
Examples
Example 1: Pull Single Increment
User: sw-ado:pull 0005 Claude: Pulling from ADO... Increment: 0005-payment-integration Work Item: #12345 Changes Applied: Status: in-progress -> implemented (external wins) Pull complete!
Example 2: Pull All (Living Docs Sync)
User: sw-ado:pull --all Claude: Discovering linked specs... Found 47 specs across 3 projects Pulling techcorp/clinical-insights/ (18 items)... ✓ US-001: Status updated (In Progress → Done) ✓ US-002: Priority changed (P2 → P1) ✓ US-003: 2 new comments imported ... (15 unchanged) Pulling techcorp/ai-platform/ (22 items)... ✓ US-010: Iter
Spec-first AI development: describe a feature → AI creates spec + plan + tasks, builds autonomously, syncs to GitHub/JIRA. Domain-expert skills for PM, Architect, Frontend, QA learn your patterns permanently. Claude Code, Codex, Cursor, Copilot & more.
Repo: anton-abyzov/specweave
Other commands on specweave.
- /abandon
Abandon an incomplete increment (requirements changed, obsolete)
Open command - /ado-cleanup-duplicates
Clean up duplicate Azure DevOps work items for a Feature. Finds work items with duplicate titles and closes all except the first created item.
Open command - /ado-clone
Clone Azure DevOps repositories to local workspace. Use after init if cloning was skipped, or to add repos later.
Open command - /ado-close
Close Azure DevOps work item when increment complete
Open command - /ado-create
Create Azure DevOps work item from SpecWeave increment
Open command - /ado-import-areas
Import Azure DevOps area paths from a project and map them to SpecWeave projects. Creates 2-level directory structure with area path-based organization.
Open command

