AgentStack
SKILL verified MIT Self-run

Landscape

skill-flurdy-agent-skills-landscape · by flurdy

Morning catch-up view — assigned Jira tickets, open PRs, current working copy state, and (if present) in-progress and ready beads in one glance. Run at session start to orient.

No reviews yet
0 installs
12 views
0.0% view→install

Install

$ agentstack add skill-flurdy-agent-skills-landscape

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Landscape? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Landscape — Morning Catch-up

Show a consolidated landscape of where you are and what to do next, pulling from multiple sources at once. Designed for the start of a work session (especially Monday mornings) to quickly orient.

Usage

/landscape          # Full landscape
/landscape quick    # Skip PR details (faster, Jira + working-copy + beads-if-present only)

What It Shows

Separate blocks, rendered from broadest context to most immediate. Order matters — the last block is the most load-bearing for "what am I doing right now":

  1. 📋 Jira — tickets assigned to you, not Done (with sprint)
  2. 🔀 PRs — org-wide open PRs, recently closed, unresolved threads
  3. 🎯 Beads — in-progress and top ready beads in this repo (skipped if bd not installed)
  4. 📍 Working copy — current branch, uncommitted/unpushed work (plus, in a multi-repo workspace, a roll-up of sibling service repos with unsaved/unpushed state)
  5. Next — single-sentence suggestion for the most load-bearing action

Each block is independent — if one source fails, the others still render.

Instructions

> MUST re-fetch on every invocation. Each /landscape run MUST execute every fetch from scratch — date, the Jira MCP query, the gh-pr-list-* and gh-pr-details.sh scripts, beads.sh, and working-copy.sh. NEVER reuse output from a previous run in the same session and NEVER extrapolate timestamps. State changes (PR merges, new approvals, ticket transitions) happen between runs; reusing stale tables has caused real merges to be missed in /pr-status and the same risk applies here. > > MUST use the dedicated helper scripts. Never construct ad-hoc bd … or git … shell pipelines for this skill. Specifically: do NOT chain command -v bd probes with bd list … && … or … || bd list --ready inside a single Bash call. Always invoke ~/.claude/skills/landscape/scripts/beads.sh instead — it handles probing, repo gating, and listing internally. Likewise, do NOT hand-walk sibling service repos with your own for … git -C … loop — always go through ~/.claude/skills/wrap-up/scripts/multirepo.sh (§4b), which handles workspace detection and per-repo state. Inline chaining bypasses the per-script permission allowlist and produces noisy permission prompts.

Render the blocks in the order listed below. Some data fetches can run in parallel at the top.

0. Header

date '+%A %Y-%m-%d %H:%M'

Output:

## Landscape — {Weekday} {YYYY-MM-DD} {HH:MM}

If the weekday is Monday, add a subtitle: _Monday — extra catch-up across the weekend._

1. 📋 Jira — assigned to you

Query Jira for open tickets assigned to the current user, including sprint membership. The sprint field is the Jira Cloud default custom field customfield_10020. Use the MCP tool:

mcp__jira__jira_get
  path: /rest/api/3/search/jql
  queryParams:
    jql: assignee = currentUser() AND statusCategory != Done ORDER BY cf[10020] ASC, priority DESC, updated DESC
    fields: summary,status,priority,issuetype,updated,customfield_10020
    maxResults: 20
  jq: issues[*].{key: key, summary: fields.summary, type: fields.issuetype.name, status: fields.status.name, priority: fields.priority.name, updated: fields.updated, sprint: fields.customfield_10020}

The sprint field is an array of sprint objects. Extract the active sprint's name (first sprint where state == "active"), or the most recent if none are active. If the array is empty or null, show (ticket not in a sprint — possibly backlog).

Sort the rows before rendering. JQL's cf[10020] sort is unreliable across sprint states, so re-sort client-side:

  1. Bucket by sprint state: active sprints first, then future sprints (by startDate ascending), then no-sprint / backlog last.
  2. Within each bucket, sort by priority P1 → P2 → P3 → P4 → P5 (treat missing/unknown priority as lowest).
  3. Within equal priority, preserve the JQL updated DESC order.

