/ado-clone
Clone Azure DevOps repositories to local workspace. Use after init if cloning was skipped, or to add repos later.
> /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-clone
Context preview
What this command does when you run it.
Clone Azure DevOps repositories to local workspace. Use after init if cloning was skipped, or to add repos later.
Command definition
ado-clone.mddescription: Clone Azure DevOps repositories to local workspace. Use after init if cloning was skipped, or to add repos later.
Clone Azure DevOps Repositories Command
You are an Azure DevOps repository cloning expert. Help users clone repositories from ADO projects to their local workspace.
Purpose
This command clones Azure DevOps repositories **after** initial SpecWeave setup (`specweave init`). Use when:
- User skipped cloning during init
- Adding repositories from additional projects
- Re-cloning after cleanup
- Selective cloning with pattern filtering
Command Syntax
# Interactive mode (prompts for everything)
sw-ado:clone-repos
# With pattern filter
sw-ado:clone-repos --pattern "sw-*"
# Regex pattern
sw-ado:clone-repos --pattern "regex:^api-.*$"
# Specific project only
sw-ado:clone-repos --project "MyProject"
# Dry-run (preview only)
sw-ado:clone-repos --dry-run
Your Task
When the user runs this command:
Step 1: Check Prerequisites
import { readEnvFile, parseEnvFile } from '../../../src/utils/env-file.js';
import chalk from 'chalk';
const projectPath = process.cwd();
const envContent = readEnvFile(projectPath);
if (!envContent) {
console.log(chalk.red('❌ No .env file found. Run `specweave init` first.'));
return;
}
const parsed = parseEnvFile(envContent);
if (!parsed.AZURE_DEVOPS_PAT || !parsed.AZURE_DEVOPS_ORG) {
console.log(chalk.red('❌ Missing Azure DevOps credentials.'));
console.log(chalk.gray(' Run `specweave init` with Azure DevOps provider.'));
return;
}
const org = parsed.AZURE_DEVOPS_ORG;
const pat = parsed.AZURE_DEVOPS_PAT;
console.log(chalk.blue('\n📦 ADO Repository Cloning\n'));
console.log(chalk.gray(` Organization: ${org}`));Step 2: Get Project Selection
import { AzureDevOpsProvider } from '../../../src/core/repo-structure/providers/azure-devops-provider.js';
const provider = new AzureDevOpsProvider();
// If project specified via CLI, use it
let selectedProjects: string[] = [];
if (args.project) {
selectedProjects = [args.project];
console.log(chalk.gray(` Project: ${args.project} (from CLI)`));
} else {
// Fetch available projects
console.log(chalk.gray('\n Fetching projects...'));
const response = await fetch(
`https://dev.azure.com/${org}/_apis/projects?api-version=7.0`,
{
headers: {
'Authorization': `Basic ${Buffer.from(':' + pat).toString('base64')}`,
'Accept': 'application/json'
}
}
);
if (!response.ok) {
console.log(chalk.red(`❌ Failed to fetch projects: ${response.status}`));
return;
}
const data = await response.json();
const projects = data.value || [];
if (projects.length === 0) {
console.log(chalk.yellow('⚠️ No projects found in organization.'));
return;
}
// Prompt for project selection
const { checkbox } = await import('@inquirer/prompts');
selectedProjects = await checkbox({
message: 'Select project(s) to clone repositories from:',
choices: projects.map(p => ({ name: p.name, value: p.name })),
required: true
});
console.log(chalk.green(` ✓ ${selectedProjects.length} project(s) selected`));
}Step 3: Fetch Repositories
const allRepos = [];
for (const project of selectedProjects) {
console.log(chalk.gray(`\n Fetching repos from ${project}...`));
try {
const repos = await provider.listRepositories(org, project, pat);
const reposWithProject = repos.map(r => ({ ...r, project }));
allRepos.push(...reposWithProject);
console.log(chalk.green(` ✓ Found ${repos.length} repositories`));
} catch (error) {
console.log(chalk.yellow(` ⚠️ Failed: ${error.message}`));
}
}
if (allRepos.length === 0) {
console.log(chalk.yellow('\n⚠️ No repositories found.'));
return;
}
console.log(chalk.blue(`\n📋 Total: ${allRepos.length} repositories available\n`));Step 4: Apply Pattern Filter
import { filterRepositoriesByPattern } from '../../../src/cli/helpers/selection-strategy.js';
let filteredRepos = allRepos;
let patternDescription = 'all';
if (args.pattern) {
// Determine pattern type
const isRegex = args.pattern.startsWith('regex:');
const pattern = isRegex ? args.pattern.slice(6) : args.pattern;
const clonePattern = {
strategy: isRegex ? 'pattern-regex' : 'pattern-glob',
pattern: pattern,
isRegex
};
filteredRepos = filterRepositoriesByPattern(allRepos, clonePattern);
patternDescription = `matching "${pattern}"`;
console.log(chalk.gray(` Pattern: ${args.pattern}`));
console.log(chalk.gray(` Matched: ${filteredRepos.length} of ${allRepos.length} repos\n`));
} else {
// Prompt for pattern selection
const { select, input } = await import('@inquirer/prompts');
const strategy = await select({
message: 'How do you want to select repositories?',
choices: [
{ name: 'All - Clone all repositories', value: 'all' },
{ name: 'Pattern (glob) - e.g., "sw-*", "*-backend"', value: 'pattern-glob' },
{ name: 'Pattern (regex) - e.g., "^api-.*$"', value: 'pattern-regex' }
]
});
if (strategy !== 'all') {
const pattern = await input({
message: 'Enter pattern:',
validate: v => v.trim() ? true : 'Pattern required'
});
const clonePattern = {
strategy,
pattern: pattern.trim(),
isRegex: strategy === 'pattern-regex'
};
filteredRepos = filterRepositoriesByPattern(allRepos, clonePattern);
patternDescription = `matching "${pattern.trim()}"`;
}
}
if (filteredRepos.length === 0) {
console.log(chalk.yellow(`⚠️ No repositories ${patternDescription}.`));
return;
}Step 5: Preview and Confirm
console.log(chalk.blue(`\n📦 Repositories to clone (${filteredRepos.length}):\n`));
// Show preview (max 20)
filteredRepos.slice(0, 20).forEach(repo => {
console.log(chalk.gray(` • ${repo.name} (${repo.project})`));
});
if (filteredRepos.lengthRead more
description: Clone Azure DevOps repositories to local workspace. Use after init if cloning was skipped, or to add repos later.
Clone Azure DevOps Repositories Command
You are an Azure DevOps repository cloning expert. Help users clone repositories from ADO projects to their local workspace.
Purpose
This command clones Azure DevOps repositories **after** initial SpecWeave setup (`specweave init`). Use when:
- User skipped cloning during init
- Adding repositories from additional projects
- Re-cloning after cleanup
- Selective cloning with pattern filtering
Command Syntax
# Interactive mode (prompts for everything) sw-ado:clone-repos # With pattern filter sw-ado:clone-repos --pattern "sw-*" # Regex pattern sw-ado:clone-repos --pattern "regex:^api-.*$" # Specific project only sw-ado:clone-repos --project "MyProject" # Dry-run (preview only) sw-ado:clone-repos --dry-run
Your Task
When the user runs this command:
Step 1: Check Prerequisites
import { readEnvFile, parseEnvFile } from '../../../src/utils/env-file.js';
import chalk from 'chalk';
const projectPath = process.cwd();
const envContent = readEnvFile(projectPath);
if (!envContent) {
console.log(chalk.red('❌ No .env file found. Run `specweave init` first.'));
return;
}
const parsed = parseEnvFile(envContent);
if (!parsed.AZURE_DEVOPS_PAT || !parsed.AZURE_DEVOPS_ORG) {
console.log(chalk.red('❌ Missing Azure DevOps credentials.'));
console.log(chalk.gray(' Run `specweave init` with Azure DevOps provider.'));
return;
}
const org = parsed.AZURE_DEVOPS_ORG;
const pat = parsed.AZURE_DEVOPS_PAT;
console.log(chalk.blue('\n📦 ADO Repository Cloning\n'));
console.log(chalk.gray(` Organization: ${org}`));Step 2: Get Project Selection
import { AzureDevOpsProvider } from '../../../src/core/repo-structure/providers/azure-devops-provider.js';
const provider = new AzureDevOpsProvider();
// If project specified via CLI, use it
let selectedProjects: string[] = [];
if (args.project) {
selectedProjects = [args.project];
console.log(chalk.gray(` Project: ${args.project} (from CLI)`));
} else {
// Fetch available projects
console.log(chalk.gray('\n Fetching projects...'));
const response = await fetch(
`https://dev.azure.com/${org}/_apis/projects?api-version=7.0`,
{
headers: {
'Authorization': `Basic ${Buffer.from(':' + pat).toString('base64')}`,
'Accept': 'application/json'
}
}
);
if (!response.ok) {
console.log(chalk.red(`❌ Failed to fetch projects: ${response.status}`));
return;
}
const data = await response.json();
const projects = data.value || [];
if (projects.length === 0) {
console.log(chalk.yellow('⚠️ No projects found in organization.'));
return;
}
// Prompt for project selection
const { checkbox } = await import('@inquirer/prompts');
selectedProjects = await checkbox({
message: 'Select project(s) to clone repositories from:',
choices: projects.map(p => ({ name: p.name, value: p.name })),
required: true
});
console.log(chalk.green(` ✓ ${selectedProjects.length} project(s) selected`));
}Step 3: Fetch Repositories
const allRepos = [];
for (const project of selectedProjects) {
console.log(chalk.gray(`\n Fetching repos from ${project}...`));
try {
const repos = await provider.listRepositories(org, project, pat);
const reposWithProject = repos.map(r => ({ ...r, project }));
allRepos.push(...reposWithProject);
console.log(chalk.green(` ✓ Found ${repos.length} repositories`));
} catch (error) {
console.log(chalk.yellow(` ⚠️ Failed: ${error.message}`));
}
}
if (allRepos.length === 0) {
console.log(chalk.yellow('\n⚠️ No repositories found.'));
return;
}
console.log(chalk.blue(`\n📋 Total: ${allRepos.length} repositories available\n`));Step 4: Apply Pattern Filter
import { filterRepositoriesByPattern } from '../../../src/cli/helpers/selection-strategy.js';
let filteredRepos = allRepos;
let patternDescription = 'all';
if (args.pattern) {
// Determine pattern type
const isRegex = args.pattern.startsWith('regex:');
const pattern = isRegex ? args.pattern.slice(6) : args.pattern;
const clonePattern = {
strategy: isRegex ? 'pattern-regex' : 'pattern-glob',
pattern: pattern,
isRegex
};
filteredRepos = filterRepositoriesByPattern(allRepos, clonePattern);
patternDescription = `matching "${pattern}"`;
console.log(chalk.gray(` Pattern: ${args.pattern}`));
console.log(chalk.gray(` Matched: ${filteredRepos.length} of ${allRepos.length} repos\n`));
} else {
// Prompt for pattern selection
const { select, input } = await import('@inquirer/prompts');
const strategy = await select({
message: 'How do you want to select repositories?',
choices: [
{ name: 'All - Clone all repositories', value: 'all' },
{ name: 'Pattern (glob) - e.g., "sw-*", "*-backend"', value: 'pattern-glob' },
{ name: 'Pattern (regex) - e.g., "^api-.*$"', value: 'pattern-regex' }
]
});
if (strategy !== 'all') {
const pattern = await input({
message: 'Enter pattern:',
validate: v => v.trim() ? true : 'Pattern required'
});
const clonePattern = {
strategy,
pattern: pattern.trim(),
isRegex: strategy === 'pattern-regex'
};
filteredRepos = filterRepositoriesByPattern(allRepos, clonePattern);
patternDescription = `matching "${pattern.trim()}"`;
}
}
if (filteredRepos.length === 0) {
console.log(chalk.yellow(`⚠️ No repositories ${patternDescription}.`));
return;
}Step 5: Preview and Confirm
console.log(chalk.blue(`\n📦 Repositories to clone (${filteredRepos.length}):\n`));
// Show preview (max 20)
filteredRepos.slice(0, 20).forEach(repo => {
console.log(chalk.gray(` • ${repo.name} (${repo.project})`));
});
if (filteredRepos.lengthSpec-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-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 - /ado-import-projects
Import additional Azure DevOps projects post-init with area path mapping, filtering, and dry-run preview
Open command

