ticketlens 0.38.8 → 0.38.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -20,6 +20,47 @@
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
+
## Contents
|
|
24
|
+
|
|
25
|
+
- [What is TicketLens?](#what-is-ticketlens)
|
|
26
|
+
- [Why TicketLens?](#why-ticketlens)
|
|
27
|
+
- [Quick Start](#quick-start)
|
|
28
|
+
- [Demos](#demos)
|
|
29
|
+
- [Commands](#commands)
|
|
30
|
+
- [Setup](#setup)
|
|
31
|
+
- [Fetch a ticket](#fetch-a-ticket)
|
|
32
|
+
- [Brief Templates](#brief-templates)
|
|
33
|
+
- [Triage](#triage)
|
|
34
|
+
- [Collisions](#collisions)
|
|
35
|
+
- [Review](#review)
|
|
36
|
+
- [Compliance](#compliance)
|
|
37
|
+
- [Compliance Ledger](#compliance-ledger)
|
|
38
|
+
- [Git Hook](#git-hook)
|
|
39
|
+
- [PR Description](#pr-description)
|
|
40
|
+
- [Standup](#standup)
|
|
41
|
+
- [Cache](#cache)
|
|
42
|
+
- [Schedule](#schedule)
|
|
43
|
+
- [History](#history)
|
|
44
|
+
- [Recall](#recall)
|
|
45
|
+
- [Comment, Transition, Assign, Duplicates, Link, Update & Create](#comment-transition-assign-duplicates-link-update--create)
|
|
46
|
+
- [Response-Time Stats](#response-time-stats)
|
|
47
|
+
- [Custom Attention Rules](#custom-attention-rules)
|
|
48
|
+
- [Login](#login)
|
|
49
|
+
- [License](#license)
|
|
50
|
+
- [Update Skill](#update-skill)
|
|
51
|
+
- [/jtb — Jira TicketBrief for Claude Code](#jtb--jira-ticketbrief-for-claude-code)
|
|
52
|
+
- [All Examples](#all-examples)
|
|
53
|
+
- [Pro & Teams Features](#pro--teams-features)
|
|
54
|
+
- [Pro — $9/mo](#pro--9mo)
|
|
55
|
+
- [Team — $19/seat/mo](#team--19seatmo)
|
|
56
|
+
- [Multi-Profile Setup](#multi-profile-setup)
|
|
57
|
+
- [Running Tests](#running-tests)
|
|
58
|
+
- [Roadmap](#roadmap)
|
|
59
|
+
- [Contributing](#contributing)
|
|
60
|
+
- [License](#license-1)
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
23
64
|
## What is TicketLens?
|
|
24
65
|
|
|
25
66
|
TicketLens 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.
|
|
@@ -271,24 +312,24 @@ Displays the append-only local ledger of all compliance checks run on this machi
|
|
|
271
312
|
### Git Hook
|
|
272
313
|
|
|
273
314
|
```bash
|
|
274
|
-
ticketlens install-hooks # Install pre-push compliance gate
|
|
315
|
+
ticketlens install-hooks # Install pre-push compliance gate
|
|
275
316
|
ticketlens install-hooks --uninstall # Remove installed hooks
|
|
276
317
|
```
|
|
277
318
|
|
|
278
|
-
Installs a `pre-push` git hook that runs `ticketlens compliance` on every push. Blocks the push if compliance coverage falls below the configured threshold.
|
|
319
|
+
Installs a `pre-push` git hook that runs `ticketlens compliance` on every push. Blocks the push if compliance coverage falls below the configured threshold. Free — the hook itself needs no license; the `compliance` check it runs follows its own free (3/month) or Pro (unlimited) limit.
|
|
279
320
|
|
|
280
321
|
---
|
|
281
322
|
|
|
282
323
|
### PR Description
|
|
283
324
|
|
|
284
325
|
```bash
|
|
285
|
-
ticketlens pr <TICKET-KEY> # Generate PR description from ticket
|
|
326
|
+
ticketlens pr <TICKET-KEY> # Generate PR description from ticket
|
|
286
327
|
ticketlens pr <TICKET-KEY> --profile=acme # Specify a profile
|
|
287
328
|
ticketlens pr <TICKET-KEY> --plain # Plain markdown output
|
|
288
329
|
ticketlens pr <TICKET-KEY> | pbcopy # Copy to clipboard
|
|
289
330
|
```
|
|
290
331
|
|
|
291
|
-
Generates a PR description template pre-filled with the ticket summary, acceptance criteria, and compliance coverage.
|
|
332
|
+
Generates a PR description template pre-filled with the ticket summary, acceptance criteria, and compliance coverage. Free — the compliance coverage section follows the `compliance` command's own free (3/month) or Pro (unlimited) limit.
|
|
292
333
|
|
|
293
334
|
---
|
|
294
335
|
|
|
@@ -425,6 +466,7 @@ Every note is scanned before saving — anything shaped like a real secret (API
|
|
|
425
466
|
|
|
426
467
|
```bash
|
|
427
468
|
ticketlens comment PROJ-123 --body="Looks good, merging." # Post a comment to the tracker
|
|
469
|
+
ticketlens comment PROJ-123 --body="See screenshot" --attach=./bug.png # Attach local files
|
|
428
470
|
ticketlens transition PROJ-123 # List valid transitions (read-only)
|
|
429
471
|
ticketlens transition PROJ-123 --target="Done" --confirm # Execute the transition
|
|
430
472
|
ticketlens assign PROJ-123 --to=me # Assign the ticket to yourself
|
|
@@ -435,6 +477,7 @@ ticketlens update PROJ-123 --title="Fix login on mobile" # Update title/de
|
|
|
435
477
|
ticketlens update PROJ-123 --add-labels=urgent,backend --remove-labels=stale
|
|
436
478
|
ticketlens create --project=PROJ --type="Task" --summary="Fix login on mobile" # Create a new ticket
|
|
437
479
|
ticketlens create --project=ENG --summary="New Linear issue" --profile=linear-team
|
|
480
|
+
ticketlens create --project=PROJ --type="Bug" --summary="Broken layout" --attach=./screenshot.png
|
|
438
481
|
```
|
|
439
482
|
|
|
440
483
|
Write directly to the ticket in its real tracker — Jira, GitHub, or Linear — from your terminal or an AI session via `ticket_comment`/`ticket_transition`/`ticket_assign`/`ticket_duplicates`/`ticket_link`/`ticket_update`/`ticket_create` MCP tools. Requires a Pro license.
|
|
@@ -443,7 +486,7 @@ Write directly to the ticket in its real tracker — Jira, GitHub, or Linear —
|
|
|
443
486
|
|
|
444
487
|
`ticketlens assign` is self-assign only for now — `--to` must be `me`. Assigning to someone else needs a per-tracker user-lookup step this doesn't do yet, so it's deliberately out of scope until that's built.
|
|
445
488
|
|
|
446
|
-
`ticketlens duplicates` is read-only — it never links or changes anything, just lists likely matches in the same project. No tracker (Jira/GitHub/Linear) scores similarity server-side, so ranking happens locally from title/description word overlap; treat a match as a nudge to check manually, not a verdict. `--threshold=N` (0–1, default 0.35) controls how loose a match counts.
|
|
489
|
+
`ticketlens duplicates` is read-only — it never links or changes anything, just lists likely matches in the same project. No tracker (Jira/GitHub/Linear) scores similarity server-side, so ranking happens locally from title/description word overlap; treat a match as a nudge to check manually, not a verdict. That local scoring can also miss a real duplicate — an empty result means none were found by this heuristic, not a confirmed absence. `--threshold=N` (0–1, default 0.35) controls how loose a match counts.
|
|
447
490
|
|
|
448
491
|
`ticketlens link SOURCE-KEY TARGET-KEY` links two tickets — direction matters: SOURCE "types" TARGET (e.g. `link A B --type=Duplicate` means A duplicates B, not the other way around). With just the two keys it lists the tracker's current valid link types without changing anything — always fetched live for Jira, since link type names are per-instance configurable there. GitHub is different from Jira/Linear: it has no generic link relationship, so linking on a GitHub-tracked ticket *closes SOURCE as a duplicate of TARGET* — a state change, not just a relationship add — and prints an explicit warning immediately before that happens, on top of the same `--confirm` gate.
|
|
449
492
|
|
|
@@ -451,6 +494,8 @@ Write directly to the ticket in its real tracker — Jira, GitHub, or Linear —
|
|
|
451
494
|
|
|
452
495
|
`ticketlens create` creates a new ticket with a fixed minimal field set — no arbitrary custom fields. Unlike every other write command, there's no existing ticket to target, so `--profile` (or your default profile) picks the tracker instead of a ticket key. `--project` is the Jira project key or Linear team key — required for both, ignored on GitHub since its target repo is already fixed by the profile. `--type` is Jira's issue type (e.g. `"Task"`, `"Bug"`) — required for Jira, ignored elsewhere. No `--confirm` gate, same risk tier as `update`/`assign` — but this is the highest-blast-radius command in the whole family: a bad `--project`/`--type` fabricates a real, hard-to-walk-back item in a live tracker, so an invalid value surfaces the tracker's own error rather than a silent guess.
|
|
453
496
|
|
|
497
|
+
`--attach=path1,path2` (comma-separated local file paths) is available on `comment` and `create` only. Images render as an inline thumbnail on Jira and Linear; GitHub has no attachment upload API, so `--attach` is unsupported there.
|
|
498
|
+
|
|
454
499
|
**A bad `--project`/`--type` gets a better error, automatically.** If create fails because the project or issue type doesn't exist, TicketLens fetches your tracker's real, current project list (and, for Jira, the real issue types for that project) and shows them alongside the failure — e.g. `Known creatable projects: CNV1, CNV2.` — rather than a bare tracker error. This is reactive only: it never runs on a successful create, never auto-retries the write, and is cached locally per profile for 24h so a burst of failed attempts doesn't re-fetch every time.
|
|
455
500
|
|
|
456
501
|
All six write actions (comment/transition/assign/link/update/create) have a short local debounce (10s) against an accidental double-fire (a flaky retry, hitting enter twice), and every successful write is appended to a local, append-only audit log (`~/.ticketlens/ticket-action-log.jsonl`). A write that times out is never retried automatically — unlike Recall notes, ticket writes aren't naturally idempotent, so a timed-out attempt is surfaced to you instead of silently repeated. `duplicates` has neither, since nothing is written.
|
|
@@ -736,6 +781,7 @@ ticketlens mcp install --dry-run # Preview the registration without
|
|
|
736
781
|
|
|
737
782
|
# ── Comment, Transition, Assign, Duplicates, Link, Update & Create ──────────────
|
|
738
783
|
ticketlens comment CNV1-2 --body="Looks good, merging." # Post a comment to the tracker [Pro]
|
|
784
|
+
ticketlens comment CNV1-2 --body="See screenshot" --attach=./bug.png # Attach local files [Pro]
|
|
739
785
|
ticketlens transition CNV1-2 # List valid transitions (read-only) [Pro]
|
|
740
786
|
ticketlens transition CNV1-2 --target="Done" --confirm # Execute the transition [Pro]
|
|
741
787
|
ticketlens assign CNV1-2 --to=me # Assign the ticket to yourself [Pro]
|
|
@@ -747,6 +793,7 @@ ticketlens update CNV1-2 --title="New title" # Update title/descr
|
|
|
747
793
|
ticketlens update CNV1-2 --add-labels=urgent --remove-labels=stale # Add/remove labels [Pro]
|
|
748
794
|
ticketlens create --project=CNV1 --type="Task" --summary="New ticket" # Create a new ticket [Pro]
|
|
749
795
|
ticketlens create --project=ENG --summary="New issue" --profile=linear-team # Create on a different profile [Pro]
|
|
796
|
+
ticketlens create --project=CNV1 --type="Bug" --summary="Broken layout" --attach=./screenshot.png # Create with an attachment [Pro]
|
|
750
797
|
|
|
751
798
|
# ── Stats ──────────────────────────────────────────────────────────────────────
|
|
752
799
|
ticketlens stats # Response-time metrics from local history
|
|
@@ -757,12 +804,12 @@ ticketlens stats --format=json # JSON output for scripting
|
|
|
757
804
|
# ── Compliance ────────────────────────────────────────────────────────────────
|
|
758
805
|
ticketlens compliance <TICKET-KEY> # Check ticket requirements against local diff [Pro/Free 3/mo]
|
|
759
806
|
ticketlens ledger # View local compliance audit ledger [Pro]
|
|
760
|
-
ticketlens install-hooks # Install pre-push compliance gate
|
|
761
|
-
ticketlens install-hooks --uninstall # Remove installed hooks
|
|
807
|
+
ticketlens install-hooks # Install pre-push compliance gate
|
|
808
|
+
ticketlens install-hooks --uninstall # Remove installed hooks
|
|
762
809
|
|
|
763
810
|
# ── PR Description ─────────────────────────────────────────────────────────────
|
|
764
|
-
ticketlens pr <TICKET-KEY> # Generate PR description from ticket
|
|
765
|
-
ticketlens pr <TICKET-KEY> | pbcopy # Copy to clipboard
|
|
811
|
+
ticketlens pr <TICKET-KEY> # Generate PR description from ticket
|
|
812
|
+
ticketlens pr <TICKET-KEY> | pbcopy # Copy to clipboard
|
|
766
813
|
|
|
767
814
|
# ── AI provider keys (BYOK) ───────────────────────────────────────────────────
|
|
768
815
|
ticketlens cloud-keys list # List configured AI providers
|
|
@@ -820,7 +867,6 @@ ticketlens CNV1-2 --summarize --cloud # AI summary via TicketLens API (no loc
|
|
|
820
867
|
ticketlens CNV1-2 --handoff # AI handoff brief from the ticket's comment thread (BYOK)
|
|
821
868
|
ticketlens CNV1-2 --handoff --cloud # AI handoff brief via TicketLens API
|
|
822
869
|
ticketlens CNV1-2 --compliance # Check ticket requirements against local diff [Pro/Free 3/mo]
|
|
823
|
-
ticketlens triage --stale=3 # Custom stale threshold (default is 5)
|
|
824
870
|
ticketlens triage --digest # POST scored triage results to digest endpoint
|
|
825
871
|
ticketlens schedule # Set up a scheduled daily digest
|
|
826
872
|
ticketlens note add --title="..." # Save a Recall note (body from stdin)
|
|
@@ -830,6 +876,7 @@ ticketlens recall sync # Retry any notes stuck in the local qu
|
|
|
830
876
|
ticketlens recall settings # Show effective retry-queue settings, fetched live
|
|
831
877
|
ticketlens mcp # Start the MCP stdio server (recall/ticket write tools)
|
|
832
878
|
ticketlens comment CNV1-2 --body="..." # Post a comment to the tracker
|
|
879
|
+
ticketlens comment CNV1-2 --body="..." --attach=./bug.png # Attach local files (comment/create only)
|
|
833
880
|
ticketlens transition CNV1-2 --target="Done" --confirm # Transition ticket status
|
|
834
881
|
ticketlens assign CNV1-2 --to=me # Assign the ticket to yourself
|
|
835
882
|
ticketlens duplicates CNV1-2 # Find likely duplicates (read-only)
|
package/package.json
CHANGED
package/skills/jtb/SKILL.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- jtb-skill-version: 0.
|
|
1
|
+
<!-- jtb-skill-version: 0.32.0 -->
|
|
2
2
|
---
|
|
3
3
|
name: jtb
|
|
4
4
|
description: Fetch a Jira ticket's full context (description, comments, linked issues, code references) and assemble a structured TicketBrief for implementation planning. Use when user types /jtb, mentions a Jira ticket key, or wants to plan work from a Jira ticket.
|
|
@@ -292,7 +292,7 @@ ticketlens create --project=PROD --type="Task" --summary="Fix login on mobile"
|
|
|
292
292
|
|
|
293
293
|
`assign` is self-assign only — `--to` must be `me`. There is no way to assign to anyone else yet; don't attempt a workaround (e.g. via `comment`) if the user asks for that — tell them it isn't supported.
|
|
294
294
|
|
|
295
|
-
`duplicates` lists likely-duplicate tickets in the same project. On Jira, any ticket already linked as a "Duplicate" is always listed first — that's a confirmed relationship a human already recorded, not a heuristic. Everything else is ranked by local title/description overlap — no tracker scores similarity server-side, so treat those as a nudge for the user to check manually, never as a confirmed duplicate to act on unprompted (e.g. don't auto-close or auto-comment based on a match). `--threshold=N` (0–1, default 0.35) tightens or loosens what counts as a text-match — it has no effect on Jira-linked duplicates, which are always shown.
|
|
295
|
+
`duplicates` lists likely-duplicate tickets in the same project. On Jira, any ticket already linked as a "Duplicate" is always listed first — that's a confirmed relationship a human already recorded, not a heuristic. Everything else is ranked by local title/description overlap — no tracker scores similarity server-side, so treat those as a nudge for the user to check manually, never as a confirmed duplicate to act on unprompted (e.g. don't auto-close or auto-comment based on a match). `--threshold=N` (0–1, default 0.35) tightens or loosens what counts as a text-match — it has no effect on Jira-linked duplicates, which are always shown. An empty result is the same approximation in the other direction — the local scorer can miss a real duplicate too, so don't treat "no likely duplicates found" as proof none exist.
|
|
296
296
|
|
|
297
297
|
`link SOURCE-KEY TARGET-KEY` links two tickets — direction matters: SOURCE "types" TARGET (e.g. `link A B --type=Duplicate` means A duplicates B, not the other way around). Called with just the two keys, it lists the tracker's current valid link types without changing anything — never guess `--type`; always list first, then use one of the names shown. GitHub has no generic link relationship, so linking on a GitHub-tracked ticket *closes SOURCE as a duplicate of TARGET* — a real state change, not just a relationship add — and prints an explicit warning immediately before that happens, on top of the same `--confirm` gate.
|
|
298
298
|
|
|
@@ -760,6 +760,7 @@ export function printDuplicatesHelp({ stream = process.stdout } = {}) {
|
|
|
760
760
|
` that's a confirmed relationship, not a guess. Everything else comes from a`,
|
|
761
761
|
` local title/description overlap score (no tracker scores similarity`,
|
|
762
762
|
` server-side) — not exact, treat those as a nudge to check.`,
|
|
763
|
+
` An empty result isn't a guarantee — this heuristic can miss real matches too.`,
|
|
763
764
|
'',
|
|
764
765
|
` ${s.bold('OPTIONS')}`,
|
|
765
766
|
'',
|
|
@@ -93,7 +93,7 @@ const TOOLS = [
|
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
name: 'ticket_duplicates',
|
|
96
|
-
description: 'Find likely duplicate tickets in the same project (Jira/GitHub/Linear). Read-only — never links or changes anything. On Jira, any ticket already linked as a "Duplicate" is always included first (a confirmed relationship, not a guess); everything else comes from a local, approximate title/description overlap score, since no tracker scores similarity server-side. Requires a TicketLens Pro license.',
|
|
96
|
+
description: 'Find likely duplicate tickets in the same project (Jira/GitHub/Linear). Read-only — never links or changes anything. On Jira, any ticket already linked as a "Duplicate" is always included first (a confirmed relationship, not a guess); everything else comes from a local, approximate title/description overlap score, since no tracker scores similarity server-side. That scorer can miss real duplicates as easily as it over-matches, so an empty result means none were found, not a guarantee that none exist. Requires a TicketLens Pro license.',
|
|
97
97
|
inputSchema: {
|
|
98
98
|
type: 'object',
|
|
99
99
|
properties: {
|
|
@@ -518,7 +518,7 @@ export async function runTicketDuplicates(cmdArgs, {
|
|
|
518
518
|
stream.write(` ${s.brand(s.bold(ticketKey))}: ${s.bold(source.summary ?? '')}\n\n`);
|
|
519
519
|
|
|
520
520
|
if (results.length === 0) {
|
|
521
|
-
stream.write(` No likely duplicates found.\n`);
|
|
521
|
+
stream.write(` No likely duplicates found (heuristic match only — not a guarantee none exist).\n`);
|
|
522
522
|
return { ok: true, results: [] };
|
|
523
523
|
}
|
|
524
524
|
stream.write(` Possible duplicates:\n\n`);
|