Claude Code Guide

Issue & Task Pipeline

Replace Linear, Jira, and GitHub Issues with markdown files in an Obsidian vault. Full lifecycle from creation to close — no SaaS, no vendor lock-in, $0/month.

The $0 Issue Tracker

I used Linear for a year ($20/month). It was great, but Claude Code couldn't read or write to it without a custom integration. GitHub Issues is free but has the same problem — it's a separate system that Claude has to API into.

Then I realized: if issues are just markdown files with YAML frontmatter, Claude can create, read, update, and close them with the tools it already has. Obsidian's Bases feature turns that frontmatter into queryable database views — filtered, sorted, and grouped like any issue tracker. No API, no subscription, no vendor lock-in.

Feature Linear / Jira Vault Issues
Cost $8-20/user/month $0 (Obsidian is free for personal use)
Claude integration Custom API wrapper needed Native — Read/Write/Grep work directly
Offline access Limited or none Full — it's local files
Version history Proprietary changelog Git — full diff, blame, bisect
Cross-references ID links within the tool [[wikilinks]] to any vault page — docs, infra, digests
Data export JSON/CSV export (maybe) Already markdown — no export needed
Database views Built-in boards, tables Obsidian Bases — filter, sort, group on frontmatter
Issue Lifecycle

Every code change starts with an issue. The issue flows through a status pipeline, optionally through a spec workflow for non-trivial features, and ends with a close sweep.

CREATION PLANNING EXECUTION /issue creates /spec (if non-trivial) Implement in worktree markdown file with Requirements Design Commit, PR, merge YAML frontmatter Tasks Implementation DocVault/Projects/ Dashboard approvals /after-action {Project}/Issues/ at each phase gate plan vs reality backlog → todo → in-progress → in-review → done /issue-close-sweep

Status Flow

backlog
todo
in-progress
in-review
done

Issues can also move to canceled or superseded if they're no longer relevant.

Issue File Structure

Each issue is a markdown file with YAML frontmatter. The frontmatter is what Obsidian Bases queries against — every field matters.

Projects/StakTrakr/Issues/STAK-498.md
---
id: "STAK-498"
title: "Fix JM Bullion price scraper reading wrong column"
type: bug
scope: user-facing
status: done
priority: 1
assignee: lbruton
created: "2026-03-20"
updated: "2026-03-22"
completed: "2026-03-22"
due: ""
parent:
tags:
  - issue
  - staktrakr
  - bug
---

## Description

JM Bullion eCheck prices are inflated by ~$200. The price extractor
is reading the Card/PayPal column instead of the eCheck/Wire column.

## Acceptance Criteria

- [ ] eCheck prices match the website's eCheck/Wire column
- [ ] Other vendors unaffected by the fix
- [ ] Poller redeployed to both Portainer and Fly.io

## Related Documentation

- [[StakTrakr Overview]] — poller pipeline context
- [[Remote Poller]] — Fly.io deployment
- [[Portainer]] — home deployment target
Critical: Frontmatter quoting
Fields id, title, created, updated, and completed must be quoted in YAML. Unquoted values can be misinterpreted (e.g., 2026-03-20 without quotes becomes a date object, not a string). Missing or misquoted fields silently break Obsidian Bases — the issue won't appear in your views.

Field Reference

FieldValuesNotes
id"PREFIX-NUM"Project prefix + auto-incremented number
typefeature bug chore spikeUnquoted enum
scopeuser-facing internalControls GitHub sync (user-facing only)
statusbacklog todo in-progress in-review doneAlso: canceled, superseded
priority1 - 41 = critical, 4 = nice-to-have
tagsArrayMust include issue + project tag
Counter & Prefix System

Each project has a counter file that auto-increments issue numbers. The /issue skill reads the counter, creates the file, and bumps the counter — all in one step.

Projects/StakTrakr/Issues/_counter.md
---
prefix: STAK
next: 532
project: StakTrakr
tags:
  - system
  - counter
---

Project Prefixes

PrefixProjectIssue Path
STAKStakTrakrProjects/StakTrakr/Issues/
HEXHexTrackrProjects/HexTrackr/Issues/
FORGEForgeProjects/Forge/Issues/
OPSDevOps / InfrastructureProjects/Devops/Issues/
SWFSpecFlow PluginProjects/SpecFlow/Issues/

Sub-Issues

For work that breaks into sub-tasks under a parent issue, use letter suffixes: STAK-498-A, STAK-498-B. Sub-issues include a parent: "[[STAK-498]]" field in their frontmatter and don't increment the counter.

Obsidian Bases: The Database Layer

Obsidian Bases turns your frontmatter into a queryable database. Create .base files that filter, sort, and group your issues — just like Linear or Jira boards, but powered by local markdown.

Cross-Project View

A single Issues.base at the vault root shows all open issues across every project, sorted by priority and grouped by status. Each project folder also has its own Issues.base for a focused view.

What Bases Extracts

Bases reads your frontmatter fields and renders them as sortable, filterable columns:

Why Bases instead of Dataview?
Dataview is a popular Obsidian plugin for querying notes, but it uses a custom query language and renders tables at view time. Bases is a core feature (no plugin needed), stores the view definition as a .base file (version-controllable), and renders a proper database grid with sorting, filtering, and inline editing. It's also readable by Claude via the Obsidian CLI's base:query command.
Issue Lifecycle Skills

Five skills manage the full issue lifecycle. Each is a SKILL.md file that Claude reads and follows.

/issue

Create a new issue. Reads the counter, writes the file with proper frontmatter, links related docs, increments the counter, and validates.

