Skip to main content

Read and write Azure Boards work items with first-class Markdown support

Project description

abwi

CI Go Report Card npm PyPI

English | 日本語 | 한국어

A CLI for reading and writing Azure Boards work items with first-class Markdown support — what az boards makes hard, abwi makes the default.

Why

  • Azure Boards supports native Markdown in large text fields, but az devops cannot write it: setting a field's format requires an extra multilineFieldsFormat entry in the JSON Patch document, which the Azure CLI never sends. abwi adds it automatically, so Description, Repro Steps, Acceptance Criteria, and friends land as real Markdown — not HTML-escaped text.
  • Every multiline field is addressed generically with -f <refname>=<value>, with curl-style input: @file reads a file, @- reads stdin, and a leading \@ escapes a literal @. No per-field flags to memorize.

[!WARNING] Switching a field to Markdown is irreversible per work item — once a field on a given work item stores Markdown, Azure DevOps does not allow converting it back to HTML. This is an Azure DevOps limitation, not an abwi one. If your organization or process is not ready for Markdown, use the --format html fallback.

Install

via npm

npm install -g @abwi/cli
abwi --help

via PyPI

pip install abwi
abwi --help

via GitHub Releases

Download the binary for your platform from Releases.

via Go

go install github.com/lohn/abwi/cmd/abwi@latest

Authentication

Entra ID (default). Sign in once with the Azure CLI; abwi picks up the Azure CLI credential automatically:

az login

PAT (explicit opt-in, not recommended). Set auth = "pat" in the global config file (or pass --auth pat) and export the token as ABWI_PAT (falling back to AZURE_DEVOPS_EXT_PAT, the variable the Azure CLI uses):

export ABWI_PAT=...          # or AZURE_DEVOPS_EXT_PAT
abwi --auth pat show 123

PAT values are read only from environment variables, never from config files, so a token can't end up committed by accident.

The auth key is honored only in the global config file — a checked-out repository must not be able to switch your authentication mode, so auth in a repo-local .abwi.toml is ignored with a warning.

Configuration

