Description
A set of utility tools for DevOps, built around a dependency-free core that is exposed through several optional surfaces: a CLI, a Qt UI, a TUI, an MCP server, agent tools, and a Claude Code plugin.
Requires Python 3.12+.
Install
Recommended — no install at all. With uv,
uvx fetches the package (and the extra you name) into a cached, throwaway
environment per invocation:
uvx --from "devops-utils[azure]" devops-utils azdo list --project MyProject --mine
uvx --from "devops-utils[mcp]" devops-utils-mcp # MCP server
uvx --from "devops-utils[all]" devops-utils --help # every surface
The extra is not optional: azdo needs [azure], the MCP server needs
[mcp], and [all] covers everything. Pin it for reproducibility
("devops-utils[azure]==0.8.0"). Worth an alias if you use it often:
alias devops-utils='uvx --from "devops-utils[all]" devops-utils'
Or install it the usual way:
# core + CLI
pip install devops-utils
# with optional surfaces
pip install "devops-utils[mcp]" # MCP server
pip install "devops-utils[tui]" # Textual TUI
pip install "devops-utils[qt]" # PySide6 desktop UI
pip install "devops-utils[azure]" # Azure DevOps work-item tools
pip install "devops-utils[all]" # everything
# or as an isolated, always-on-PATH tool
uv tool install "devops-utils[all]"
For development this project uses uv:
uv sync --all-extras --dev
Usage
# Mask Secret values in a Kubernetes manifest, print to stdout
devops-utils sanitize manifest.yml -o -
# Write the sanitized manifest to a file
devops-utils sanitize manifest.yml -o manifest.sanitized.yml
Run the MCP server (requires the mcp extra):
devops-utils-mcp
# or, without installing:
uvx --from "devops-utils[mcp]" devops-utils-mcp
Azure DevOps work items
A small, LLM-friendly interface to Azure DevOps work items, working against both
Services (cloud) and Server (on-prem). Requires the azure extra.
Credentials are never read from the machine — supply a bearer token (or PAT) out-of-band via environment variables:
export AZURE_DEVOPS_ORG_URL="https://dev.azure.com/your-org" # or on-prem: https://server/tfs/DefaultCollection
export AZURE_DEVOPS_TOKEN="<bearer-token-or-pat>"
export AZURE_DEVOPS_AUTH_SCHEME="bearer" # or "pat" for a raw Personal Access Token
export AZURE_DEVOPS_API_VERSION="7.1" # lower for older on-prem servers
devops-utils azdo repos --project MyProject --name api
devops-utils azdo list --project MyProject --state Active --type Bug
devops-utils azdo list --project MyProject --mine --tag backend # @Me macro
devops-utils azdo list --project MyProject --iteration-path 'MyProject\Sprint 3'
devops-utils azdo search --project MyProject "login timeout"
devops-utils azdo get 42 --full # every raw field: description, dates, Custom.*
devops-utils azdo create --project MyProject --type Task --title "Fix flaky test" \
--area-path 'MyProject\Payments' --field Custom.RiskLevel=High
devops-utils azdo update 42 --state Closed --assigned-to dev@example.com
devops-utils azdo comment 42 "Investigating."
devops-utils azdo tag 42 backend urgent
devops-utils azdo link 42 --kind commit --project MyProject --repo MyRepo --value <sha>
devops-utils azdo attach 42 ./trace.log
Pipeline and repository research (read-only):
devops-utils azdo definitions --project MyProject --name 'CI*'
devops-utils azdo builds --project MyProject --branch main --result failed
devops-utils azdo timeline 1234 --project MyProject # stages/tasks + errors
devops-utils azdo logs 1234 --project MyProject # log ids + line counts
devops-utils azdo log 1234 7 --project MyProject --start-line 800 # tail
devops-utils azdo files --project MyProject --repo MyRepo --pattern '*.yml'
devops-utils azdo code-search "connection pool" --project MyProject
code-search uses the Search extension (always available on cloud; on-prem
needs it installed — files is the portable fallback).
Bulk operations: azdo apply
azdo apply creates and updates many work items from one declarative
plan file (YAML or JSON) — hierarchy, links, comments and all — with a
single review-and-confirm step instead of one prompt per command:
devops-utils azdo apply plan.yml # preview, confirm once, apply
devops-utils azdo apply plan.yml --dry-run # preview only, change nothing
devops-utils azdo apply plan.yml --yes --out results.json
cat plan.yml | devops-utils azdo apply - # read the plan from stdin
A plan is a project, optional defaults merged into every item, and an
ordered list of items. An item without id is a create; with id it is
an update. Later items can point at earlier ones with ref:<name>:
project: MyProject
defaults:
area_path: MyProject\Platform
fields: # any field by reference name, incl. Custom.*
Custom.Source: git-history
items:
- ref: feat # name other items can reference
type: Feature
title: Payment retries
state: Closed # applied after create (state machines allow it)
tags: [payments, backend]
- type: User Story
title: Retry failed captures
parent: ref:feat # parented under the feature created above
assigned_to: dev@example.com
links:
- {kind: commit, repo: MyRepo, value: 0a1b2c3d}
- {kind: hyperlink, value: "https://wiki/retries"}
comments: ["Imported from git history."]
- id: 42 # existing item -> update
state: Resolved
fields: {Custom.RiskLevel: Low}
The schema is deliberately loose: named keys cover the common fields, anything
else goes under fields: by reference name (unknown top-level keys produce a
warning in the preview, not an error). All of an item's links are sent in one
request; failures don't stop the run (dependents of a failed ref fail with a
clear message; use --stop-on-error to halt instead). Per-item results —
created / updated / failed / skipped plus the new ids — are printed as
JSON on stdout, and the exit code is non-zero if anything failed.
The same engine is exposed as the azdo_apply_plan MCP/agent tool, gated by
the usual human confirmation.
Results are JSON on stdout and nothing else — write commands send their preview
and confirmation prompt to stderr — so devops-utils azdo get 42 --full | jq
works. Output is UTF-8 whatever the shell's code page, so accented text needs no
chcp / PYTHONUTF8 preamble.
The same operations are exposed as MCP tools (azdo_*) and framework-agnostic
agent callables in devops_utils.agent.tools, all reading the env vars above.
Set up an agent
devops-utils setup installs the bundled skills and Claude Code subagents and
writes an Azure DevOps env scaffold. Defaults target Claude Code at user scope
(~/.claude). Registering the MCP server is opt-in (--with-mcp /
setup mcp) — the skills run every command through uvx, so most setups need
no server entry at all.
# Skills + agents + env scaffold, for the current user
devops-utils setup all
# same thing without installing:
uvx --from "devops-utils[all]" devops-utils setup all
# ... also registering the MCP server
devops-utils setup all --with-mcp
# Scope to the current repo (./.claude, ./.mcp.json)
devops-utils setup all --project
# Individual steps, or an arbitrary directory
devops-utils setup skills --dest ./agent-skills
devops-utils setup agents # ~/.claude/agents/*.md
devops-utils setup mcp --dest .
devops-utils setup env
setup mcp registers the zero-install uvx launcher by default — only uv
needs to be present:
{
"mcpServers": {
"devops-utils": {
"command": "uvx",
"args": ["--from", "devops-utils[mcp]", "devops-utils-mcp"],
"env": {}
}
}
}
Pass --no-uvx to register the bare devops-utils-mcp console script instead
(requires pip install "devops-utils[mcp]" so it is on PATH).
setup agents installs three read-only Azure DevOps research subagents
for Claude Code — azdo-workitem-analyst (pending items, assigned-to-me via
the WIQL @Me macro, type/tag filters), azdo-build-analyst (definitions,
run status, failure diagnosis via timeline + log tailing), and
azdo-repo-analyst (repo/file/code search). Writes stay with the main
assistant, gated by the MCP server's human confirmation.
Nothing is clobbered silently. When a target already exists, setup asks about it
one item at a time — y (overwrite), n (keep), a (overwrite all remaining),
q (stop asking and keep the rest), or d to see a diff of the bundled version
against yours first. Files identical to the bundled copy are reported as same
and never prompt.
$ devops-utils setup all
wrote ~/.claude/skills/azure-devops-research/SKILL.md
overwrite ~/.claude/agents/azdo-build-analyst.md? [y]es / [n]o / [a]ll / [q]uit / [d]iff: n
skip ~/.claude/agents/azdo-build-analyst.md (kept existing)
--force (or -y/--yes) answers yes to everything and prompts for nothing.
An answer of a/q during setup all carries across its remaining steps.
Unattended runs — no terminal, or DEVOPS_UTILS_SKIP_CONFIRMATION set — keep
every existing file and exit 0, so CI never blocks on a prompt or overwrites by
surprise; pass --force there if you do want a refresh.
setup mcp prompts before replacing an existing mcpServers.devops-utils
entry and merges into any existing config without clobbering other servers.
Use as a Claude Code plugin
The same skills and subagents also ship as a Claude Code plugin named
devops-utils, so Claude Code lists them under a distinguishing namespace —
devops-utils:azure-devops-research, devops-utils:azdo-workitem-analyst, and
so on — instead of bare, unqualified names. Install it from this repo's bundled
marketplace:
/plugin marketplace add carneirofc/devops-utils
/plugin install devops-utils@carneirofc
/reload-plugins
(carneirofc/devops-utils is GitHub shorthand; a local checkout path works too:
/plugin marketplace add /path/to/devops-utils.)
The plugin ships only the skills and agents. The bundled subagents call the
Azure DevOps MCP tools (mcp__devops-utils__azdo_*), so using them needs the
server registered — devops-utils setup mcp writes the uvx-launched entry
shown under Set up an agent. The skills themselves work without it (they
drive the devops-utils azdo CLI via uvx). MCP is intentionally not bundled in the plugin: a
plugin-scoped server would rename those tools and break the agents that call
them.
The committed plugin tree (plugins/devops-utils/, .claude-plugin/marketplace.json)
is generated from the bundled sources; re-run devops-utils setup plugin --force
after changing a skill or agent (a test enforces they stay in sync).
Use with mattpocock/skills
Skills like mattpocock/skills (triage,
wayfinder, to-tickets, …) read a repo-local config file,
docs/agents/issue-tracker.md, to learn how to talk to the issue tracker —
GitHub's gh CLI by default. To point them at Azure DevOps work items
via devops-utils instead, run in the target repo:
devops-utils setup tracker --project-name MyProject --done-state Closed
This writes docs/agents/issue-tracker.md and docs/agents/triage-labels.md
mapping every tracker operation (create, comment, labels→tags, close, claim,
blocking links, PR references) to devops-utils azdo / the azdo_* MCP tools.
--done-state is the state meaning "closed" in your process template
(Closed, Done, Resolved, …).
Author
Cláudio Ferreira Carneiro - carneirofc @ claudiofcarneiro@gmail.com
Licence
devops-utils is licensed under the MIT License. See LICENSE.
Metadata
Release files for devops-utils 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| devops_utils-0.10.0.tar.gz | 114.2 kB | Without provenance | Details for devops_utils-0.10.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| devops_utils-0.10.0-py3-none-any.whl | Python 3 | none | any | Details for devops_utils-0.10.0-py3-none-any.whl |
Total release size: 205.3 kB
Release files / devops_utils-0.10.0.tar.gz
| Download URL | devops_utils-0.10.0.tar.gz |
|---|---|
| Size | 114.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26d30146ff02a24f77e2210c3268b4bd2310c750229d9761c1415f10f03d77e3
|
|
BLAKE2b-256 checksum How to use checksums |
a2ba3cf67a1a7f77e5f502699ee999c549eb17bd3c7e45c82d6737cbc531acb0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / devops_utils-0.10.0-py3-none-any.whl
| Download URL | devops_utils-0.10.0-py3-none-any.whl |
|---|---|
| Size | 91.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a033ba62661d05e3e6a0711d2d7def7116beb1ac700501893c9921f19afc87a
|
|
BLAKE2b-256 checksum How to use checksums |
1fd758e2638f8bb461a4f94ac82789812791fadc7125a23312ce8f4c1909483d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for devops-utils 0.10.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.