/spec

Spec-driven development. Takes an issue through Requirements, Design, Tasks, and Implementation with approval gates at each phase.

/issue-triage

Organize the backlog. Groups issues into sprints, reprioritizes, identifies duplicates, and suggests consolidation.

/issue-close-sweep

Find issues that should be closed. Matches merged PRs, checks acceptance criteria, flags stale issues, and moves closed files to Closed/ folder.

/after-action

Plan vs. reality report. Compares what the issue planned against what was actually delivered — deferred criteria, scope changes, follow-ups.

/issue Skill Workflow

1. Read .claude/project.json for issuePrefix and issueTag
2. Read _counter.md → get next number (e.g., 532)
3. Write STAK-532.md with full frontmatter + description
4. Identify and link related vault pages in ## Related Documentation
5. Increment counter: next → 533
6. Read file back and VALIDATE all frontmatter fields
   (this is a hard gate — missing fields break Bases)
7. Confirm: "Created STAK-532: [title] at [path]"

GitHub Issues Policy

GitHub Issues are treated as an inbound-only public bug inbox. All internal planning, features, and specs stay in the vault. When a user reports a bug on GitHub:

  1. Create a vault issue with scope: user-facing and type: bug
  2. Reference the GH issue number in the body (not frontmatter)
  3. Close the GH issue when the vault issue reaches done
Issue → Spec → Ship

Non-trivial features go through a four-phase spec workflow. Each phase produces a document, requires a dashboard approval, and feeds into the next phase.

The Four Phases

PhaseDocumentQuestion
1. Requirementsrequirements.mdWHAT are we building and for whom?
2. Designdesign.mdHOW will it work technically?
3. Taskstasks.mdWhat are the atomic steps?
4. ImplementationCode + logsBuild it, review it, ship it.
# Spec files live in the project's .spec-workflow directory
.spec-workflow/specs/STAK-498-price-scraper-fix/
  ├── requirements.md      # User stories, acceptance criteria
  ├── design.md            # Architecture, API designs, components
  ├── tasks.md             # Atomic tasks with _Prompt guidance
  └── Implementation Logs/
      ├── Task-1-log.md    # What was built, files changed
      └── Task-2-log.md

Task Format

Each task in tasks.md includes structured guidance that Claude uses during implementation:

## Task 1.1: Fix Price Column Selection
- [ ] Update column-aware parser to check eCheck first
- [ ] Add regression test for JM Bullion parsing

_Prompt: Role: Backend | Task: Fix price-extract.js column
  selection order | Restrictions: Don't change other vendors |
  Success: eCheck prices within $5 of website values

_Leverage: devops/pollers/shared/price-extract.js (existing parser)

_Requirements: Requirement #1, Acceptance Criteria #1

Implementation Logging

Before marking any task [x] (complete), the log-implementation tool must be called. This creates a searchable knowledge base of what was built, preventing duplicate API endpoints and components across future specs.

When to skip the spec
Simple bug fixes and chores don't need a full spec. Use the bug fast path: /systematic-debugging/issue → fix → PR. Or for trivial fixes, use /gsd (Get Stuff Done) — no issue, no spec, just a chore: PR.
Standups, Roadmaps & Sweeps

Three skills produce reports from your issue data — weekly progress summaries, project roadmaps, and automated close sweeps.

/weekly-standup

Generates a weekly progress report: commits, issues completed, PRs merged. Written to Standups/YYYY-WNN.md in the vault.

/update-roadmap

Generates or updates ROADMAP.md in each project repo from current issue data. Groups by status: completed, active, backlog.

/issue-close-sweep

Finds closeable issues: criteria complete, matching merged PR, stale (30+ days no activity), or superseded by newer work.

Set Up Vault-Based Issues

1. Create the issue directory

# In your Obsidian vault
mkdir -p Projects/MyProject/Issues

2. Create the counter

cat > Projects/MyProject/Issues/_counter.md << 'EOF'
---
prefix: PROJ
next: 1
project: MyProject
tags:
  - system
  - counter
---
EOF

3. Create an Obsidian Base view

# Create a .base file that queries your issues
cat > Projects/MyProject/Issues/Issues.base << 'EOF'
{
  "name": "MyProject Issues",
  "source": "folder:Projects/MyProject/Issues",
  "filter": { "property": "tags", "operator": "contains", "value": "issue" },
  "columns": ["id", "title", "type", "status", "priority", "created"],
  "sort": [{ "property": "priority", "direction": "asc" }]
}
EOF

4. Tell Claude about your project

Add issue routing to your project's .claude/project.json:

{
  "issuePrefix": "PROJ",
  "issueTag": "myproject",
  "issuePath": "Projects/MyProject/Issues"
}

5. Create your first issue

# In Claude Code
> /issue "Add user authentication" --type feature --priority 2
Prompt for Claude: Build the issue skill
I want a Claude Code skill called /issue that creates issues as markdown files in my Obsidian vault. The skill should:

1. Read my project config (.claude/project.json) for the issue prefix and vault path
2. Read the _counter.md file to get the next issue number
3. Create a markdown file with YAML frontmatter (id, title, type, scope, status, priority, assignee, created, updated, tags)
4. Increment the counter after creating the file
5. Read the file back to validate all frontmatter fields are present and quoted correctly
6. Support sub-issues with letter suffixes (PROJ-1-A, PROJ-1-B) that reference a parent

The frontmatter must be Obsidian Bases compatible — id, title, created, updated must be quoted strings. Save as ~/.claude/skills/issue/SKILL.md.