abwi merges configuration from two TOML files:

  • Local: .abwi.toml, found by walking up from the current directory (put it at your repository root)
  • Global: the per-user config directory — ~/.config/abwi/config.toml on Linux (Go's os.UserConfigDir, so ~/Library/Application Support/abwi/config.toml on macOS and %AppData%\abwi\config.toml on Windows)

Precedence, highest first: flags > environment (ABWI_ORG, ABWI_PROJECT) > local file > global file.

# .abwi.toml — committed at the repository root
org = "https://dev.azure.com/myorg"
project = "MyProject"
default-type = "Product Backlog Item"

# Shorthand names for -f, expanded to full field reference names
[aliases]
ac = "Microsoft.VSTS.Common.AcceptanceCriteria"
repro = "Microsoft.VSTS.TCM.ReproSteps"

Available keys:

Key Description Default
org Organization URL (https://dev.azure.com/<org>)
project Project name
format Large text format: markdown / html markdown
auth Authentication: entra / patglobal config only entra
default-type Work item type used when create --type is omitted
[aliases] Table of shorthand names for -f, expanded to full reference names

Run abwi config to see the resolved values and where each one came from — see Usage below.

Usage

Create a work item (--type falls back to default-type from the config; -d/-f values support @file and @-):

abwi create -T Bug -t "Crash when saving a draft" \
  -d @description.md \
  -f Microsoft.VSTS.TCM.ReproSteps=@repro.md

# The same, using the [aliases] shorthand from the config
abwi create -T Bug -t "Crash when saving a draft" -d @description.md -f repro=@repro.md

Update fields of an existing work item (Markdown from stdin via @-; use \@ when a value must start with a literal @):

generate-criteria | abwi update 123 -s Active -f ac=@- \
  -f System.Description='\@mentions start with an escaped at-sign'

Show a work item (--json for the raw response):

abwi show 123

List work items — yours by default, most recently changed first; filter with flags or take over with a full WIQL query:

abwi list -T Bug -s Active --limit 20
abwi list --all                            # everyone's, not just yours
abwi list --assignee "someone@example.com" # someone else's
abwi list --wiql @query.wiql               # full control

Comments (posted as Markdown by default):

abwi comment add 123 "Reproduced on \`main\`; see #456."
abwi comment add 123 @-        # comment body from stdin
abwi comment list 123

Link and unlink (--type: parent, child, related — the default — or a full System.LinkTypes.* reference name):

abwi link 123 456 --type parent   # make #456 the parent of #123
abwi unlink 123 456               # --type disambiguates multiple links

Show the resolved configuration, each value annotated with its origin (flag, env, local, global, or default):

$ abwi config
# global: /home/you/.config/abwi/config.toml
# local:  /home/you/src/myrepo/.abwi.toml
org = "https://dev.azure.com/myorg"  # local
project = "MyProject"  # env
format = "markdown"  # default
auth = "entra"  # default
default-type = "Product Backlog Item"  # local

[aliases]
ac = "Microsoft.VSTS.Common.AcceptanceCriteria"
repro = "Microsoft.VSTS.TCM.ReproSteps"

abwi config <key> prints a single value; --json prints the whole thing as JSON.

The --format html fallback

If your organization does not support Markdown work items yet (or you want to avoid the irreversible switch), pass --format html or set format = "html" in the config. You still write Markdown — abwi converts it to HTML via goldmark before sending, and the fields stay in HTML format:

abwi create -T Bug -t "Crash when saving a draft" --format html -d @description.md

License

MIT © lohn

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

abwi-0.1.0-py3-none-win_arm64.whl (3.8 MB view details)

Uploaded Python 3Windows ARM64

abwi-0.1.0-py3-none-win_amd64.whl (4.3 MB view details)

Uploaded Python 3Windows x86-64

abwi-0.1.0-py3-none-manylinux_2_17_x86_64.whl (4.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

abwi-0.1.0-py3-none-manylinux_2_17_aarch64.whl (3.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

abwi-0.1.0-py3-none-macosx_11_0_arm64.whl (3.9 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

abwi-0.1.0-py3-none-macosx_10_9_x86_64.whl (4.2 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file abwi-0.1.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: abwi-0.1.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 3.8 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for abwi-0.1.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 85a47c6026f988c5fb80a9833e0061e034b6931ac233a84874178d9a47c49b99
MD5 31584436fad6398ab2e23fe8638e9eb2
BLAKE2b-256 84f33f596b5ff5dac4382444e1acecec99d2e5af0892f8eba428f3ec00bcc6a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for abwi-0.1.0-py3-none-win_arm64.whl:

Publisher: release.yaml on lohn/abwi

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

File details

Details for the file abwi-0.1.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: abwi-0.1.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for abwi-0.1.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 b3ad6a1f8e5ba2bcb77b9b2d80176387105c47a1cc502cb19f1319c5a1ab0006
MD5 1fdc574c1f80096e7f0307013c6eb251
BLAKE2b-256 e0a0cc8a4bbe2d3c35ccef623844485c32a46875f2b982a6f01800caab681a84

See more details on using hashes here.

Provenance

The following attestation bundles were made for abwi-0.1.0-py3-none-win_amd64.whl:

Publisher: release.yaml on lohn/abwi

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

File details

Details for the file abwi-0.1.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: abwi-0.1.0-py3-none-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 4.2 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for abwi-0.1.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 96e2ae9fc995503a8e355881ac970fae855c2c49c69ad90057d55c42cda27a40
MD5 91bae87dee86a99ea1e893b971205e56
BLAKE2b-256 37fc17c0e0a4b1f1a0681fae4c4c6ec1f112c2442255f6b23d047e2ce0513e5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for abwi-0.1.0-py3-none-manylinux_2_17_x86_64.whl:

Publisher: release.yaml on lohn/abwi

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

File details

Details for the file abwi-0.1.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for abwi-0.1.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 8420905beec401e1f53becc54902280ef5925a3028cfd43360883bb2f64ef516
MD5 b3db63114022e827e251d16b4c80efdd
BLAKE2b-256 67aa8ee819ee5591e0175c534f7ba6d1e88aad0486f169e4c5e087432cdb6f7d

See more details on using hashes here.

Provenance

The following attestation bundles were made for abwi-0.1.0-py3-none-manylinux_2_17_aarch64.whl:

Publisher: release.yaml on lohn/abwi

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

File details

Details for the file abwi-0.1.0-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: abwi-0.1.0-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 3.9 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for abwi-0.1.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e61e6d17d65ba75bb2f57070540dfe8970c9a92c9b7db4b922d12992daacf9c3
MD5 5cf338b69a3fb77d2917ad887fb4777a
BLAKE2b-256 53df5a57364cc2ade18a0f28d568e54010871a227e883011023111263fecf99a

See more details on using hashes here.

Provenance

The following attestation bundles were made for abwi-0.1.0-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yaml on lohn/abwi

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

File details

Details for the file abwi-0.1.0-py3-none-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: abwi-0.1.0-py3-none-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 4.2 MB
  • Tags: Python 3, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for abwi-0.1.0-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 06d7639f42fef89a9bae63006fcdb9c1153cc610df90203e09426653843ddd40
MD5 64db3e3404bcb8acac5699809550ffdb
BLAKE2b-256 d6aa23408faa3b829e801ac3232253c8fbfdd2945314a2f04cf1663c9a82e388

See more details on using hashes here.

Provenance

The following attestation bundles were made for abwi-0.1.0-py3-none-macosx_10_9_x86_64.whl:

Publisher: release.yaml on lohn/abwi

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