Skip to content
Development
Command

/ado-import-projects

Import additional Azure DevOps projects post-init with area path mapping, filtering, and dry-run preview

From plugin
specweave
15673 skills20 agents73 commands
Install
> /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-import-projects

Context preview

What this command does when you run it.

Import additional Azure DevOps projects post-init with area path mapping, filtering, and dry-run preview

Command definition

ado-import-projects.md
description: Import additional Azure DevOps projects post-init with area path mapping, filtering, and dry-run preview

Import Azure DevOps Projects Command

You are an Azure DevOps project import expert. Help users add additional ADO projects to their SpecWeave workspace after initial setup.

Purpose

This command allows users to import additional Azure DevOps projects **after** initial SpecWeave setup (`specweave init`), with area path mapping, filtering, and dry-run preview.

**Use Cases**:

  • Adding new ADO projects to existing workspace
  • Importing projects from different organizations
  • Selective import with area path granularity
  • Multi-project organization (Backend, Frontend, Mobile, Infrastructure)

Command Syntax

# Basic import (interactive)
sw-ado:import-projects

# With area path granularity
sw-ado:import-projects --granularity two-level

# Dry-run (preview)
sw-ado:import-projects --dry-run

# Resume interrupted import
sw-ado:import-projects --resume

# Combined
sw-ado:import-projects --granularity top-level --dry-run

Your Task

When the user runs this command:

Step 1: Validate Prerequisites

import { readEnvFile, parseEnvFile } from '../../../src/utils/env-file.js';

// 1. Check if ADO credentials exist
const envContent = readEnvFile(process.cwd());
const parsed = parseEnvFile(envContent);

if (!parsed.AZURE_DEVOPS_PAT || !parsed.AZURE_DEVOPS_ORG) {
  console.log('โŒ Missing Azure DevOps credentials. Run `specweave init` first.');
  return;
}

// 2. Get existing configuration
const org = parsed.AZURE_DEVOPS_ORG;
const existingProject = parsed.AZURE_DEVOPS_PROJECT;

console.log(`\n๐Ÿ“‹ Organization: ${org}`);
console.log(`   Current project: ${existingProject || 'None'}\n`);

Step 2: Fetch Available Projects

import { getProjectCount } from '../../../src/cli/helpers/project-count-fetcher.js';
import { AsyncProjectLoader } from '../../../src/cli/helpers/async-project-loader.js';

// Count check (< 1 second)
const countResult = await getProjectCount({
  provider: 'ado',
  credentials: {
    organization: org,
    pat: parsed.AZURE_DEVOPS_PAT
  }
});

console.log(`โœ“ Found ${countResult.accessible} accessible project(s)`);

// Fetch all projects (with smart pagination)
const loader = new AsyncProjectLoader(
  {
    organization: org,
    pat: parsed.AZURE_DEVOPS_PAT
  },
  'ado',
  {
    batchSize: 50,
    updateFrequency: 5,
    showEta: true
  }
);

const result = await loader.fetchAllProjects(countResult.accessible);
const allProjects = result.projects;

Step 3: Area Path Mapping (Multi-Project Organization)

import { AreaPathMapper } from '../../../src/integrations/ado/area-path-mapper.js';

const { selectedProject } = await inquirer.prompt([{
  type: 'select',
  name: 'selectedProject',
  message: 'Select ADO project to import area paths from:',
  choices: allProjects.map(p => ({ name: p.name, value: p.name }))
}]);

const mapper = new AreaPathMapper({
  credentials: { organization: org, pat: parsed.AZURE_DEVOPS_PAT },
  project: selectedProject
});

// Fetch area path tree
const areaPathTree = await mapper.fetchAreaPaths();

// Get granularity suggestion
const suggestion = mapper.suggestGranularity(areaPathTree);
console.log(`\n๐Ÿ’ก Suggestion: ${suggestion.suggested}`);
console.log(`   ${suggestion.reasoning}\n`);

// Prompt for granularity (if not provided via CLI)
const granularity = args.granularity || await mapper.promptAreaPathGranularity(areaPathTree);

// Flatten area paths with selected granularity
const areaPaths = mapper.flattenAreaPaths(areaPathTree, granularity);

console.log(`\n๐Ÿ“Š ${areaPaths.length} project(s) will be created from area paths:\n`);
areaPaths.forEach(ap => {
  const projectId = mapper.mapToProjectId(ap.path);
  console.log(`   โœจ ${ap.path} โ†’ ${projectId}`);
});

Step 4: Dry-Run or Execute

if (args.dryRun) {
  console.log('\n๐Ÿ”Ž DRY RUN: No changes will be made.\n');
  console.log('The following projects would be configured:');
  areaPaths.forEach(ap => {
    const projectId = mapper.mapToProjectId(ap.path);
    console.log(`   โœจ ${projectId} (${ap.path})`);
  });
  console.log(`\nTotal: ${areaPaths.length} projects would be configured\n`);
  return;
}

// Confirm import
const { confirmed } = await inquirer.prompt([{
  type: 'confirm',
  name: 'confirmed',
  message: `Configure ${areaPaths.length} project(s) from area paths?`,
  default: true
}]);

if (!confirmed) {
  console.log('โญ๏ธ  Import cancelled.');
  return;
}

Step 5: Update Configuration

import { getConfigManager } from '../../../src/core/config/index.js';

const configManager = getConfigManager(process.cwd());

// Build area path configuration
const areaPathConfig: Record<string, string[]> = {};

for (const ap of areaPaths) {
  const projectId = mapper.mapToProjectId(ap.path);
  areaPathConfig[projectId] = [ap.path];
}

// Update configuration
await configManager.update({
  issueTracker: {
    provider: 'ado',
    ado: {
      organization: org,
      project: selectedProject,
      areaPathMapping: areaPathConfig,
      granularity
    }
  }
});

// Update .env file
import { updateEnvFile } from '../../../src/utils/env-manager.js';

await updateEnvFile('AZURE_DEVOPS_PROJECT', selectedProject);

// Write area paths to .env (comma-separated)
const areaPathList = areaPaths.map(ap => ap.path).join(',');
await updateEnvFile('AZURE_DEVOPS_AREA_PATHS', areaPathList);

console.log('\nโœ… Projects configured successfully!\n');
console.log(`Organization: ${org}`);
console.log(`Project: ${selectedProject}`);
console.log(`Granularity: ${granularity}`);
console.log(`\nArea paths configured:\n   ${areaPathList.split(',').join('\n   ')}\n`);

Step 6: Resume Support

if (args.resume) {
  const { CacheManager } = await import('../../../src/core/cache/cache-manager.js');
  const cacheManager = new CacheManager(process.cwd());

  const importState = await ca
Read more
Ships withspecweave

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.

Get the whole plugin