Skip to main content

Sync and search Azure DevOps work items and wiki pages for AI agents

Project description

ado-search

Sync and search Azure DevOps work items and wiki pages locally for AI agents.

Install

pip install ado-search

Or from source:

pip install git+https://github.com/HurleySk/ado-search.git

Quick Start

# Configure (requires az login first)
ado-search init --org https://dev.azure.com/yourorg --project YourProject

# Pull data
ado-search sync

# Search
ado-search search "login bug"
ado-search search "auth" --type Bug --state Active
ado-search search "setup guide" --format paths

How It Works

  1. Sync pulls work items and wiki pages from Azure DevOps
    • Tries OData analytics first (fetches all items in one call — fast)
    • Falls back to az devops CLI if analytics isn't available
  2. Data is stored as sorted JSONL files — git-friendly, diffable, one file per entity type
  3. A SQLite FTS5 index is derived from the JSONL and auto-rebuilt when stale
  4. Agents search the index, then use show to render full content — minimal context

Git-Friendly Storage

Sync produces two text files that are safe to commit, push, and pull:

  • work-items.jsonl — one JSON object per line, sorted by ID
  • wiki-pages.jsonl — one JSON object per line, sorted by path

The SQLite index (index.db) is .gitignored — it auto-rebuilds from JSONL on first search or show.

Synced Fields

Each work item includes: id, title, type, state, area, iteration, assigned_to, tags, priority, parent_id, created, updated, description, acceptance_criteria, story_points, state_history, attachments, and inline_images.

Story points are sourced from StoryPoints or Effort fields. State history tracks every state change (e.g., New → Active → Resolved → Closed) with date and author.

Attachments & Inline Images

When include_attachments = true in config, or --include-attachments is passed on the command line, sync/fetch downloads:

  • File attachments — stored in .ado-search/attachments/{work_item_id}/
  • Inline images — images embedded in Description/Acceptance Criteria HTML, stored in .ado-search/attachments/{work_item_id}/inline/

Attachment filenames are indexed and searchable. Inline images are referenced as [image: path] in text output so agents can locate them. Downloads are incremental — existing files with correct size are skipped on re-sync.

