diff --git a/docs/cast-issue-create.svg b/docs/cast-issue-create.svg
index 9ff98288..1ccc142e 100644
--- a/docs/cast-issue-create.svg
+++ b/docs/cast-issue-create.svg
@@ -4,15 +4,15 @@
width="1300"
height="607.88"
>
-
+
+
+
diff --git a/docs/cast-issue-start.svg b/docs/cast-issue-start.svg
index 0c9d81a5..edc08372 100644
--- a/docs/cast-issue-start.svg
+++ b/docs/cast-issue-start.svg
@@ -4,15 +4,15 @@
width="1300"
height="607.88"
>
-
+
-
+ ❯
+
+ ❯
+ ❯linearissue
+ ❯
+ linear
+ issue
+ start?Selectstart
+
+
+ ?
+ Select
+ anissuean
+ issue
+ tostart:❯---to
+ start:
+
+
+ ❯
+ ---
+ CLI-14:AllowCLI-14:
+ Allow
+ assigningpeopleassigning
+ people
+ otherthanother
+ than
+ yourselfwhenyourself
+ when
+ creatingissuescreating
+ issues
+
+
+ ---CLI-20:---
+ CLI-20:
+ AllowskippingAllow
+ skipping
+ confirmationwhendeletingconfirmation
+ when
+ deleting
+ issuesissues
+
+
+ ---CLI-16:---
+ CLI-16:
+ SupportlistingSupport
+ listing
+ projectsprojects
+
+
+ ---CLI-14:---
+ CLI-14:
+ AllowassigningAllow
+ assigning
+ peopleotherpeople
+ other
+ thanyourselfthan
+ yourself
+ whencreatingwhen
+ creating
+ issues❯---issues
+
+
+ ❯
+ ---
+ CLI-20:AllowCLI-20:
+ Allow
+ skippingconfirmationwhendeletingskipping
+ confirmation
+ when
+ deleting
+ issues❯---issues
+
+
+ ❯
+ ---
+ CLI-16:SupportCLI-16:
+ Support
+ listingprojects?Selectlisting
+ projects
+
+
+ ?
+ Select
+ anissuean
+ issue
+ tostart:to
+ start:
+ ›---›
+ ---
+ CLI-20:AllowCLI-20:
+ Allow
+ skippingconfirmationwhendeletingskipping
+ confirmation
+ when
+ deleting
+ issues⠋?Branchissues
+
+ ⠋
+
+ ?
+ Branch
+ cli-20-allow-skipping-confirmation-when-deleting-issuescli-20-allow-skipping-confirmation-when-deleting-issues
+ alreadyexists.already
+ exists.
+ WhatwouldWhat
+ would
+ youlikeyou
+ like
+ todo?Switchtoto
+ do?
+
+
+ Switch
+ to
+ existingbranch❯Createexisting
+ branch
+
+
+ ❯
+ Create
+ newbranchnew
+ branch
+ withsuffix?Branchwith
+ suffix
+
+
+ ?
+ Branch
+ cli-20-allow-skipping-confirmation-when-deleting-issuescli-20-allow-skipping-confirmation-when-deleting-issues
+ alreadyexists.already
+ exists.
+ WhatwouldWhat
+ would
+ youlikeyou
+ like
+ todo?to
+ do?
+ ›Create›
+ Create
+ newbranchnew
+ branch
+ withsuffix✓Createdwi
+
+
+ th
+ suffix
+
+
+ ✓
+ Created
+ andswitchedand
+ switched
+ tobranchto
+ branch
+ 'cli-20-allow-skipping-confirmation-when-deleting-issues-1''cli-20-allow-skipping-confirmation-when-deleting-issues-1'
+
+ ✓Issuestate
+ ✓
+ Issue
+ state
+ updatedtoupdated
+ to
+ 'InProgress''In
+ Progress'
+
+
+ ❯git❯
+ git
+ branch--show-currentbranch
+ --show-current
+
+
+ ❯git❯
+ git
+ branch--show-currentbranch
+ --show-current
+
+
+ cli-20-allow-skipping-confirmation-when-deleting-issues-1cli-20-allow-skipping-confirmation-when-deleting-issues-1
+
+
+
+
+
+
+
+
+
+
+ >
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+ ❯❯
+ l
-
-
+
+
+
+ ❯l
-
- ❯
+ l
+
+
+
+
+ ❯l❯
+ l
+ lmcmdlm
+ cmd
+ "gitshow"git
+ show
+ currentbranch"
-
- current
+ branch"
+
+
+
+
+ ❯linear
-
- ❯
+ linear
+
+
+
+
+ ❯linear
-
- ❯
+ linear
+
+
+
+
+ ❯linear❯
+ linear
+ issuelistissue
+ list
+ -a
-
-
+
+
+
+ ❯linear❯
+ linear
+ issuei
+ ssue
+ list-a
-
- list
+ -a
+
+
+
+
+ ❯linear❯
+ linear
+ issuei
+ ssue
+ list-a
-
- list
+ -a
+
+
+
+
+ ❯linear❯
+ linear
+ i
-
-
+
+
+
+ ❯linear❯
+ linear
+ issue
-
-
+
+
+
+ ❯linear❯
+ linear
+ issue
-
-
+
+
+
+ ❯linear❯
+ linear
+ issuelistissue
+ list
+ -a
-
-
+
+
+
+ ❯linear❯
+ linear
+ issuesissue
+ s
+ tart
-
-
+
+
+
+ ❯linear❯
+ linear
+ issuestissue
+ st
+ art
-
-
+
+
+
+ ❯linear❯
+ linear
+ issuestaissue
+ sta
+ rt
-
-
+
+
+
+ ❯linear❯
+ linear
+ issuestarissue
+ star
+ t
-
-
+
+
+
diff --git a/skills/linear-cli/references/issue.md b/skills/linear-cli/references/issue.md
index 16f8bc03..1c1e3328 100644
--- a/skills/linear-cli/references/issue.md
+++ b/skills/linear-cli/references/issue.md
@@ -33,7 +33,8 @@ Commands:
comment - Manage issue comments
attach - Attach a file to an issue
link [url] - Link a URL to an issue
- relation - Manage issue relations (dependencies)
+ relation - Manage issue relations (dependencies)
+ agent-session - Manage agent sessions for an issue
```
## Subcommands
@@ -520,3 +521,60 @@ Options:
-h, --help - Show this help.
-w, --workspace - Target workspace (uses credentials)
```
+
+### agent-session
+
+> Manage agent sessions for an issue
+
+```
+Usage: linear issue agent-session
+
+Description:
+
+ Manage agent sessions for an issue
+
+Options:
+
+ -h, --help - Show this help.
+ -w, --workspace - Target workspace (uses credentials)
+
+Commands:
+
+ list [issueId] - List agent sessions for an issue
+ view, v - View agent session details
+```
+
+#### agent-session subcommands
+
+##### list
+
+```
+Usage: linear issue agent-session list [issueId]
+
+Description:
+
+ List agent sessions for an issue
+
+Options:
+
+ -h, --help - Show this help.
+ -w, --workspace - Target workspace (uses credentials)
+ -j, --json - Output as JSON
+ --status - Filter by status (pending, active, complete, awaitingInput, error, stale)
+```
+
+##### view
+
+```
+Usage: linear issue agent-session view
+
+Description:
+
+ View agent session details
+
+Options:
+
+ -h, --help - Show this help.
+ -w, --workspace - Target workspace (uses credentials)
+ -j, --json - Output as JSON
+```
diff --git a/src/commands/issue/issue-agent-session-list.ts b/src/commands/issue/issue-agent-session-list.ts
new file mode 100644
index 00000000..cb5fec78
--- /dev/null
+++ b/src/commands/issue/issue-agent-session-list.ts
@@ -0,0 +1,152 @@
+import { Command } from "@cliffy/command"
+import { unicodeWidth } from "@std/cli"
+import { green, yellow } from "@std/fmt/colors"
+import { gql } from "../../__codegen__/gql.ts"
+import { getGraphQLClient } from "../../utils/graphql.ts"
+import { padDisplay, truncateText } from "../../utils/display.ts"
+import { getIssueIdentifier } from "../../utils/linear.ts"
+import { shouldShowSpinner } from "../../utils/hyperlink.ts"
+import { header, muted } from "../../utils/styling.ts"
+import { handleError, ValidationError } from "../../utils/errors.ts"
+
+const GetIssueAgentSessions = gql(`
+ query GetIssueAgentSessions($issueId: String!) {
+ issue(id: $issueId) {
+ comments(first: 100) {
+ nodes {
+ agentSession {
+ id
+ status
+ type
+ createdAt
+ startedAt
+ endedAt
+ summary
+ creator {
+ name
+ }
+ appUser {
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+`)
+
+function formatStatus(status: string): string {
+ switch (status) {
+ case "active":
+ return green(padDisplay("active", 13))
+ case "pending":
+ return yellow(padDisplay("pending", 13))
+ case "awaitingInput":
+ return yellow(padDisplay("awaitingInput", 13))
+ case "complete":
+ return muted(padDisplay("complete", 13))
+ case "error":
+ return padDisplay("error", 13)
+ case "stale":
+ return muted(padDisplay("stale", 13))
+ default:
+ return padDisplay(status, 13)
+ }
+}
+
+function formatDate(dateString: string): string {
+ return dateString.slice(0, 10)
+}
+
+export const agentSessionListCommand = new Command()
+ .name("list")
+ .description("List agent sessions for an issue")
+ .arguments("[issueId:string]")
+ .option("-j, --json", "Output as JSON")
+ .option(
+ "--status ",
+ "Filter by status (pending, active, complete, awaitingInput, error, stale)",
+ )
+ .action(async ({ json, status }, issueId) => {
+ try {
+ const resolvedIdentifier = await getIssueIdentifier(issueId)
+ if (!resolvedIdentifier) {
+ throw new ValidationError(
+ "Could not determine issue ID",
+ { suggestion: "Please provide an issue ID like 'ENG-123'." },
+ )
+ }
+
+ const { Spinner } = await import("@std/cli/unstable-spinner")
+ const showSpinner = shouldShowSpinner()
+ const spinner = showSpinner ? new Spinner() : null
+ spinner?.start()
+
+ const client = getGraphQLClient()
+ const result = await client.request(GetIssueAgentSessions, {
+ issueId: resolvedIdentifier,
+ })
+ spinner?.stop()
+
+ let sessions = (result.issue?.comments?.nodes || [])
+ .map((c) => c.agentSession)
+ .filter((s): s is NonNullable => s != null)
+
+ if (status) {
+ sessions = sessions.filter((s) => s.status === status)
+ }
+
+ if (json) {
+ console.log(JSON.stringify(sessions, null, 2))
+ return
+ }
+
+ if (sessions.length === 0) {
+ console.log("No agent sessions found for this issue.")
+ return
+ }
+
+ const { columns } = Deno.stdout.isTerminal()
+ ? Deno.consoleSize()
+ : { columns: 120 }
+
+ const STATUS_WIDTH = 13
+ const DATE_WIDTH = 10
+ const AGENT_WIDTH = Math.max(
+ 5,
+ ...sessions.map((s) => unicodeWidth(s.appUser.name)),
+ )
+ const SPACE_WIDTH = 3
+
+ const fixed = STATUS_WIDTH + DATE_WIDTH + AGENT_WIDTH + SPACE_WIDTH
+ const PADDING = 1
+ const availableWidth = Math.max(columns - PADDING - fixed, 10)
+
+ const headerCells = [
+ padDisplay("STATUS", STATUS_WIDTH),
+ padDisplay("AGENT", AGENT_WIDTH),
+ padDisplay("CREATED", DATE_WIDTH),
+ "SUMMARY",
+ ]
+
+ console.log(header(headerCells.join(" ")))
+
+ for (const session of sessions) {
+ const summaryText = session.summary
+ ? truncateText(
+ session.summary.replace(/\n/g, " "),
+ availableWidth,
+ )
+ : muted("--")
+
+ const line = `${formatStatus(session.status)} ${
+ padDisplay(session.appUser.name, AGENT_WIDTH)
+ } ${
+ padDisplay(formatDate(session.createdAt), DATE_WIDTH)
+ } ${summaryText}`
+ console.log(line)
+ }
+ } catch (error) {
+ handleError(error, "Failed to list agent sessions")
+ }
+ })
diff --git a/src/commands/issue/issue-agent-session-view.ts b/src/commands/issue/issue-agent-session-view.ts
new file mode 100644
index 00000000..cb08784d
--- /dev/null
+++ b/src/commands/issue/issue-agent-session-view.ts
@@ -0,0 +1,179 @@
+import { Command } from "@cliffy/command"
+import { renderMarkdown } from "@littletof/charmd"
+import { gql } from "../../__codegen__/gql.ts"
+import { getGraphQLClient } from "../../utils/graphql.ts"
+import { formatRelativeTime } from "../../utils/display.ts"
+import { shouldShowSpinner } from "../../utils/hyperlink.ts"
+import { handleError, NotFoundError } from "../../utils/errors.ts"
+
+const GetAgentSessionDetails = gql(`
+ query GetAgentSessionDetails($id: String!) {
+ agentSession(id: $id) {
+ id
+ status
+ type
+ createdAt
+ updatedAt
+ startedAt
+ endedAt
+ dismissedAt
+ summary
+ externalLink
+ creator {
+ name
+ }
+ appUser {
+ name
+ }
+ dismissedBy {
+ name
+ }
+ issue {
+ identifier
+ title
+ url
+ }
+ activities(first: 20) {
+ nodes {
+ id
+ createdAt
+ content {
+ ... on AgentActivityThoughtContent {
+ type
+ body
+ }
+ ... on AgentActivityActionContent {
+ type
+ action
+ parameter
+ result
+ }
+ ... on AgentActivityResponseContent {
+ type
+ body
+ }
+ ... on AgentActivityPromptContent {
+ type
+ body
+ }
+ ... on AgentActivityErrorContent {
+ type
+ body
+ }
+ ... on AgentActivityElicitationContent {
+ type
+ body
+ }
+ }
+ }
+ }
+ }
+ }
+`)
+
+export const agentSessionViewCommand = new Command()
+ .name("view")
+ .description("View agent session details")
+ .alias("v")
+ .arguments("")
+ .option("-j, --json", "Output as JSON")
+ .action(async ({ json }, sessionId) => {
+ try {
+ const { Spinner } = await import("@std/cli/unstable-spinner")
+ const showSpinner = shouldShowSpinner()
+ const spinner = showSpinner ? new Spinner() : null
+ spinner?.start()
+
+ const client = getGraphQLClient()
+ const result = await client.request(GetAgentSessionDetails, {
+ id: sessionId,
+ })
+ spinner?.stop()
+
+ const session = result.agentSession
+ if (!session) {
+ throw new NotFoundError("Agent session", sessionId)
+ }
+
+ if (json) {
+ console.log(JSON.stringify(session, null, 2))
+ return
+ }
+
+ const lines: string[] = []
+
+ lines.push(`# Agent Session`)
+ lines.push("")
+
+ lines.push(`**ID:** ${session.id}`)
+ lines.push(`**Status:** ${session.status}`)
+ lines.push(`**Type:** ${session.type}`)
+ lines.push(`**Agent:** ${session.appUser.name}`)
+
+ if (session.creator) {
+ lines.push(`**Creator:** ${session.creator.name}`)
+ }
+
+ if (session.issue) {
+ lines.push(
+ `**Issue:** ${session.issue.identifier} - ${session.issue.title}`,
+ )
+ }
+
+ lines.push("")
+ lines.push(`**Created:** ${formatRelativeTime(session.createdAt)}`)
+ if (session.startedAt) {
+ lines.push(`**Started:** ${formatRelativeTime(session.startedAt)}`)
+ }
+ if (session.endedAt) {
+ lines.push(`**Ended:** ${formatRelativeTime(session.endedAt)}`)
+ }
+ if (session.dismissedAt) {
+ lines.push(`**Dismissed:** ${formatRelativeTime(session.dismissedAt)}`)
+ if (session.dismissedBy) {
+ lines.push(`**Dismissed by:** ${session.dismissedBy.name}`)
+ }
+ }
+
+ if (session.externalLink) {
+ lines.push("")
+ lines.push(`**External Link:** ${session.externalLink}`)
+ }
+
+ if (session.summary) {
+ lines.push("")
+ lines.push("## Summary")
+ lines.push("")
+ lines.push(session.summary)
+ }
+
+ if (session.activities.nodes.length > 0) {
+ lines.push("")
+ lines.push("## Activities")
+ lines.push("")
+ for (const activity of session.activities.nodes) {
+ const time = formatRelativeTime(activity.createdAt)
+ const content = activity.content
+ const type = "type" in content ? content.type : "unknown"
+ let detail = ""
+ if ("body" in content && content.body) {
+ detail = ` - ${content.body.replace(/\n/g, " ")}`
+ } else if ("action" in content && content.action) {
+ detail = ` - ${content.action}: ${content.parameter}`
+ }
+ lines.push(`- **${type}** (${time})${detail}`)
+ }
+ }
+
+ const markdown = lines.join("\n")
+
+ if (Deno.stdout.isTerminal()) {
+ const terminalWidth = Deno.consoleSize().columns
+ console.log(renderMarkdown(markdown, { lineWidth: terminalWidth }))
+ } else {
+ console.log(markdown)
+ }
+ } catch (error) {
+ handleError(error, "Failed to fetch agent session details")
+ }
+ })
diff --git a/src/commands/issue/issue-agent-session.ts b/src/commands/issue/issue-agent-session.ts
new file mode 100644
index 00000000..914d58ab
--- /dev/null
+++ b/src/commands/issue/issue-agent-session.ts
@@ -0,0 +1,11 @@
+import { Command } from "@cliffy/command"
+import { agentSessionListCommand } from "./issue-agent-session-list.ts"
+import { agentSessionViewCommand } from "./issue-agent-session-view.ts"
+
+export const agentSessionCommand = new Command()
+ .description("Manage agent sessions for an issue")
+ .action(function () {
+ this.showHelp()
+ })
+ .command("list", agentSessionListCommand)
+ .command("view", agentSessionViewCommand)
diff --git a/src/commands/issue/issue.ts b/src/commands/issue/issue.ts
index 56b9f517..bce5ae38 100644
--- a/src/commands/issue/issue.ts
+++ b/src/commands/issue/issue.ts
@@ -10,6 +10,7 @@ import { linkCommand } from "./issue-link.ts"
import { listCommand } from "./issue-list.ts"
import { pullRequestCommand } from "./issue-pull-request.ts"
import { relationCommand } from "./issue-relation.ts"
+import { agentSessionCommand } from "./issue-agent-session.ts"
import { startCommand } from "./issue-start.ts"
import { titleCommand } from "./issue-title.ts"
import { updateCommand } from "./issue-update.ts"
@@ -37,3 +38,4 @@ export const issueCommand = new Command()
.command("attach", attachCommand)
.command("link", linkCommand)
.command("relation", relationCommand)
+ .command("agent-session", agentSessionCommand)
diff --git a/test/commands/issue/__snapshots__/issue-agent-session-list.test.ts.snap b/test/commands/issue/__snapshots__/issue-agent-session-list.test.ts.snap
new file mode 100644
index 00000000..f5edbb02
--- /dev/null
+++ b/test/commands/issue/__snapshots__/issue-agent-session-list.test.ts.snap
@@ -0,0 +1,39 @@
+export const snapshot = {};
+
+snapshot[`Issue Agent Session List Command - Help Text 1`] = `
+stdout:
+"
+Usage: list [issueId]
+
+Description:
+
+ List agent sessions for an issue
+
+Options:
+
+ -h, --help - Show this help.
+ -j, --json - Output as JSON
+ --status - Filter by status (pending, active, complete, awaitingInput, error, stale)
+
+"
+stderr:
+""
+`;
+
+snapshot[`Issue Agent Session List Command - With Mock Sessions 1`] = `
+stdout:
+"STATUS AGENT CREATED SUMMARY
+active Linear Assistant 2026-03-20 Investigating auth token refresh bug
+complete Linear Assistant 2026-03-19 Added dark mode toggle to settings page
+"
+stderr:
+""
+`;
+
+snapshot[`Issue Agent Session List Command - No Sessions Found 1`] = `
+stdout:
+"No agent sessions found for this issue.
+"
+stderr:
+""
+`;
diff --git a/test/commands/issue/__snapshots__/issue-agent-session-view.test.ts.snap b/test/commands/issue/__snapshots__/issue-agent-session-view.test.ts.snap
new file mode 100644
index 00000000..3f68e965
--- /dev/null
+++ b/test/commands/issue/__snapshots__/issue-agent-session-view.test.ts.snap
@@ -0,0 +1,73 @@
+export const snapshot = {};
+
+snapshot[`Issue Agent Session View Command - Help Text 1`] = `
+stdout:
+"
+Usage: view
+
+Description:
+
+ View agent session details
+
+Options:
+
+ -h, --help - Show this help.
+ -j, --json - Output as JSON
+
+"
+stderr:
+""
+`;
+
+snapshot[`Issue Agent Session View Command - Active Session With Activities 1`] = `
+stdout:
+"# Agent Session
+
+**ID:** session-1
+**Status:** active
+**Type:** commentThread
+**Agent:** Linear Assistant
+**Creator:** Alice
+**Issue:** ENG-412 - Fix auth token refresh
+
+**Created:** 1/1/2020
+**Started:** 1/1/2020
+
+## Summary
+
+Investigating auth token refresh bug in the middleware layer
+
+## Activities
+
+- **thought** (1/1/2020) - Looking at the auth middleware code
+- **action** (1/1/2020) - read_file: src/middleware/auth.ts
+- **response** (1/1/2020) - The token refresh is failing because the expiry check uses UTC
+"
+stderr:
+""
+`;
+
+snapshot[`Issue Agent Session View Command - Completed Session No Activities 1`] = `
+stdout:
+"# Agent Session
+
+**ID:** session-2
+**Status:** complete
+**Type:** commentThread
+**Agent:** Linear Assistant
+**Creator:** Bob
+**Issue:** ENG-398 - Add dark mode toggle
+
+**Created:** 1/1/2020
+**Started:** 1/1/2020
+**Ended:** 1/1/2020
+
+**External Link:** https://github.com/org/repo/pull/42
+
+## Summary
+
+Added dark mode toggle to settings page
+"
+stderr:
+""
+`;
diff --git a/test/commands/issue/issue-agent-session-list.test.ts b/test/commands/issue/issue-agent-session-list.test.ts
new file mode 100644
index 00000000..be76c63a
--- /dev/null
+++ b/test/commands/issue/issue-agent-session-list.test.ts
@@ -0,0 +1,122 @@
+import { snapshotTest as cliffySnapshotTest } from "@cliffy/testing"
+import { agentSessionListCommand } from "../../../src/commands/issue/issue-agent-session-list.ts"
+import { commonDenoArgs } from "../../utils/test-helpers.ts"
+import { MockLinearServer } from "../../utils/mock_linear_server.ts"
+
+await cliffySnapshotTest({
+ name: "Issue Agent Session List Command - Help Text",
+ meta: import.meta,
+ colors: false,
+ args: ["--help"],
+ denoArgs: commonDenoArgs,
+ async fn() {
+ await agentSessionListCommand.parse()
+ },
+})
+
+await cliffySnapshotTest({
+ name: "Issue Agent Session List Command - With Mock Sessions",
+ meta: import.meta,
+ colors: false,
+ args: ["ENG-412"],
+ denoArgs: commonDenoArgs,
+ async fn() {
+ const server = new MockLinearServer([
+ {
+ queryName: "GetIssueAgentSessions",
+ variables: { issueId: "ENG-412" },
+ response: {
+ data: {
+ issue: {
+ comments: {
+ nodes: [
+ {
+ agentSession: {
+ id: "session-1",
+ status: "active",
+ type: "commentThread",
+ createdAt: "2026-03-20T10:00:00.000Z",
+ startedAt: "2026-03-20T10:00:05.000Z",
+ endedAt: null,
+ summary: "Investigating auth token refresh bug",
+ creator: { name: "Alice" },
+ appUser: { name: "Linear Assistant" },
+ },
+ },
+ {
+ agentSession: {
+ id: "session-2",
+ status: "complete",
+ type: "commentThread",
+ createdAt: "2026-03-19T15:30:00.000Z",
+ startedAt: "2026-03-19T15:30:05.000Z",
+ endedAt: "2026-03-19T16:00:00.000Z",
+ summary: "Added dark mode toggle to settings page",
+ creator: { name: "Bob" },
+ appUser: { name: "Linear Assistant" },
+ },
+ },
+ {
+ agentSession: null,
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ ])
+
+ try {
+ await server.start()
+ Deno.env.set("LINEAR_GRAPHQL_ENDPOINT", server.getEndpoint())
+ Deno.env.set("LINEAR_API_KEY", "Bearer test-token")
+
+ await agentSessionListCommand.parse()
+ } finally {
+ await server.stop()
+ Deno.env.delete("LINEAR_GRAPHQL_ENDPOINT")
+ Deno.env.delete("LINEAR_API_KEY")
+ }
+ },
+})
+
+await cliffySnapshotTest({
+ name: "Issue Agent Session List Command - No Sessions Found",
+ meta: import.meta,
+ colors: false,
+ args: ["ENG-412"],
+ denoArgs: commonDenoArgs,
+ async fn() {
+ const server = new MockLinearServer([
+ {
+ queryName: "GetIssueAgentSessions",
+ variables: { issueId: "ENG-412" },
+ response: {
+ data: {
+ issue: {
+ comments: {
+ nodes: [
+ { agentSession: null },
+ { agentSession: null },
+ ],
+ },
+ },
+ },
+ },
+ },
+ ])
+
+ try {
+ await server.start()
+ Deno.env.set("LINEAR_GRAPHQL_ENDPOINT", server.getEndpoint())
+ Deno.env.set("LINEAR_API_KEY", "Bearer test-token")
+
+ await agentSessionListCommand.parse()
+ } finally {
+ await server.stop()
+ Deno.env.delete("LINEAR_GRAPHQL_ENDPOINT")
+ Deno.env.delete("LINEAR_API_KEY")
+ }
+ },
+})
diff --git a/test/commands/issue/issue-agent-session-view.test.ts b/test/commands/issue/issue-agent-session-view.test.ts
new file mode 100644
index 00000000..d6b4c2f1
--- /dev/null
+++ b/test/commands/issue/issue-agent-session-view.test.ts
@@ -0,0 +1,157 @@
+import { snapshotTest } from "@cliffy/testing"
+import { agentSessionViewCommand } from "../../../src/commands/issue/issue-agent-session-view.ts"
+import { commonDenoArgs } from "../../utils/test-helpers.ts"
+import { MockLinearServer } from "../../utils/mock_linear_server.ts"
+
+await snapshotTest({
+ name: "Issue Agent Session View Command - Help Text",
+ meta: import.meta,
+ colors: false,
+ args: ["--help"],
+ denoArgs: commonDenoArgs,
+ async fn() {
+ await agentSessionViewCommand.parse()
+ },
+})
+
+await snapshotTest({
+ name: "Issue Agent Session View Command - Active Session With Activities",
+ meta: import.meta,
+ colors: false,
+ args: ["session-1"],
+ denoArgs: commonDenoArgs,
+ async fn() {
+ const server = new MockLinearServer([
+ {
+ queryName: "GetAgentSessionDetails",
+ variables: { id: "session-1" },
+ response: {
+ data: {
+ agentSession: {
+ id: "session-1",
+ status: "active",
+ type: "commentThread",
+ createdAt: "2020-01-01T10:00:00Z",
+ updatedAt: "2020-01-01T10:05:00Z",
+ startedAt: "2020-01-01T10:00:05Z",
+ endedAt: null,
+ dismissedAt: null,
+ summary:
+ "Investigating auth token refresh bug in the middleware layer",
+ externalLink: null,
+ creator: { name: "Alice" },
+ appUser: { name: "Linear Assistant" },
+ dismissedBy: null,
+ issue: {
+ identifier: "ENG-412",
+ title: "Fix auth token refresh",
+ url: "https://linear.app/eng/issue/ENG-412",
+ },
+ activities: {
+ nodes: [
+ {
+ id: "activity-1",
+ createdAt: "2020-01-01T10:00:05Z",
+ content: {
+ __typename: "AgentActivityThoughtContent",
+ type: "thought",
+ body: "Looking at the auth middleware code",
+ },
+ },
+ {
+ id: "activity-2",
+ createdAt: "2020-01-01T10:01:00Z",
+ content: {
+ __typename: "AgentActivityActionContent",
+ type: "action",
+ action: "read_file",
+ parameter: "src/middleware/auth.ts",
+ result: "Found token refresh logic",
+ },
+ },
+ {
+ id: "activity-3",
+ createdAt: "2020-01-01T10:02:00Z",
+ content: {
+ __typename: "AgentActivityResponseContent",
+ type: "response",
+ body:
+ "The token refresh is failing because the expiry check uses UTC",
+ },
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ ])
+
+ try {
+ await server.start()
+ Deno.env.set("LINEAR_GRAPHQL_ENDPOINT", server.getEndpoint())
+ Deno.env.set("LINEAR_API_KEY", "Bearer test-token")
+
+ await agentSessionViewCommand.parse()
+ } finally {
+ await server.stop()
+ Deno.env.delete("LINEAR_GRAPHQL_ENDPOINT")
+ Deno.env.delete("LINEAR_API_KEY")
+ }
+ },
+})
+
+await snapshotTest({
+ name: "Issue Agent Session View Command - Completed Session No Activities",
+ meta: import.meta,
+ colors: false,
+ args: ["session-2"],
+ denoArgs: commonDenoArgs,
+ async fn() {
+ const server = new MockLinearServer([
+ {
+ queryName: "GetAgentSessionDetails",
+ variables: { id: "session-2" },
+ response: {
+ data: {
+ agentSession: {
+ id: "session-2",
+ status: "complete",
+ type: "commentThread",
+ createdAt: "2020-01-01T10:00:00Z",
+ updatedAt: "2020-01-01T10:30:00Z",
+ startedAt: "2020-01-01T10:00:05Z",
+ endedAt: "2020-01-01T10:30:00Z",
+ dismissedAt: null,
+ summary: "Added dark mode toggle to settings page",
+ externalLink: "https://github.com/org/repo/pull/42",
+ creator: { name: "Bob" },
+ appUser: { name: "Linear Assistant" },
+ dismissedBy: null,
+ issue: {
+ identifier: "ENG-398",
+ title: "Add dark mode toggle",
+ url: "https://linear.app/eng/issue/ENG-398",
+ },
+ activities: {
+ nodes: [],
+ },
+ },
+ },
+ },
+ },
+ ])
+
+ try {
+ await server.start()
+ Deno.env.set("LINEAR_GRAPHQL_ENDPOINT", server.getEndpoint())
+ Deno.env.set("LINEAR_API_KEY", "Bearer test-token")
+
+ await agentSessionViewCommand.parse()
+ } finally {
+ await server.stop()
+ Deno.env.delete("LINEAR_GRAPHQL_ENDPOINT")
+ Deno.env.delete("LINEAR_API_KEY")
+ }
+ },
+})