Skip to content
Build 6ff80cd

8. Dev Tooling & Claude Code Integrations

The integration stack lives across Jira (the work), Azure (Service Bus and the nonprod resources), Datadog (observability), and Postgres (OMS's local database). This page sets up the CLIs and connections that let Claude Code work across all four with you — read a ticket, inspect a dead-letter queue, query a trace, or run OMS locally, without leaving the terminal.

Install these once. Each step gives both the macOS and Windows path.

Package managers

Every install below uses the platform's package manager. On macOS that's Homebrew (brew); on Windows it's winget, which ships with Windows 11 and current Windows 10. Install Homebrew first if you don't have it; winget is already present on a modern Windows.

1. Connect Jira to Claude Code (REST API)

Rather than an MCP server, Claude Code talks to PopSockets' Jira Cloud through the REST API directly — reading tickets, creating issues, and adding comments without the per-turn token overhead of an MCP tool schema. Setup is a one-time scoped API token plus a local .env. You don't run the API by hand — once the credentials are in place, just ask Claude ("check my Jira connection", "show me CM-1234", "comment on this ticket") and it drives the REST calls for you.

Create a scoped API token

Generate one at id.atlassian.com/manage-profile/security/api-tokens. Use an API token with scopes — Atlassian's security recommendation — and grant just what Jira work needs:

Scope Purpose
read:jira-work Read issues, projects, comments, fields
write:jira-work Create/update issues, add comments, transitions

Scopes are fixed at creation

A token's scopes can't be changed after it's created — generate a new token to adjust them.

Find the Jira Cloud ID

A scoped token must be called through the api.atlassian.com gateway (see the gotcha below), and the gateway URL includes the cloud ID. While logged into Jira, open https://popsockets.atlassian.net/_edge/tenant_info in a browser tab — it returns the cloudId:

{"cloudId":"1234abcd-56ef-78gh-90ij-klmnopqrstuv"}

It needs a logged-in session, so open it in the browser.

Store credentials in .env

Create a .env in the project root:

JIRA_BASE_URL=https://popsockets.atlassian.net
JIRA_CLOUD_ID=your-cloud-id-here
JIRA_EMAIL=              # your own Atlassian account email — whoever is setting this up
JIRA_API_TOKEN=your-api-token-here

Before you save real values, make sure .env is git-ignored — ask Claude to add .env to .gitignore, confirm it's ignored, and untrack it if it was ever committed. Also commit a secret-free .env.example so teammates know which variables are required:

JIRA_BASE_URL=
JIRA_CLOUD_ID=
JIRA_EMAIL=
JIRA_API_TOKEN=

Load the file so the values are available in your shell (or let Claude read them from .env directly):

set -a; source .env; set +a
# PowerShell — load .env into the current session
Get-Content .env | Where-Object { $_ -match '=' -and $_ -notmatch '^\s*#' } | ForEach-Object {
  $name, $value = $_ -split '=', 2
  Set-Item -Path "env:$($name.Trim())" -Value $value.Trim()
}

Or load programmatically instead: require('dotenv').config() (Node), from dotenv import load_dotenv; load_dotenv() (Python).

Always use the gateway domain

Scoped token + Basic Auth → 401 on the direct domain

A scoped token returns 401 Unauthorized — Client must be authenticated to access this resource against the direct site domain (popsockets.atlassian.net/rest/api/3/...) even with a correct email and token — a known rough edge with Atlassian's scoped tokens. Always call the gateway domain, which is why the cloud ID matters:

https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/...

Point Claude at the api.atlassian.com/ex/jira/$JIRA_CLOUD_ID base for every Jira call.

Verify it's working

Don't script a check yourself — ask Claude to confirm the connection, e.g. "verify my Jira connection works." It calls /rest/api/3/myself on the gateway with the .env credentials; a 200 with your account details means the token is good. From there, Claude can search with JQL, fetch and create issues, and add comments — note that comment bodies use Atlassian Document Format (ADF), not plain strings, which Claude formats for you.

Keep the token out of Spring context

If .env lives inside a service directory like cm-ext-service-exp, cm-order-prc, or cm-osor-sys, make sure Spring Boot isn't also loading it. Spring doesn't read .env by default, but a spring-dotenv-style dependency could — keep the Jira token isolated from application context and logs, separate from Spring Cloud Config values.

2. Azure CLI

The az CLI is how Claude inspects the nonprod Azure Service Bus (int-nonprod-psb-1) — active backlogs and dead-letter counts across dev, qa, and stage — plus the rest of the integration resources.

brew update && brew install azure-cli

Requires macOS 13 or higher.

winget install -e --id Microsoft.AzureCLI

Close and reopen the terminal afterward so az lands on your PATH. If you can't use winget, the MSI installer from Microsoft Learn works too.

Then sign in with your PopSockets account:

# interactive browser flow
az login

# or, when no local browser is available (headless / remote box)
az login --use-device-code
# > To sign in, open https://microsoft.com/devicelogin and enter the code ...

# confirm the active subscription before touching any resource
az account show --query "{sub:name, id:id, tenant:tenantDefaultDomain, user:user.name}" -o table

Running az login from inside Claude Code

Interactive logins hang if Claude runs them for you. Instead, type the command yourself in the session prompt with a leading ! — e.g. ! az login --use-device-code — so the device code and sign-in output land directly in the conversation for Claude to use.

There is a single nonprod subscription and it's already the default, so no az account set is normally needed — but always verify with az account show before running a command against resources.

3. pup CLI (Datadog)

pup is Datadog's CLI companion — 200+ commands across logs, traces, metrics, monitors, and more. Claude uses it to pull observability data when you're diagnosing a flow. Auth is OAuth2 via a browser and tokens are short-lived (~1 hour).

Install

brew tap datadog-labs/pack
brew install pup

No Homebrew tap on Windows — build from source with the Rust toolchain (install rustup first), or grab a prebuilt binary from the releases page and add it to your PATH:

cargo install --git https://github.com/DataDog/pup

Verify with pup --version.

Log in

pup auth login     # OAuth2 browser flow
pup auth status    # check token validity
pup auth refresh   # refresh an expired token without re-opening the browser

If a pup command fails mid-session with a 401/403, the token has expired — run pup auth refresh (or pup auth login if refresh fails) and retry.

Add the pup skill to Claude Code

The skill teaches Claude how to drive pup correctly. Install it as a plugin from inside a Claude Code session:

/plugin marketplace add DataDog/pup
/plugin install     # pick the Datadog plugin, then follow the prompts

This is a one-time, cross-platform step (it only edits Claude Code config). After it's installed, ask Claude an observability question and it will reach for pup on its own.

4. PostgreSQL

OMS (the Rails order-management app) runs on Postgres, so you need a local server to run or point at it during onboarding work.

brew install postgresql@16
brew services start postgresql@16    # start now + on login

Prefer a GUI? Postgres.app is a drop-in alternative — download, drag to Applications, and click Initialize.

winget install -e --id PostgreSQL.PostgreSQL.16

The installer also offers pgAdmin (GUI) and sets up the postgres service to start automatically. If you skip winget, the EDB installer from postgresql.org is the standard alternative.

Confirm the server is reachable:

psql --version
psql -U postgres -c "SELECT version();"

You're set

With Jira wired into Claude, az/pup authenticated, and Postgres running locally, Claude Code can help across the whole loop — from the ticket, to the Service Bus queue behind it, to the trace, to the OMS record.