Note: attachments require the WIQL/REST sync path (OData doesn't include relations), so OData fast path is skipped when attachments are enabled.

Use --include-attachments on fetch or sync for per-invocation attachment downloads without changing config:

# Fetch specific items with their attachments
ado-search fetch 73541 --include-attachments

# One-time full sync with attachments
ado-search sync --include-attachments

Commands

Command Description
ado-search init Configure organization, project, and auth
ado-search sync Pull latest data from Azure DevOps (--full for complete re-fetch)
ado-search search "query" Full-text search with filters
ado-search show <id> Display full content of an item
ado-search create Create a new work item
ado-search update <id> Update an existing work item
ado-search add-comment <id> <text> Add a comment to a work item
ado-search add-link <source> <target> Add a link between two work items
ado-search list-links <id> List links on a work item (live)
ado-search list-comments <id> List comments on a work item (live)
ado-search grep "pattern" Regex search across work item fields
ado-search children <parent_id> List children (or full tree) of a work item

Create & Update

Create and update work items directly from the CLI:

# Create a new bug
ado-search create --type Bug --title "Login button broken" --state New --priority 1

# Create with description and tags
ado-search create --type "User Story" --title "Add dark mode" \
  --description "Users want a dark theme option" \
  --tags "ui; theme" --story-points 5

# Create a child task under a parent work item
ado-search create --type Task --title "Subtask" --parent 62434

# Update a work item
ado-search update 12345 --state Active --assigned-to "user@example.com"

# Close as duplicate (--reason sets Microsoft.VSTS.Common.ResolvedReason)
ado-search update 67154 --state Closed --reason Duplicate

# Set arbitrary ADO fields (including custom fields)
ado-search create --type Task --title "Research" --field "Custom.Effort=3"
ado-search update 12345 --field "System.AreaPath=Project\Team" --field "Custom.Sprint=Sprint 5"

# Preview without writing
ado-search create --type Bug --title "Test" --dry-run

HTML Content from Files

Description, acceptance criteria, and comment text accept HTML. For multi-line content, use the @file convention to read from a file:

# Set description from an HTML file
ado-search create --type Bug --title "Rendering issue" --description @bug-details.html

# Update acceptance criteria from a file
ado-search update 12345 --acceptance-criteria @criteria.html

# Add a comment from a file
ado-search add-comment 12345 @review-notes.html

# Inline HTML still works
ado-search add-comment 12345 "<p>Looks good!</p>"

# @mentions are auto-resolved to ADO identity links
ado-search add-comment 12345 "Great work @John.Smith, please review"

# Skip mention resolution (post raw text as-is)
ado-search add-comment 12345 "@not-a-user just a note" --no-mentions

# Escape a literal @ with @@
ado-search update 12345 --description "@@mention is not a file reference"

@DisplayName patterns in comment text are resolved via the ADO Identity Picker API and replaced with mention HTML so the mentioned user receives a notification.

After create/update/add-comment/add-link, the item is automatically re-fetched and merged into the local JSONL store so it appears in search immediately.

Links

# Add a parent link
ado-search add-link 12345 67890 --type parent

# Add a related link with a comment
ado-search add-link 12345 67891 --type related --comment "See also this item"

# Link types: related, parent, child, duplicate, duplicate-of, depends-on, predecessor, successor
ado-search add-link 12345 67892 --type depends-on

# Use a raw ADO relation type
ado-search add-link 12345 67893 --type "System.LinkTypes.Related"

# Preview without creating
ado-search add-link 12345 67890 --type child --dry-run

# List all links on a work item (live from ADO)
ado-search list-links 12345

# List all comments on a work item (live from ADO)
ado-search list-comments 12345

Configuration

Default sync includes Bug, User Story, Epic, and Feature work item types. To include Tasks or customize:

# .ado-search/config.toml
[sync]
work_item_types = ["Bug", "User Story", "Task", "Epic", "Feature"]
include_comments = false
include_attachments = false  # set to true to download file attachments and inline images

Auth Methods

  • az-cli (default): Uses az devops commands. Requires az login.
  • az-powershell: Uses Azure PowerShell + REST. Requires Connect-AzAccount.
  • pat: Uses a Personal Access Token via REST. For cross-cloud or service account scenarios.

Set via ado-search init --auth-method <method> or in config.toml.

# PAT example (token can also be set via ADO_PAT env var)
ado-search init --org https://dev.azure.com/yourorg --project YourProject --auth-method pat --pat <token>

Search Formats

ado-search search "query"                          # compact (default)
ado-search search "query" --format detail           # with description snippets
ado-search search "query" --format json             # machine-readable
ado-search search "query" --format paths            # file paths only (for agent piping)
ado-search search "query" --type Bug --state Active # filtered

Grep — Regex Pattern Matching

Search work items with regex patterns across fields:

# Find IP addresses anywhere in title/description/comments
ado-search grep '\d+\.\d+\.\d+\.\d+'

# Find "deprecated" only in comments, case-insensitive
ado-search grep -i 'deprecated' -f comments

# Find URL patterns in active bugs, brief output
ado-search grep 'https?://\S+' --type Bug --state Active --brief

# JSON output for scripting
ado-search grep 'TODO|FIXME' --format json

Default fields searched: title, description, comments. Use --field / -f to scope to specific fields (title, description, acceptance_criteria, comments, tags, assigned_to, area, iteration, state_history).

Metadata pre-filters (--type, --state, --area, --assigned-to, --tag) narrow candidates via SQLite indexes before the regex scan. Exit codes follow grep convention: 0 = matches found, 1 = no matches, 2 = error.

Children — Hierarchy Queries

Query work item parent-child hierarchy from local data:

# Show direct children of an epic
ado-search children 61123

# Full recursive tree (features, stories, tasks, ...)
ado-search children 61123 --recursive

# Indented tree view
ado-search children 61123 --recursive --format tree

# Filter to user stories only
ado-search children 61123 --recursive --type "User Story"

# Include closed date from state history
ado-search children 61123 --recursive --include-closed-date

# JSON for scripting
ado-search children 61123 --recursive --format json --include-closed-date

The children command queries the local SQLite index (no API calls). Use sync or fetch first to ensure data is current. Exit codes: 0 = children found, 1 = no children, 2 = parent not found.

Prerequisites

  • Python 3.10+
  • Azure CLI with azure-devops extension (az extension add --name azure-devops)
  • az login completed

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ado_search-1.9.0.tar.gz (64.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ado_search-1.9.0-py3-none-any.whl (47.8 kB view details)

Uploaded Python 3

File details

Details for the file ado_search-1.9.0.tar.gz.

File metadata

  • Download URL: ado_search-1.9.0.tar.gz
  • Upload date:
  • Size: 64.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ado_search-1.9.0.tar.gz
Algorithm Hash digest
SHA256 c9eda624bc7c1e6db5e96f5431fec36835285f062d2a883d8cd1bc70cc7debb0
MD5 9500b7c49dc6d6b01735a746e40c5e35
BLAKE2b-256 9bc62f4b8191c873a4555674014034f1dd976e60ea1c0e569cfd616f0a216651

See more details on using hashes here.

Provenance

The following attestation bundles were made for ado_search-1.9.0.tar.gz:

Publisher: publish.yml on HurleySk/ado-search

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ado_search-1.9.0-py3-none-any.whl.

File metadata

  • Download URL: ado_search-1.9.0-py3-none-any.whl
  • Upload date:
  • Size: 47.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ado_search-1.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9e256aa7f38ab28ea464bb86d6eb5264d5f272a95209fcc93a265fe749e440b
MD5 7df40c3992b1af6c9bc418ee31f078a2
BLAKE2b-256 a27c1935201fce078ee8f6566a06f241c55d5ac223059b0bc3005708c930cbc2

See more details on using hashes here.

Provenance

The following attestation bundles were made for ado_search-1.9.0-py3-none-any.whl:

Publisher: publish.yml on HurleySk/ado-search

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page