{"id":50688148,"url":"https://github.com/ralphmoran/ticket-lens","last_synced_at":"2026-06-09T00:33:27.916Z","repository":{"id":342732729,"uuid":"1172970258","full_name":"ralphmoran/ticket-lens","owner":"ralphmoran","description":"Privacy-first CLI that transforms Jira tickets into AI-ready briefs. 60–80% fewer tokens. No relay. Pipe-friendly.","archived":false,"fork":false,"pushed_at":"2026-06-08T22:46:59.000Z","size":1926,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T00:33:27.234Z","etag":null,"topics":["ai","atlassian","cli","context-window","developer-productivity","developer-tools","devtools","jira","jira-api","jira-server","llm","nodejs","prompt-engineering","token-optimization"],"latest_commit_sha":null,"homepage":"https://www.ticketlens.dev","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ralphmoran.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security/2026-03-30-compliance-threat-model.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-04T22:03:42.000Z","updated_at":"2026-06-08T22:47:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ralphmoran/ticket-lens","commit_stats":null,"previous_names":["ralphmoran/ticket-lens"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ralphmoran/ticket-lens","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphmoran%2Fticket-lens","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphmoran%2Fticket-lens/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphmoran%2Fticket-lens/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphmoran%2Fticket-lens/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ralphmoran","download_url":"https://codeload.github.com/ralphmoran/ticket-lens/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphmoran%2Fticket-lens/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34086664,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","atlassian","cli","context-window","developer-productivity","developer-tools","devtools","jira","jira-api","jira-server","llm","nodejs","prompt-engineering","token-optimization"],"created_at":"2026-06-09T00:33:27.786Z","updated_at":"2026-06-09T00:33:27.901Z","avatar_url":"https://github.com/ralphmoran.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# TicketLens\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/npm/v/ticketlens?style=flat-square\u0026color=6c63ff\u0026label=version\" /\u003e\n  \u003cimg src=\"https://img.shields.io/npm/dm/ticketlens?style=flat-square\u0026color=06b6d4\u0026label=downloads\" /\u003e\n  \u003cimg src=\"https://github.com/ralphmoran/ticket-lens/actions/workflows/test.yml/badge.svg?style=flat-square\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-green?style=flat-square\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat-square\" /\u003e\n\u003c/div\u003e\n\n\u003c/div\u003e\n\n\u003e Your AI assistant shouldn't need to read your tickets.\n\n\u003e Works alongside Atlassian MCP — Atlassian MCP writes the tickets; TicketLens tells you which ones need you right now.\n\n\u003cdiv align=\"center\"\u003e\u003cimg src=\"docs/demos/fetch.gif\" alt=\"ticketlens CNV1-2 demo\" width=\"700\" /\u003e\u003c/div\u003e\n\n---\n\n## What is TicketLens?\n\nTicketLens is a local-first Jira CLI that preprocesses ticket context on your machine and hands your AI tools a clean, compressed brief — instead of dumping raw Jira API JSON into your session. It supports Jira Cloud, Server, and Data Center, works with any AI tool that accepts text, and runs independently of any AI session.\n\nZero npm dependencies. Node.js built-ins only.\n\n---\n\n## Why TicketLens?\n\n- **Privacy** — ticket content never leaves your machine; no cloud relay, no data sent to Anthropic or anyone else\n- **60–80% token savings** — structured briefs instead of verbose Jira JSON; 4-hour cache by default\n- **Scriptable** — standard CLI output: pipe to cron, git hooks, CI/CD, or any LLM tool\n- **Multi-profile** — connect multiple Jira instances simultaneously; auto-route by ticket prefix or project path\n- **Attachments included** — images, PDFs, and text files downloaded locally; Claude Code reads them as context\n- **Confluence pages** — linked Confluence pages fetched and included in the brief automatically (Jira only)\n\n---\n\n## Quick Start\n\n```bash\nnpm install -g ticketlens\nticketlens init          # Guided setup: Jira, GitHub Issues, or Linear — connection test included\nticketlens CNV1-2        # Fetch a ticket brief\nticketlens triage        # Scan your assigned tickets\n```\n\nOr without installing:\n\n```bash\nnpx ticketlens init\nnpx ticketlens CNV1-2\n```\n\n**Prerequisites:** Node.js \u003e=20\n\n---\n\n## Demos\n\n\u003cdiv align=\"center\"\u003e\u003cimg src=\"docs/demos/triage.gif\" alt=\"ticketlens triage demo\" width=\"700\" /\u003e\u003c/div\u003e\n\n---\n\n## Commands\n\n### Setup\n\n| Command | Description |\n|---------|-------------|\n| `ticketlens init` | Guided wizard — Jira, GitHub Issues, or Linear — live connection test, optional settings |\n| `ticketlens switch` | Arrow-key panel to switch between configured profiles |\n| `ticketlens config [--profile=NAME]` | Edit any field on an existing profile — always re-validates the connection |\n| `ticketlens profiles` | List all configured profiles (alias: `ticketlens ls`) |\n| `ticketlens delete \u003cNAME\u003e` | Remove a profile and its credentials (prompts `y/N` in TTY; use `--yes` in scripts/CI) |\n\n`init` collects: profile name, tracker type (Jira / GitHub Issues / Linear), URL or workspace, credentials (masked), and optional ticket prefixes, project paths, and triage statuses. On connection failure, a retry menu lets you fix credentials, URL, or skip — all inputs pre-populated. `config` is tracker-aware and always re-validates the connection after edits.\n\n`config` uses merge semantics: new ticket prefixes and triage statuses are added to existing lists, never replaced. Partial matching resolves `QA` to `QA Testing` if that's the status in your Jira.\n\n---\n\n### Fetch a ticket\n\n```bash\nticketlens CNV1-2                  # Depth 1, styled output (default)\nticketlens get CNV1-2              # Same — explicit alias\nticketlens CNV1-2 --depth=0        # Target ticket only\nticketlens CNV1-2 --depth=1        # + linked ticket descriptions and comments\nticketlens CNV1-2 --depth=2        # + linked-of-linked (full graph)\nticketlens CNV1-2 --plain          # Plain markdown — pipe-safe, LLM-ready\nticketlens CNV1-2 --profile=acme   # Force a specific profile\nticketlens CNV1-2 --no-cache       # Bypass cache, re-fetch from Jira\nticketlens CNV1-2 --no-attachments # Skip attachment download and Confluence page fetching\nticketlens CNV1-2 --check          # Append local VCS diff + Claude Code review instructions\nticketlens CNV1-2 --compliance     # Check ticket requirements against local diff [Pro/Free 3/mo]\nticketlens CNV1-2 --summarize                  # AI summary via your own API key (BYOK) [Pro]\nticketlens CNV1-2 --summarize --provider=groq  # Force a specific AI provider [Pro]\nticketlens CNV1-2 --summarize --cloud          # AI summary routed through TicketLens API [Pro]\nticketlens CNV1-2 --handoff                    # AI handoff brief from comment thread (BYOK) [Pro]\nticketlens CNV1-2 --handoff --cloud            # AI handoff brief via TicketLens API [Pro]\nticketlens CNV1-2 --template=quick             # Apply a brief template (full|quick|code-review, or custom [Team])\n```\n\n| `--depth` | Scope |\n|-----------|-------|\n| `0` | Target ticket: description, comments, attachments, Confluence pages |\n| `1` | + linked tickets: descriptions and comments _(default)_ |\n| `2` | + linked-of-linked: key and summary only |\n\nMax 15 tickets at any depth. Circular references handled automatically.\n\nAfter the first fetch, ticket data is cached to `~/.ticketlens/cache/PROFILE/TICKET-KEY/brief.json` (4h TTL, depth-aware). A dim notice appears on stderr on cache hit:\n\n```\n  ○ CNV1-2 · from cache (12m ago)  ·  --no-cache to refresh\n```\n\nAttachments download to `~/.ticketlens/cache/TICKET-KEY/` (10 MB per-file cap). Claude Code reads images multimodally, extracts PDF text, and reads plain text files as context.\n\nConfluence pages linked to the ticket via Jira Remote Links are fetched automatically and included as plain text in the brief (Jira profiles only, same-origin). Use `--no-attachments` to skip both attachments and Confluence pages.\n\n---\n\n### Brief Templates\n\nControl which sections appear in a brief without changing the default output for everyone else.\n\n```bash\nticketlens CNV1-2 --template=quick              # Meta + 2 comments only\nticketlens CNV1-2 --template=code-review        # Meta + description + linked + code refs\nticketlens CNV1-2 --template=full               # All sections (same as default)\nticketlens CNV1-2 --template=my-team-template   # Custom team template [Team]\n```\n\nThree system templates ship out of the box:\n\n| Slug | Sections | Best for |\n|------|----------|---------|\n| `full` | Everything (default) | LLM context, deep planning |\n| `quick` | Meta + 2 comments | Standup, daily triage |\n| `code-review` | Meta + description + linked + code refs | PR review |\n\n**Custom templates [Team]** — create your own in the Console under **Admin → Brief Templates**. Pick which sections appear and cap comment count. The slug you set is what you pass to `--template=`.\n\n---\n\n### Triage\n\n```bash\nticketlens triage                               # Scan assigned tickets — interactive\nticketlens triage --profile=acme               # Explicit profile\nticketlens triage --stale=3                    # Aging threshold: 3 days (default: 5)\nticketlens triage --status=\"Code Review,QA\"    # Override statuses to scan\nticketlens triage --assignee=\"Jane Dev\"        # Another dev's tickets [Team]\nticketlens triage --sprint=\"Sprint 12\"         # Filter by sprint [Team]\nticketlens triage --project=MYPROJ             # Scope to a Jira project key [Team]\nticketlens triage --label=Bug,P1               # Filter by label(s) [Team]\nticketlens triage --priority=High              # Filter by priority level [Team]\nticketlens triage --export=csv                 # Export results to CSV [Team]\nticketlens triage --export=json                # Export results to JSON [Team]\nticketlens triage --push                       # Push snapshot to Console queue [Team]\nticketlens triage --share                      # Generate 24h share URL (no login for recipient) [Team]\nticketlens triage --all                        # Triage all profiles at once, merged output [Pro]\nticketlens triage --save=~/triage.txt          # Save ANSI-stripped output to file [Pro]\nticketlens triage --digest                     # POST scored results to digest endpoint [Pro]\nticketlens triage --plain                      # Plain markdown — pipe to file or LLM\nticketlens triage --static                     # Static table, no interactive mode\n```\n\n| Badge | Category | Condition |\n|-------|----------|-----------|\n| `●` red | Needs response | Someone else commented within the last N days |\n| `●` yellow | Aging | Last comment or update is N+ days old |\n\n`--stale=N` controls both categories. Unanswered comments older than N days downgrade from \"needs response\" to \"aging\" automatically.\n\nInteractive mode: `↑/↓` navigate, `Enter` open in browser, `p` switch profile, `q/Esc` exit. Columns adapt to terminal width.\n\nStatus mismatch auto-fix: if configured statuses don't match Jira's exact casing, triage shows a diff and offers to update your profile:\n\n```\n  ~ In progress  →  In Progress\n  ~ QA           →  QA Testing\n\n  Update \"myteam\" with corrected statuses?  y/N\n```\n\nBot comments (Jira Automation, Jenkins, GitHub Actions) are automatically ignored.\n\n---\n\n### Collisions\n\n```bash\nticketlens collisions                         # Show branches that overlap with teammates [Team]\nticketlens collisions --json                  # Machine-readable output\nticketlens collisions --plain                 # Plain text, no ANSI colour\n```\n\nRequires a Team license and at least one teammate in your group. Compares your current git branch's changed files against your teammates' recent branches (within 7 days). Reports each overlap as a collision: your branch, their branch, the shared files, and linked ticket keys.\n\n```\n[1] feat/auth-refactor ↔ Jane Dev (feat/login-redesign)\n    Your tickets:  PROJ-101\n    Their tickets: PROJ-88\n    Shared files:  src/auth/LoginController.php, src/auth/guards.php\n```\n\nBranches are captured automatically when you run `ticketlens triage --push`. No extra step required.\n\n---\n\n### Review\n\n```bash\nticketlens review                             # Assemble PR review context from current branch\nticketlens review --branch=main              # Compare against main (auto-detected by default)\nticketlens review --branch=develop           # Compare against a specific branch\nticketlens review --base=main                # Alias for --branch\nticketlens review --profile=acme             # Use a specific profile for ticket fetching\nticketlens review --branch=main | pbcopy     # Copy brief to clipboard\nticketlens review --branch=main | llm \"What changed and why?\"\nticketlens review --help                     # Review subcommand help\n```\n\nExtracts linked ticket keys from the branch name and commit messages, fetches each ticket via the configured profile, then assembles a structured brief: branch, changed files, and ticket context. On TTY, output is ANSI-styled with colored section headers, file paths, and coverage percentages.\n\n`--branch=BRANCH` (or `--base=BRANCH`) sets the comparison base. Defaults to auto-detecting `main`, `master`, or `develop`.\n\nFlag validation provides actionable hints:\n\n```\n✖ Unknown flag: --branch-main\n  Did you mean --branch=main?\n```\n\n---\n\n### Compliance\n\n```bash\nticketlens compliance \u003cTICKET-KEY\u003e                # Check ticket requirements against local diff [Pro/Free 3/mo]\nticketlens compliance \u003cTICKET-KEY\u003e --profile=acme # Specify a profile\nticketlens compliance \u003cTICKET-KEY\u003e --plain        # Plain markdown output\n```\n\nRuns the same compliance check as `ticketlens CNV1-2 --compliance` but as a dedicated subcommand — useful when you want to check compliance without fetching the full ticket brief. Free accounts get 3 checks per month; Pro is unlimited.\n\n---\n\n### Compliance Ledger\n\n```bash\nticketlens ledger                             # View the local compliance audit ledger [Pro]\nticketlens ledger --plain                     # Plain markdown output\n```\n\nDisplays the append-only local ledger of all compliance checks run on this machine. Useful for SOC 2 / HIPAA audit trails. Requires a Pro license.\n\n---\n\n### Git Hook\n\n```bash\nticketlens install-hooks                      # Install pre-push compliance gate [Pro]\nticketlens install-hooks --uninstall          # Remove installed hooks\n```\n\nInstalls a `pre-push` git hook that runs `ticketlens compliance` on every push. Blocks the push if compliance coverage falls below the configured threshold. Requires a Pro license.\n\n---\n\n### PR Description\n\n```bash\nticketlens pr \u003cTICKET-KEY\u003e                    # Generate PR description from ticket [Pro]\nticketlens pr \u003cTICKET-KEY\u003e --profile=acme    # Specify a profile\nticketlens pr \u003cTICKET-KEY\u003e --plain           # Plain markdown output\nticketlens pr \u003cTICKET-KEY\u003e | pbcopy          # Copy to clipboard\n```\n\nGenerates a PR description template pre-filled with the ticket summary, acceptance criteria, and compliance coverage. Requires a Pro license.\n\n---\n\n### Standup\n\n```bash\nticketlens standup                            # Standup summary for the last 24 hours\nticketlens standup --since=48                 # Last 48 hours\nticketlens standup --since=yesterday          # Git date string\nticketlens standup --format=pr               # PR body format: \"What changed\" + commit list\nticketlens standup --profile=myteam          # Enrich with ticket summaries from Jira\nticketlens standup --plain                   # Plain markdown (no ANSI colour)\nticketlens standup --plain | pbcopy          # Copy standup to clipboard\nticketlens standup --help                    # Standup subcommand help\n```\n\nScans `git log` for the configured window, extracts ticket keys from commit messages, and groups commits by ticket. Optionally fetches ticket summaries from your Jira profile to add context. Outputs a dated standup brief or a PR body depending on `--format`.\n\n**`--format=standup` (default)**\n```\n## Standup — Mon, May 18, 2026\n\n### Commits by ticket\n\n**PROJ-123** — Fix payment validation (2 commits)\n  abc1234 feat: PROJ-123 add payment validation check\n  def5678 test: PROJ-123 payment validation tests\n\n[No ticket key] (1 commit)\n  jkl3456 chore: bump deps\n```\n\n**`--format=pr`** — paste directly into a GitHub/GitLab PR description\n```\n## What changed\n\n- **PROJ-123** — Fix payment validation\n\n## Commits (3)\n\n- `abc1234` feat: PROJ-123 add payment validation check\n- `def5678` test: PROJ-123 payment validation tests\n- `jkl3456` chore: bump deps\n```\n\nWhen no commits reference a ticket key, `## What changed` shows `_No ticket references found in commits._` instead of a blank section.\n\n---\n\n### Cache\n\n```bash\nticketlens cache size                          # Disk usage by profile and ticket\nticketlens cache size --profile=acme           # Filter to one profile\nticketlens cache clear                         # Interactive picker (TTY)\nticketlens clear                               # Alias for cache clear\nticketlens cache clear CNV1-2                  # Clear one ticket\nticketlens cache clear --older-than=7d         # Files older than 7 days\nticketlens cache clear --profile=acme          # One profile's files only\nticketlens cache clear --older-than=30d --yes  # Skip confirmation (CI/scripts)\n```\n\nAge units: `d` = days · `m` = months (30d) · `y` = years (365d)\n\nCache locations:\n- Attachments: `~/.ticketlens/cache/TICKET-KEY/`\n- Briefs: `~/.ticketlens/cache/PROFILE/TICKET-KEY/brief.json`\n\n---\n\n### Schedule\n\n```bash\nticketlens schedule               # Interactive wizard — set digest time, timezone, profile [Pro]\nticketlens schedule --stop        # Cancel the scheduled digest\nticketlens schedule --status      # Show current schedule\nticketlens schedule --local       # Local-only cron (no Console auth) — saves triage to file [Pro]\n```\n\nStores the schedule as a cron entry. Delivers your triage digest at the configured time without an open terminal. Requires a Pro license.\n\n---\n\n### History\n\n```bash\nticketlens history \u003cTICKET-KEY\u003e   # Show urgency timeline for a ticket [Pro]\n```\n\nReads from your local `~/.ticketlens/triage-history/` snapshots (written automatically on each `ticketlens triage` run) and renders a day-by-day urgency timeline for the requested ticket. Entries where urgency changed direction are flagged as \"bounced\" — useful for spotting tickets that keep reverting between Code Review and In Progress.\n\nRequires a Pro license. No network call — reads local snapshots only.\n\n---\n\n### Response-Time Stats\n\n```bash\nticketlens stats                         # Personal metrics from local triage history\nticketlens stats --profile=acme          # Metrics for a specific profile\nticketlens stats --days=14               # Extend lookback window [Pro, max 30]\nticketlens stats --format=json           # JSON output for scripting\nticketlens stats --format=json | jq '.avgResponseHours'\n```\n\nShows avg/median response time, clear rate (resolved within 24h), triage run count, and week-over-week trend — all computed from local `~/.ticketlens/triage-history/` snapshots. No network call.\n\n- **Free**: last 7 days (fixed)\n- **Pro**: `--days=N` up to 30 days\n\nA one-line summary footer is also appended automatically to `ticketlens triage` output once you have 2 or more triage runs:\n\n```\n── This week: avg 3.2h response · 80% cleared within 24h (5 runs) ──\n```\n\n---\n\n### Custom Attention Rules\n\nAdd an `attentionRules` array to any profile in `~/.ticketlens/profiles.json` to override how `ticketlens triage` scores specific tickets:\n\n```json\n{\n  \"profiles\": {\n    \"work\": {\n      \"baseUrl\": \"https://jira.example.com\",\n      \"attentionRules\": [\n        { \"match\": { \"priority\": \"Highest\" }, \"action\": \"force-urgent\", \"reason\": \"P1 always urgent\" },\n        { \"match\": { \"label\": \"backlog\" },    \"action\": \"ignore\",       \"reason\": \"skip backlog\" },\n        { \"match\": { \"status\": \"Parked\" },    \"action\": \"ignore\",       \"reason\": \"parked tickets\" }\n      ]\n    }\n  }\n}\n```\n\nRules are evaluated in order — first match wins. Supported `match` keys: `priority`, `label`, `status`, `keyPrefix`. Supported `action` values: `force-urgent` (bumps to needs-response) and `ignore` (excludes from output). Requires a Pro license.\n\n---\n\n### Login\n\n```bash\nticketlens login           # Open browser → authorize in Console → token saved automatically\nticketlens login --manual  # Paste a token instead (CI/headless environments)\nticketlens logout          # Revoke and remove the stored CLI token\nticketlens sync            # Pull your latest tracker profiles from the Console\n```\n\n`ticketlens login` opens the TicketLens Console in your default browser. Click **Authorize**, and the CLI receives your token via a one-shot localhost callback — no copy-pasting. Cancelling in the browser exits the CLI cleanly.\n\nUse `--manual` when there is no GUI (CI runners, SSH sessions, containers).\n\n`ticketlens logout` removes the stored Console auth token and disconnects this machine from your TicketLens account. Local Jira profiles and credentials are kept intact — re-run `ticketlens login` to reconnect.\n\n`ticketlens sync` pulls any tracker profiles you have configured in the Console and writes them locally, keeping your CLI in sync with your team settings without re-running `init`.\n\n\u003e **Console features** — `ticketlens triage --push`, `--share`, `ticketlens collisions`, and `ticketlens schedule` all require an active Console session. Run `ticketlens login` once and the token is stored automatically.\n\n---\n\n### License\n\n```bash\nticketlens license                # Show tier and status\nticketlens activate \u003cKEY\u003e         # Activate a Pro or Team license\n```\n\n---\n\n### Update Skill\n\n```bash\nticketlens update-skill                          # Sync /jtb skill to all detected AI assistants\nticketlens update-skill --dry-run                # Preview what would be updated (no writes)\nticketlens update-skill --path=~/.gemini/commands  # Sync to a specific assistant directory\nticketlens update-skill --quiet                  # Suppress output (useful in scripts)\n```\n\nCopies the latest `SKILL.md` to every AI assistant command directory where `/jtb` is already installed. Runs automatically on `npm install -g ticketlens` — for most users, upgrading the CLI is enough. Use `--dry-run` to confirm what would change before writing.\n\nSupported assistants detected automatically:\n- Claude Code — `~/.claude/commands/jtb.md`\n- Claude Code (work) — `~/.claude-work/commands/jtb.md`\n- Gemini CLI — `~/.gemini/commands/jtb.md`\n- Copilot CLI — `~/.copilot-cli/commands/jtb.md`\n\n---\n\n### /jtb — Jira TicketBrief for Claude Code\n\n`/jtb` is a Claude Code slash command that fetches full ticket context and drops a structured implementation brief directly into your session, then enters plan mode.\n\n\u003e Requires [Claude Code](https://claude.ai/code). For standalone use, the `ticketlens` commands above work independently.\n\n**Install:**\n\n```bash\nnpm install -g ticketlens \u0026\u0026 ticketlens init\nticketlens update-skill        # copies /jtb skill into ~/.claude/commands/jtb.md\n# Restart Claude Code, then:\n# /jtb CNV1-2\n```\n\n**Keeping the skill up to date:**\n\n```bash\nnpm install -g ticketlens@latest   # update the CLI\nticketlens update-skill            # sync the /jtb skill to the new version\n```\n\n`update-skill` runs automatically on `npm install -g`, so for most users the second step is handled. If you manage Claude Code across multiple machines or accounts, run it manually after updating.\n\n```bash\nticketlens update-skill --dry-run         # preview what would change\nticketlens update-skill --path=~/.gemini/commands  # sync to a different AI assistant\n```\n\n**Usage in Claude Code:**\n\n```\n/jtb CNV1-2                         # Fetch ticket + linked issues → plan mode\n/jtb CNV1-2 --depth=0               # Target ticket only (fast)\n/jtb CNV1-2 --depth=2               # Deep: full linked-issue graph\n/jtb CNV1-2 --profile=acme          # Force a specific profile\n/jtb CNV1-2 --no-attachments        # Skip attachment download\n/jtb CNV1-2 --no-cache              # Re-fetch from Jira\n/jtb CNV1-2 --template=quick        # Apply quick template (meta + 2 comments)\n/jtb CNV1-2 --template=code-review  # Apply code-review template\n/jtb CNV1-2 --template=my-slug      # Apply a custom team template [Team]\n/jtb triage                         # Scan your assigned tickets\n```\n\nAttachments are listed in the brief as absolute paths. Claude Code reads images (multimodal), PDFs, and text files before planning. Files over 10 MB are skipped.\n\n---\n\n## All Examples\n\n```bash\n# ── Setup ────────────────────────────────────────────────────────────────────\nticketlens init                               # Guided wizard (recommended)\nticketlens switch                             # Switch between configured profiles\nticketlens config                             # Edit the active profile\nticketlens config --profile=acme             # Edit a specific profile\nticketlens config set aiProvider groq        # Set default AI provider (groq|openai|anthropic)\nticketlens profiles                           # List all configured profiles\nticketlens ls                                 # Alias for profiles\nticketlens profiles --plain                   # Tab-separated (scripts / pipes)\nticketlens delete \u003cPROFILE-NAME\u003e              # Remove a profile (prompts y/N in TTY)\nticketlens delete \u003cPROFILE-NAME\u003e --yes        # Remove without prompt (scripts/CI)\n\n# ── Fetch a ticket brief ──────────────────────────────────────────────────────\nticketlens CNV1-2                            # Fetch with defaults (depth 1, styled)\nticketlens get CNV1-2                        # Explicit alias (same result)\nticketlens CNV1-2 --depth=0                  # Target ticket only — no linked issues\nticketlens CNV1-2 --depth=1                  # + linked ticket descriptions and comments\nticketlens CNV1-2 --depth=2                  # + linked-of-linked (full graph)\nticketlens CNV1-2 --profile=acme             # Force a specific Jira profile\nticketlens CNV1-2 --plain                    # Plain markdown — no color codes\nticketlens CNV1-2 --styled                   # Force ANSI color even when piping\nticketlens CNV1-2 --no-attachments           # Skip attachment download entirely\nticketlens CNV1-2 --no-cache                 # Skip brief cache + force re-download\nticketlens CNV1-2 --check                    # Append local VCS diff + Claude Code review instructions\nticketlens CNV1-2 --compliance               # Check ticket requirements against local diff [Pro/Free 3/mo]\nticketlens CNV1-2 --summarize                   # AI summary via your own API key (BYOK) [Pro]\nticketlens CNV1-2 --summarize --provider=groq   # Force Groq (Llama 3.1, free tier) [Pro]\nticketlens CNV1-2 --summarize --cloud           # AI summary via TicketLens API [Pro]\nticketlens CNV1-2 --handoff                     # AI handoff brief from comment thread (BYOK) [Pro]\nticketlens CNV1-2 --handoff --cloud             # AI handoff brief via TicketLens API [Pro]\nticketlens CNV1-2 --template=quick              # Apply quick template (meta + 2 comments only)\nticketlens CNV1-2 --template=code-review        # Apply code-review template (meta + desc + linked + code refs)\nticketlens CNV1-2 --template=full               # Apply full template (all sections, default)\nticketlens CNV1-2 --template=my-team-template   # Apply a custom team template [Team]\nticketlens CNV1-2 --depth=2 --profile=acme --plain   # Combine flags freely\n\n# Pipe plain output to clipboard, LLM, or file\nticketlens CNV1-2 --plain \u003e brief.md\nticketlens CNV1-2 --plain | pbcopy\nticketlens CNV1-2 --plain | llm \"Summarize this ticket in 3 bullets\"\n\n# ── Triage ────────────────────────────────────────────────────────────────────\nticketlens triage                             # Scan assigned tickets — interactive\nticketlens triage --profile=acme             # Explicit profile\nticketlens triage --stale=3                  # Needs-response window: 3 days (default: 5)\nticketlens triage --stale=10                 # More lenient — only flag very stale tickets\nticketlens triage --status=\"Code Review,QA Testing\"  # Scan these statuses only\nticketlens triage --static                   # Static table output (no interactive mode)\nticketlens triage --plain                    # Plain markdown — pipe to LLM or file\nticketlens triage --assignee=\"Jane Dev\"      # View another dev's tickets [Team]\nticketlens triage --sprint=\"Sprint 12\"       # Filter by sprint name [Team]\nticketlens triage --project=MYPROJ           # Scope to a Jira project key [Team]\nticketlens triage --label=Bug,P1             # Filter by label(s) [Team]\nticketlens triage --priority=High            # Filter by priority level [Team]\nticketlens triage --project=MYPROJ --label=Bug --priority=High  # Combined [Team]\nticketlens triage --assignee=\"Jane Dev\" --sprint=\"Sprint 12\"  # Combined [Team]\nticketlens triage --export=csv               # Export to CSV [Team]\nticketlens triage --export=json              # Export to JSON [Team]\nticketlens triage --push                     # Push snapshot to Console queue [Team]\nticketlens triage --share                    # Generate 24h share URL (no login for recipient) [Team]\nticketlens triage --all                      # Triage all profiles at once, merged output [Pro]\nticketlens triage --save=~/triage.txt        # Save ANSI-stripped output to file [Pro]\nticketlens triage --digest                   # POST results to digest endpoint [Pro]\nticketlens triage --profile=acme --stale=3 --static          # Combine flags\n\n# Pipe triage output\nticketlens triage --plain \u003e my-tickets.md\nticketlens triage --plain | llm \"Which ticket is most urgent and why?\"\n\n# ── Collisions ────────────────────────────────────────────────────────────────\nticketlens collisions                         # Show branch collisions with teammates [Team]\nticketlens collisions --json                  # Machine-readable JSON output\nticketlens collisions --plain                 # Plain text, no ANSI colour\n\n# ── PR Review ─────────────────────────────────────────────────────────────────\nticketlens review                             # Assemble PR review context from current branch\nticketlens review --branch=main              # Compare against main (auto-detected by default)\nticketlens review --branch=develop           # Compare against a specific branch\nticketlens review --base=main                # Alias for --branch\nticketlens review --profile=acme             # Use a specific profile for ticket fetching\nticketlens review --branch=main | pbcopy     # Copy brief to clipboard\nticketlens review --branch=main --profile=myteam  # Branch + profile combined\nticketlens review --help                     # Review subcommand help\n\n# ── Standup ───────────────────────────────────────────────────────────────────\nticketlens standup                            # Standup summary for last 24 hours\nticketlens standup --since=48                 # Last 48 hours\nticketlens standup --since=yesterday          # Git date string\nticketlens standup --format=pr               # PR body: \"What changed\" + commit list\nticketlens standup --profile=myteam          # Enrich with Jira ticket summaries\nticketlens standup --plain | pbcopy          # Copy to clipboard\nticketlens standup --help                    # Standup subcommand help\n\n# ── Cache management ──────────────────────────────────────────────────────────\nticketlens cache                              # Overview + subcommand hints\nticketlens cache --help                       # Detailed help\nticketlens cache size                         # Disk usage by profile and ticket\nticketlens cache size --profile=acme          # Filter to one profile only\nticketlens cache clear                        # Interactive picker (TTY)\nticketlens clear                              # Alias for cache clear\nticketlens cache clear CNV1-2                # Clear one ticket's cache\nticketlens cache clear --older-than=7d        # Files older than 7 days\nticketlens cache clear --older-than=1m        # Files older than 1 month\nticketlens cache clear --older-than=1y        # Files older than 1 year\nticketlens cache clear --profile=acme         # Only one profile's files\nticketlens cache clear CNV1-2 --older-than=7d            # Ticket + age filter\nticketlens cache clear --profile=acme --older-than=30d   # Profile + age filter\nticketlens cache clear --older-than=30d --yes            # Skip confirmation (CI/scripts)\n\n# ── Schedule ─────────────────────────────────────────────────────────────────\nticketlens schedule                           # Interactive wizard — set time, timezone, profile [Pro]\nticketlens schedule --stop                    # Cancel the scheduled digest [Pro]\nticketlens schedule --status                  # Show current schedule [Pro]\nticketlens schedule --local                   # Local-only cron/LaunchAgent — no Console auth needed [Pro]\n\n# ── History ───────────────────────────────────────────────────────────────────\nticketlens history \u003cTICKET-KEY\u003e               # Show urgency timeline for a ticket [Pro]\n\n# ── Stats ──────────────────────────────────────────────────────────────────────\nticketlens stats                              # Response-time metrics from local history\nticketlens stats --profile=acme              # Metrics for a specific profile\nticketlens stats --days=14                   # Extend lookback window (Pro, max 30)\nticketlens stats --format=json               # JSON output for scripting\n\n# ── Compliance ────────────────────────────────────────────────────────────────\nticketlens compliance \u003cTICKET-KEY\u003e            # Check ticket requirements against local diff [Pro/Free 3/mo]\nticketlens ledger                             # View local compliance audit ledger [Pro]\nticketlens install-hooks                      # Install pre-push compliance gate [Pro]\nticketlens install-hooks --uninstall          # Remove installed hooks [Pro]\n\n# ── PR Description ─────────────────────────────────────────────────────────────\nticketlens pr \u003cTICKET-KEY\u003e                    # Generate PR description from ticket [Pro]\nticketlens pr \u003cTICKET-KEY\u003e | pbcopy          # Copy to clipboard [Pro]\n\n# ── AI provider keys (BYOK) ───────────────────────────────────────────────────\nticketlens cloud-keys list                            # List configured AI providers\nticketlens cloud-keys add groq gsk_xxxx               # Add Groq key (free tier)\nticketlens cloud-keys add anthropic sk-ant-xxxx       # Add Anthropic key\nticketlens cloud-keys add openai sk-xxxx              # Add OpenAI key\nticketlens cloud-keys add groq gsk_xxxx --timeout=10  # Add with custom timeout\nticketlens cloud-keys test groq                       # Test a provider key\nticketlens cloud-keys remove groq                     # Remove a provider\nticketlens cloud-keys priority groq 1                 # Set provider priority\nticketlens cloud-keys timeout anthropic 15            # Set per-request timeout\nticketlens cloud-keys --help                          # Subcommand help\n\n# ── Login ─────────────────────────────────────────────────────────────────────\nticketlens login                              # Browser flow — opens Console, token saved automatically\nticketlens login --manual                     # Paste flow — for CI/headless environments\nticketlens logout                             # Revoke and remove stored CLI token\nticketlens sync                               # Pull tracker profiles from the Console\n\n# ── License and account ────────────────────────────────────────────────────────\nticketlens license                            # Show license tier and status\nticketlens activate \u003cLICENSE-KEY\u003e             # Activate a license key\n\n# ── Skill maintenance ─────────────────────────────────────────────────────────\nticketlens update-skill                       # Sync /jtb skill to all detected AI assistants\nticketlens update-skill --dry-run             # Preview what would be updated\nticketlens update-skill --path=~/.gemini/commands  # Sync to a custom assistant directory\n\n# ── Help and version ──────────────────────────────────────────────────────────\nticketlens --help                             # Main help\nticketlens --version                          # Show installed version\nticketlens CNV1-2 --help                     # Fetch subcommand help\nticketlens triage --help                      # Triage subcommand help\nticketlens review --help                      # Review subcommand help\nticketlens cache --help                       # Cache overview help\nticketlens cache size --help                  # Cache size help\nticketlens cache clear --help                 # Cache clear help\n```\n\n---\n\n## Pro \u0026 Teams Features\n\nStart free, upgrade when you need it — `ticketlens activate \u003ckey\u003e`\n\n### Pro — $9/mo\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/demos/pro-triage.gif\" alt=\"ticketlens --summarize AI summary demo\" width=\"700\" /\u003e\n\u003c/div\u003e\n\n```bash\nticketlens CNV1-2 --summarize            # AI summary via your own API key (BYOK)\nticketlens CNV1-2 --summarize --cloud    # AI summary via TicketLens API (no local key needed)\nticketlens CNV1-2 --handoff              # AI handoff brief from the ticket's comment thread (BYOK)\nticketlens CNV1-2 --handoff --cloud      # AI handoff brief via TicketLens API\nticketlens CNV1-2 --compliance           # Check ticket requirements against local diff [Pro/Free 3/mo]\nticketlens triage --stale=3              # Custom stale threshold (default is 5)\nticketlens triage --digest               # POST scored triage results to digest endpoint\nticketlens schedule                      # Set up a scheduled daily digest\nticketlens activate YOUR-LICENSE-KEY     # Activate Pro license\n```\n\n**`--summarize`** generates a 3-sentence AI summary of the ticket. The AI receives the full ticket context: description, comments, linked Confluence pages, and any text-readable attachments. The summary is cached alongside the brief (same 4h TTL) — repeat runs return instantly from cache. Use `--no-cache` to force a fresh AI call.\n\n**`--handoff`** synthesizes the ticket into a structured one-pager for the developer picking up the work. The AI receives the same full context and returns:\n\n- **What was attempted** — concrete work already done\n- **Current blockers** — unresolved issues\n- **Open questions** — decisions not yet made\n- **Recommendation** — where to start\n\n**What the AI can read:**\n\n| Content | Included |\n|---|---|\n| Description | ✅ Always |\n| Comments | ✅ Always |\n| Linked Confluence pages | ✅ Jira only, same-origin |\n| Text files (`.txt`, `.md`, `.log`, `.csv`, `.json`, `.yaml`, etc.) | ✅ Up to 4 KB per file, 12 KB total |\n| Screenshots (`.png`, `.jpg`, `.gif`, etc.) | ❌ Binary — images require multimodal API |\n| PDFs | ❌ Binary — no parser included (zero-dependency) |\n| Office documents (`.docx`, `.xlsx`) | ❌ Binary — no parser included |\n\nAdd your AI provider keys once via `cloud-keys` — they're stored encrypted on your account and used automatically:\n\n```bash\nticketlens cloud-keys add groq gsk_xxxx          # Groq (Llama 3.x — free tier)\nticketlens cloud-keys add anthropic sk-ant-xxxx  # Anthropic Claude\nticketlens cloud-keys add openai sk-xxxx         # OpenAI GPT-4o mini\nticketlens cloud-keys list                       # See configured providers\nticketlens cloud-keys test groq                  # Verify a key works\nticketlens cloud-keys remove groq                # Remove a provider\n```\n\nOr use `--cloud` to route through the TicketLens API without managing keys yourself.\n\n| Provider | Cost | Sign up |\n|---|---|---|\n| Groq (Llama 3.x) | **Free tier** | [console.groq.com](https://console.groq.com) |\n| Anthropic (Claude) | Paid | console.anthropic.com |\n| OpenAI (GPT-4o mini) | Paid | platform.openai.com |\n\n**Provider priority:** Providers are tried in the order you configure them. To set a default fallback order:\n\n```bash\nticketlens cloud-keys priority groq 1        # try Groq first\nticketlens cloud-keys priority anthropic 2   # Anthropic second\n```\n\nOverride per-command with `--provider=`:\n\n```bash\nticketlens CNV1-2 --summarize --provider=groq\nticketlens CNV1-2 --handoff --provider=openai\n```\n\nOr manage keys in **Console → Admin → AI Settings**.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/demos/pro-triage.gif\" alt=\"ticketlens triage --stale=3 demo\" width=\"700\" /\u003e\n\u003c/div\u003e\n\nPro also unlocks configurable brief cache TTL per profile — set `cacheTtl` to `4h`, `1d`, `7d`, `30d`, or `0` (disable) via `ticketlens config`. Free tier is fixed at 4h.\n\n### Team — $19/seat/mo\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/demos/teams-digest.gif\" alt=\"ticketlens triage --plain digest pipeline demo\" width=\"700\" /\u003e\n\u003c/div\u003e\n\n```bash\nticketlens triage --assignee=\"Jane Dev\"        # View another dev's tickets\nticketlens triage --sprint=\"Sprint 12\"         # Filter by sprint name\nticketlens triage --project=MYPROJ             # Scope to a Jira project key\nticketlens triage --label=Bug,P1               # Filter by label(s)\nticketlens triage --priority=High              # Filter by priority level\nticketlens triage --export=csv                 # Export triage to CSV for standups and reports\nticketlens triage --export=json                # Machine-readable export for dashboards\nticketlens triage --push                       # Push snapshot to the Console queue\nticketlens triage --share                      # Generate a 24h share URL — paste into Slack, no login needed for recipients\n```\n\n`--push` syncs the scored snapshot to the TicketLens Console after each triage run. The queue page at `/console/queue` shows the latest snapshot for every team profile — no manual refresh needed.\n\n`--share` generates a signed URL valid for 24 hours. Recipients open it in any browser — no account, no install. The asymmetry is the product: you run one command, everyone sees the same snapshot.\n\nAutomate a morning digest with cron — no open terminal required:\n\n```bash\n0 9 * * 1-5 ticketlens triage --plain \u003e ~/digest-$(date +%F).md\n```\n\nMulti-profile team workflows: each teammate runs `ticketlens init` with their own credentials; shared `ticketPrefixes` auto-route tickets to the right Jira instance.\n\n---\n\n## Multi-Profile Setup\n\nProfiles live in `~/.ticketlens/profiles.json`:\n\n```json\n{\n  \"profiles\": {\n    \"myteam\": {\n      \"baseUrl\": \"https://myteam.atlassian.net\",\n      \"auth\": \"cloud\",\n      \"email\": \"you@myteam.com\",\n      \"ticketPrefixes\": [\"PROJ\", \"OPS\"],\n      \"projectPaths\": [\"~/projects/myteam-app\"],\n      \"triageStatuses\": [\"In Progress\", \"Code Review\", \"QA Testing\"]\n    },\n    \"client\": {\n      \"baseUrl\": \"https://jira.client.com\",\n      \"auth\": \"server\",\n      \"email\": \"yourname\",\n      \"ticketPrefixes\": [\"ACME\", \"SHOP\"],\n      \"projectPaths\": [\"~/projects/client-app\"],\n      \"triageStatuses\": [\"In Progress\", \"In Development\", \"QA\"]\n    }\n  }\n}\n```\n\nCredentials in `~/.ticketlens/credentials.json` (chmod 600):\n\n```json\n{\n  \"myteam\": { \"apiToken\": \"your-atlassian-api-token\" },\n  \"client\":  { \"pat\": \"your-jira-server-pat\" }\n}\n```\n\n**Profile resolution order:**\n\n| Priority | Method | Example |\n|----------|--------|---------|\n| 1 | `--profile=NAME` flag | `ticketlens CNV1-2 --profile=client` |\n| 2 | Ticket prefix match | `ticketlens CNV1-2` → prefix `PROJ` → `myteam` |\n| 3 | Project path match | `triage` in `~/projects/myteam-app` → `myteam` |\n| 4 | `config.default` field | Explicit default set via `ticketlens switch` |\n| 5 | First profile in file | Fallback when `config.default` is absent |\n| 6 | Environment variables | `JIRA_BASE_URL`, `JIRA_EMAIL`, `JIRA_API_TOKEN` / `JIRA_PAT` |\n\n---\n\n## Running Tests\n\n```bash\nnpm test\n```\n\n---\n\n## Roadmap\n\nSee [ROADMAP.md](ROADMAP.md) for the full plan.\n\nRecently shipped:\n- **Collision detection** (`ticketlens collisions`) — shows which files your branch shares with teammates' in-flight branches; `--push` auto-sends git branch data to the team snapshot. Team tier\n- **Shareable triage snapshot** (`ticketlens triage --share`) — generates a 24h signed URL; recipients open it in any browser, no account needed. Team tier\n- **Compliance push** (`ticketlens triage --push`) — enriches the team snapshot with per-ticket compliance status and coverage from the local ledger. Pro tier\n- **\"TicketLens for PRs\"** (`ticketlens review`) — assembles a code-review context brief from your current branch: linked tickets, changed files, and ticket context in one brief\n- **Confluence pages** — linked Confluence pages fetched automatically and included in the brief; origin-validated, non-fatal, capped at 10 pages\n- **Linear support** — `ticketlens init` → Linear; connects via GraphQL API key, fetches tickets, triage, and statuses\n- **GitHub Issues support** — `ticketlens init` → GitHub Issues; PAT-based, same normalized ticket shape\n\n---\n\n## Contributing\n\nBug reports and feature requests welcome — open an issue on [GitHub](https://github.com/ralphmoran/ticket-lens/issues). For larger changes, open an issue first to discuss.\n\n---\n\n## License\n\n[MIT](LICENSE) © Ralph Moran\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fralphmoran%2Fticket-lens","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fralphmoran%2Fticket-lens","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fralphmoran%2Fticket-lens/lists"}