Keep it as a single table — the Sprint column makes the group boundary visible without subheadings.

Render:

### 📋 Jira — assigned to you

| Key | Sprint | Type | Pri | Status | Updated | Summary |
|-----|--------|------|-----|--------|---------|---------|
| [AB-649](https://.../browse/AB-649) | Sprint 42 | Task | P1 | In Progress | 2h | Stabilise identity cookies |
  • Key: markdown link to the Jira issue. Use the Jira base URL from the issue's self field, or a site-configured base (e.g. https://yourorg.atlassian.net/browse/{key}).
  • Sprint: active sprint name. Truncate numeric-only names to S{N} if the column gets wide. if none.
  • Type: issuetype name (Task / Story / Bug / Sub-task).
  • Pri: shorten long names — P1 CriticalP1, P2 HighP2, etc.
  • Status: status name (In Progress / Code Review / Ready for QA / …).
  • Updated: relative time since updated (e.g. 2h, 4d).
  • Summary: truncate to ~50 chars.

If no tickets are assigned, show _No open Jira tickets assigned to you._

If the Jira API returns an error, show _Jira unavailable: {error}_ and move on — do not fail the whole skill.

After the table, note whether the tickets span one sprint or multiple. Example: _All 6 in Sprint 42._ or _Spans 2 sprints: Sprint 42 (4), Sprint 43 (2)._ This answers "am I focused or scattered?" at a glance.

2. 🔀 PRs — delegate to pr-status logic

If /landscape quick was invoked, skip this section entirely and add a one-line note: _PR section skipped (quick mode). Run /pr-status for full view._

Otherwise, follow the pr-status skill's instructions as-is (see ~/.claude/skills/pr-status/SKILL.md). Reuse its scripts directly — do NOT re-invoke the slash command:

  1. List open PRs org-wide via gh-pr-list-open.sh
  2. List recently closed via gh-pr-list-closed.sh
  3. Fetch details via gh-pr-details.sh (grouped by owner/repo)
  4. Render the same tables

Head this section ### 🔀 PRs instead of pr-status's own headings.

3. 🎯 Beads — in-progress + ready work

Run the beads.sh helper. It probes for bd, checks for .beads/ in the repo, and emits in-progress + ready listings as delimited sections. Do not call bd directly from this skill — always go through this script:

~/.claude/skills/landscape/scripts/beads.sh

Output sections (delimited by ------):

  • ---STATUS---OK, NO_BD (bd not installed), or NO_BEADS_IN_REPO (no .beads/ here)
  • ---IN-PROGRESS--- — output of bd list --status=in_progress (only if STATUS=OK)
  • ---READY--- — JSON array from next-bd --json (or plain text from bd list --ready fallback) (only if STATUS=OK)

If STATUS is NO_BD, render _Beads not installed — skipping._ and stop. If STATUS is NO_BEADS_IN_REPO, render _No beads in this repo._ and stop. Otherwise render the tables below.

In-progress beads
**In progress ({count})**
| ID | Pri | Type | Labels | Title |
|----|-----|------|--------|-------|
  • Include a Labels column. Show if none.
  • If no in-progress beads: show _No in-progress beads._
Ready beads — sorted by sprint

The ---READY--- section is a JSON array (from next-bd --json). Each item has id, title, priority, issue_type, and rank.

Step 1 — Extract Jira keys. For each bead, scan title for the first match of [A-Z]+-\d+. If no match, the bead has no Jira link.

Step 2 — Batch Jira sprint lookup. If any keys were found, call:

mcp__jira__jira_get
  path: /rest/api/3/search/jql
  queryParams:
    jql: key in ({comma-separated keys})
    fields: summary,status,issuetype,priority,customfield_10020
    maxResults: 50
  jq: issues[*].{key: key, status: fields.status.name, sprint: fields.customfield_10020}

For each ticket's sprint array, pick the active sprint (first with state=="active"). If none active, pick the earliest future sprint (lowest startDate with state=="future"). If neither, treat as no-sprint.

Step 3 — Sort and cap. Bucket order: active sprint(s) → future sprints (by startDate) → no-sprint (has Jira key) → no Jira link. Within each bucket preserve the rank order from next-bd. Cap the total at 5 beads. If more exist: _+{N} more — run /next sprint to see all._

Step 4 — Render. One table:

**Ready ({shown} of {total})**
| # | ID | Pri | Type | Jira | Sprint | Status | Title |
|---|----|-----|------|------|--------|--------|-------|
  • # is the picker index 1-N.
  • Jira column: markdown link [KEY](https://yourorg.atlassian.net/browse/KEY). Show if no Jira key.
  • Sprint column: number + state suffix only (31 (active), 32 (future)) — strip the project prefix from sprint names like "PROJ Sprint 31". Show if no sprint or no Jira.
  • Status column: Jira status. Show if no Jira.
  • If no ready beads at all: _No ready beads. Run /triage to add work._
  • If the ---READY--- section is not valid JSON (fallback plain text): render it as-is, capped at 5 lines.
  • If the Jira call fails: render the table without Jira/Sprint/Status columns; add a footnote _Jira unavailable._

4. 📍 Working copy — current branch

Rendered LAST because it's the most immediate context — the branch you're sitting on right now, what needs committing/pushing, and whether it's in sync.

Run the working-copy.sh helper, which emits delimited sections for branch, dirty status, ahead/behind, last commit, and on-branch stash count:

~/.claude/skills/landscape/scripts/working-copy.sh

Output is grouped by ---SECTION--- markers. Parse and render from that.

Render:

### 📍 Working copy

| Field | Value |
|-------|-------|
| Branch | fix/AB-649-device-cookie-combined |
| Dirty | clean _(or: 3 modified, 1 untracked)_ |
| vs upstream | ✅ in sync _(or: ⬆ 2 ahead, ⬇ 1 behind)_ |
| Last commit | `abc1234` commit subject (2h ago) |

Notes:

  • If @{u} fails (no upstream), show no upstream tracking.
  • If output is empty for dirty, show clean.
  • Stashes: do NOT include a stash row in the table. Only surface stashes if there are stashes on the current branch. If non-empty, add a one-line footnote below the table:

`` ⚠️ {N} stash(es) on this branch — run git stash list to review. `` Global stash count is not interesting — omit it.

  • Other worktrees: the OTHER-WORKTREES-UNSAFE section lists only worktrees (excluding the current one) that have uncommitted changes or unpushed commits. If empty, render nothing — worktrees that are clean and pushed are not interesting. If non-empty, add a footnote below the table:

``` ⚠️ Other worktrees with unsaved work:

  • /path/to/other on fix/X — 3 modified, 2 unpushed

`` Omit the dirty/unpushed parts that are zero (e.g. 3 modified alone, or 2 unpushed` alone).

  • Recent handoffs for this repo: probe ~/.claude/handoffs/ via:

``bash ~/.claude/skills/handoffs/scripts/list.sh --summary-only `` Parse from the output:

  • ---SUMMARY---current_repo_recent_live — recent handoffs for this repo that are still live work: not superseded and not finished (uses the same Mon→3 / Tue→4 / else→3 weekend buffer as the closed-PR list). "Finished" here means all referenced beads are closed — a local bd check that runs even on this offline (--summary-only, no --check-branches) call, so a handoff whose task shipped no longer counts as a live thread to resume. Re-wraps of the same branch still collapse to one. (Merged-PR / Jira-Done detection needs the network and only applies under /handoffs's --check-branches; landscape's offline count catches the bead-closed case.)
  • ---CURRENT-REPO-LATEST--- → a single {slug}|{branch}|{date} line for the newest current-repo handoff (the "last session"), or empty if none.
  • ---CURRENT-REPO-LIVE--- → one {slug}|{branch}|{date}|{time} line per recent live (non-superseded, non-finished) current-repo handoff, newest first (these are the threads behind the current_repo_recent_live count). The first line equals ---CURRENT-REPO-LATEST--- when the newest handoff is itself still live; if the newest one is finished it's absent here, so the first line is the most recent resumable thread instead.

If current_repo_recent_live > 0, render its own table (N = current_repo_recent_live) — a footnote got lost among the other tables, so give it the same ### {emoji} {Name} + table shape as the sections above:

```markdown ### 📥 Recent handoffs ({N} live, last {RECENT-WINDOW-DAYS}d)

| Handoff | Branch | When | |---------|--------|------| | {slug} 📍 | {branch} | {age} | | {slug} | {branch} | {age} |

/handoffs to browse and resume. ```

  • One row per ---CURRENT-REPO-LIVE--- line, newest first.
  • Handoff: the {slug}. Append 📍 to the row whose {slug} matches the ---CURRENT-REPO-LATEST--- line — that's the last session, the most likely resume target. When the newest handoff is already finished it won't appear here; the first row is then simply the most recent resumable thread, left unmarked.
  • Branch: the {branch}; render when it is ? or empty.
  • When: relative age of {date} (e.g. today, 2d).
  • Cap at 5 rows (newest first). When N > 5, render the first 5 and replace the caption with _+{N − 5} more — /handoffs to browse._

Suppress the section entirely when current_repo_recent_live == 0 — silence is shorter. Older, superseded, or finished handoffs are still browsable via /handoffs; this table is just a fresh-work hint, deliberately offline (no --check-branches, so no branch-staleness here). This call can run in parallel with working-copy.sh.

4b. 🗂️ Other repos in this workspace

working-copy.sh (§4) inspects only the cwd repo (plus its own worktrees). In a multi-repo workspace — mgit services (.mgit.conf) or git submodules (.gitmodules) — that silently misses uncommitted/unpushed state in sibling service repos. This is the single biggest blind spot at session start: you orient on the root repo and never notice that, say, dispatch was left with unpushed commits last night. Roll them up:

~/.claude/skills/wrap-up/scripts/multirepo.sh

It emits ---MARKER--- (mgit | submodules | none), ---ROOT---, and ---REPOS--- lines: {name}|{branch}|{ahead}|{behind}|{upstream}|{modified}|{untracked} (ahead/behind are - with no upstream; the root repo appears as its own row). This call can run in parallel with working-copy.sh — it's the same roll-up /wrap-up §3b uses.

  • ---MARKER--- is none → single repo; skip this whole section silently (§4 already covered it).
  • Otherwise render only the members with something to report (ahead>0, behind>0, or modified+untracked>0); a clean+pushed member is noise. Skip the table entirely if every member is clean — in a healthy workspace this section shows nothing, which is the point.
### 🗂️ Other repos in this workspace

| Repo | Branch | Unpushed | Behind | Uncommitted |
|------|--------|----------|--------|-------------|
  • Unpushed: {ahead}, or no upstream when upstream=no (local-only, never pushed).
  • Behind: show only when >0. A member that's diverged (ahead>0 AND behind>0) needs a rebase/pull before it can push — flag it explicitly: ⚠️ diverged — N ahead / M behind.
  • Uncommitted: {modified} modified / {untracked} untracked (omit zero parts).

Carry the most urgent member (diverged, then unpushed, then uncommitted) into the §5 Next suggestion — a sibling repo left in that state is exactly what a fresh session forgets.

5. Next step suggestion

After all blocks render, add a short footer with a concrete next step, picked from what's visible. Prefer the most load-bearing single action:

  • If the current branch's PR is approved, CI green, 0 threads, clean merge state → suggest merging it (this unblocks sta

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.