yurtle-kanban
File-based kanban using Yurtle (Turtle RDF in Markdown). Git is your database.
What is yurtle-kanban?
A workflow management system where:
- Files ARE work items - Each task is a markdown file with Yurtle (Turtle RDF) blocks
- Git IS the database - No external database, your repo is the source of truth
- SPARQL enables queries - Query your work items like a knowledge graph
- Themes customize naming - Use software terms (feature, bug) or nautical (expedition, voyage) or your own
Part of the Yurtle Ecosystem
yurtle -> Turtle RDF in Markdown specification
yurtle-rdflib -> RDFlib parser/serializer plugin
yurtle-kanban -> This project: file-based workflow management
nusy-nano -> Optional: neurosymbolic reasoning
Installation
Requires git 2.36 or later: every push runs git hook run --ignore-missing (2.36), and yurtle-kanban uses git diff --no-relative and its tests git init -b (2.28).
pip install yurtle-kanban
# With semantic search (sentence-transformers)
pip install yurtle-kanban[search]
# With MCP server support
pip install yurtle-kanban[mcp]
# Everything (search + LLM + MCP)
pip install yurtle-kanban[all]
Quick Start
# Initialize in your project (scaffolds directories + templates)
cd my-project
yurtle-kanban init --theme software
# Creates: kanban-work/features/, kanban-work/bugs/, kanban-work/epics/,
# kanban-work/issues/, kanban-work/tasks/, kanban-work/ideas/
# Each with a _TEMPLATE.md showing the correct frontmatter format
# Create work items — always with --push, which allocates the ID atomically
# so two people creating at once cannot land on the same one
yurtle-kanban create feature "Add dark mode" --push --priority high
yurtle-kanban create bug "Fix login error" --push --assign dev-1
yurtle-kanban create feature "Dark mode settings" --push # FEAT-002
# View the board
yurtle-kanban board
# List work items
yurtle-kanban list
yurtle-kanban list --status in_progress
yurtle-kanban list --assignee dev-1
# Move items (kb:by records the actor: --agent, else $YURTLE_AGENT, else git user.name)
yurtle-kanban move FEAT-001 ready # create puts it in backlog
yurtle-kanban move FEAT-001 in_progress --assign dev-1 --agent dev-1
yurtle-kanban move FEAT-001 review --agent dev-1 # the holder moves it on
yurtle-kanban move FEAT-001 done --agent reviewer-1 # review → done: any reviewer
# Comment: free text goes through --body-file and a QUOTED heredoc, so the shell
# expands nothing ($(...), backticks, $VARS are stored verbatim); a ```yurtle or
# ```turtle fence in a comment is stripped from its text, as in a description
yurtle-kanban comment FEAT-001 --body-file - <<'EOF'
Shipped; see the PR.
EOF
# Edit fields and dependencies (only the changed lines are rewritten; a
# self-dependency, an unknown or duplicated target, or a new cycle is refused)
yurtle-kanban update FEAT-002 --add-dep feat-001 --priority high --tag ui
yurtle-kanban update FEAT-002 --depends-on "" # clear the dependencies
yurtle-kanban update FEAT-002 --body-file - <<'EOF'
The new body; the heading, status history and comments are kept.
EOF
# Show item details (with the statuses it can move to)
yurtle-kanban show FEAT-001
# Each board's lifecycle: every status and its legal next statuses
yurtle-kanban states
yurtle-kanban states --board default --json # one board, as JSON
# Prioritized roadmap (excludes done items)
yurtle-kanban roadmap
yurtle-kanban roadmap --by-type
yurtle-kanban roadmap --export md
# Completed work history
yurtle-kanban history
yurtle-kanban history --week
yurtle-kanban history --by-assignee
# Export board
yurtle-kanban export --format html --output board.html
yurtle-kanban export --format markdown --output BOARD.md
yurtle-kanban export --format json
CLI Commands
| Command | Description |
|---|---|
init |
Initialize with theme, scaffold directories + templates |
list |
List work items with optional filters (--pickable for what --agent may pick up now, in pick order; --explain also shows each ready item that isn't pickable, and why); aging: --older-than DURATION, --stale, --stale-after DURATION (default 24h; m/h/d/w), and --json rows carry since, since_source, age_seconds, stale, clock_skew, board; --resolution R: a done item with none counts as completed |
create |
Create a new work item (--push for atomic multi-agent safety) |
claim |
Claim an item race-free: move it to in progress, held by you (--agent, --take-over); claim --next claims the first pickable item you win (exit 7 when none) |
move |
Move item to new status (with --assign, --agent, --force, --closed-by, --resolution completed|superseded|duplicate|wont_do, --superseded-by ID); a move to a status that is not finished clears the resolution |
bounce |
Give an ill-defined item back (--reason TEXT or --reason-file PATH|-; --agent, --take-over): to backlog, unassigned, not pickable until its body is edited |
control |
Emergency stop: control halt (--reason TEXT | --reason-file PATH|-) [--agent A], control resume, control status [--json]; a halt refuses claim and a move to in progress (exit 8), next and list --pickable exit 8, holders may still finish; one repo-wide .kanban/control.yaml on origin's default branch |
update |
Edit fields and dependencies: --title, --priority, --tag/--untag, --body/--body-file, --depends-on/--add-dep/--rm-dep, --related, --allow-unknown, --no-commit |
show |
Show item details, including Can move to (--json: next_statuses, next_status_labels) |
states |
Each board's lifecycle: status → legal next statuses (--board, --type, --json with gate ids); gates, WIP and workflow rules can still refuse |
board |
Display kanban board (board research, board --all, board --campaign VOY-XXX) |
boards |
List configured boards |
board-add |
Add a new board (--preset hdd for research) |
stats |
Show board statistics |
roadmap |
Prioritized view of all non-done items |
history |
Completed work log with time filters |
metrics |
Flow metrics (cycle time, lead time) |
next |
Suggest next item to work on (--agent; --json: {"id", "kind", "reason"}, or null and exit 7 when nothing is left) |
next-id |
Allocate next ID atomically (prevents duplicates!) |
blocked |
Status- and dependency-blocked items, each once, with a tree of what they wait on (--board, --all, --json); hdd implements: hdd critical-path --dev-blockers |
comment |
Add comment to item (--body TEXT or --body-file PATH|-; --agent) |
export |
Export board to HTML/Markdown/JSON |
query |
Hybrid search: SPARQL, semantic, or natural language |
validate |
Check for ID mismatches, duplicate IDs across boards, dependency cycles and dangling depends_on targets |
voyage/epic |
Campaign management: create, show, add |
idea |
HDD: Create research/feature ideas |
literature |
HDD: Create literature reviews |
paper |
HDD: Create research papers |
hypothesis |
HDD: Create testable hypotheses |
experiment |
HDD: create, run (timestamped runs), status (run history) |
measure |
HDD: Create metrics/measures |
hdd |
HDD: backfill (turtle blocks), registry (cross-ref index), validate (link checking) |
rank |
Set priority rank and value summary on items |
Identity and free text
- Actor (who did it: a comment's author,
kb:byon a move) is--agent, else$YURTLE_AGENT, else gituser.name, else an error. Sessions on one machine share gituser.name, so give each session its ownYURTLE_AGENT. - Assignee (who holds the item) is never defaulted: only
--assignsets it.list --assigneeis a filter only. - Identity values are refused when empty, whitespace-only, or holding a control character.
- Every free-text
--Xhas a--X-file PATH|-twin (comment --body/--body-file,create --body/--body-file,update --body/--body-file).-reads stdin, which must be piped (a terminal is refused); the text must be UTF-8, CRLF becomes LF, trailing newlines are dropped, and empty text is refused. Use a quoted heredoc (<<'EOF') so the shell expands nothing.
Preventing Duplicate IDs (Multi-Agent Safe)
Recommended: Use create --push for a single atomic operation:
# Atomic: fetch → allocate → create file → commit → push (retries on conflict)
yurtle-kanban create expedition "Research vectors" --push
yurtle-kanban create feature "Add dark mode" --push --assign Mini
This is the safest approach — one command, no race window between ID allocation and file creation.
Advanced: Use next-id when you need the ID before creating the file manually:
yurtle-kanban next-id EXP --json
# {"success": true, "id": "EXP-609", "prefix": "EXP", "number": 609}
Both commands:
- Fetch latest from remote
- Scan files (frontmatter + filenames +
_ID_ALLOCATIONS.json) for highest ID - Commit and push to claim the ID
- Retry with rebase if another agent pushed first
Querying Your Board
yurtle-kanban builds an RDF knowledge graph from all your work items. You can query it three ways:
# Natural language (hybrid: graph filter + semantic ranking)
yurtle-kanban query "not-done expeditions above 700 that improve brain functioning"
# Raw SPARQL against the unified graph
yurtle-kanban query --sparql "SELECT ?id ?title WHERE {
?item kb:id ?id . ?item kb:title ?title .
?item kb:status kb:in_progress .
}"
# Pure semantic search (requires sentence-transformers)
yurtle-kanban query --semantic "knowledge graph reasoning"
Natural language queries are automatically decomposed into structured filters (status, type, ID range, assignee, tag) plus a semantic intent for ranking. Use --verbose to see the decomposition.
Optional dependencies for search:
pip install yurtle-kanban[search] # Adds sentence-transformers for semantic search
pip install yurtle-kanban[all] # Everything (search + LLM + MCP)
Without [search], query still works in graph-only mode — SPARQL and structured NL filters work with zero extra dependencies.
See docs/query.md for the full query guide.
Work Items as Files
Each work item is a markdown file with Yurtle blocks:
---
id: FEAT-042
title: "Add dark mode support"
type: feature
status: in_progress
priority: high
assignee: dev-1
created: 2026-01-12
tags: [ui, accessibility]
---
# Add Dark Mode Support
Implement dark mode toggle in the settings panel.
## Acceptance Criteria
- [ ] Toggle in settings
- [ ] Persists across sessions
- [ ] Respects system preference
```yurtle
@prefix kb: <https://yurtle.dev/kanban/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<> a kb:Feature ;
kb:id "FEAT-042" ;
kb:status kb:in_progress ;
kb:priority kb:high ;
kb:assignee <../team/dev-1.md> ;
kb:created "2026-01-12"^^xsd:date ;
kb:tag "ui", "accessibility" .
The file IS the work item. `<>` refers to the file itself as an RDF subject.
## Configuration
Running `yurtle-kanban init --theme software` auto-generates this config:
```yaml
# .kanban/config.yaml
kanban:
theme: software # or: nautical, custom
paths:
root: kanban-work/
scan_paths:
- "kanban-work/features/"
- "kanban-work/bugs/"
- "kanban-work/epics/"
- "kanban-work/issues/"
- "kanban-work/tasks/"
- "kanban-work/ideas/"
ignore:
- "**/archive/**"
- "**/templates/**"
- "**/_TEMPLATE*"
ignore and scan_paths belong under paths:. A copy directly under kanban:, as older
examples showed, is still read when paths: doesn't set that key (#482).
On a single board, the type folders under its root are always part of the board (inside the
repo), whatever scan_paths lists. By default create puts each type in its own folder,
<root>/<plural>/ (features/, ideas/, papers/, …). A theme path, a legacy
paths.<type>s or a matching scan path can place it elsewhere. Wherever create writes inside
the repo, scan() walks that folder, so an item is never written where the board can't see it
(#109, #113). With a broad root such as root: . and narrow scan_paths, that means
./ideas/, ./papers/, ./issues/ and so on at the repo root are scanned too. Any
hand-written .md in them that has frontmatter shows up as an item. Give the board a dedicated
root (kanban-work/), or exclude those folders with paths.ignore patterns such as ideas/*
(#137). In a multi-board config, each board scans only its own path.
ignore patterns match a file's path relative to the repo. For a board root outside the
repo (an absolute path, or one reached with ../), items aren't under the repo, so patterns
match the file's absolute path instead: write them as **/archive/**-style globs (or as
absolute paths), not ../other/archive/*. Such a board isn't git-tracked either: create --push, move and comment skip git with a warning.
Each directory gets a _TEMPLATE.md with the correct frontmatter and type-specific sections (e.g., bugs get "Steps to Reproduce", features get "Acceptance Criteria").
Themes
Software (default):
Feature (FEAT-), Bug (BUG-), Epic (EPIC-), Issue (ISSUE-), Task (TASK-), Idea (IDEA-)
Columns: Backlog → Ready → In Progress → Review → Done
Nautical:
Expedition (EXP-), Voyage (VOY-), Chore (CHORE-), Hazard (HAZ-), Signal (SIG-)
Columns: Harbor → Provisioning → Underway → Approaching Port → Arrived (+ Stranded)
HDD (Hypothesis-Driven Development):
Idea (IDEA-R-), Literature (LIT-), Paper (PAPER-), Hypothesis (H-NNN, or H{paper}.{n} when scoped to a paper), Experiment (EXPR-), Measure (M-)
Columns: Draft → Active → Complete → Abandoned
Use HDD for research workflows where experiments validate hypotheses:
# Add HDD board for research
yurtle-kanban board-add research --preset hdd --path research/
# A PAPER IS OPTIONAL. Start with the belief; the paper is a thing you write
# later, if the work ever earns one.
yurtle-kanban hypothesis create "Most support tickets come from one feature"
yurtle-kanban experiment create --title "Count tickets by feature for a month"
yurtle-kanban measure create "Ticket concentration" --unit percent --category quality
# Scope items to a paper when you have one — ids become H{paper}.{n}
yurtle-kanban idea create "Research question" --type research --push
yurtle-kanban literature create "Prior art survey" --idea IDEA-R-001 --push
yurtle-kanban paper create 130 "Cognitive Signal Fusion" --push
yurtle-kanban hypothesis create "V12 improves accuracy" --paper 130 --target ">=85%" --push
yurtle-kanban experiment create EXPR-130 --hypothesis H130.1 --title "Accuracy test" --push
yurtle-kanban measure create "Reasoning Accuracy" --unit percent --category accuracy --push
# View research board
yurtle-kanban board research
# Run experiments (timestamped folders with config.yaml)
yurtle-kanban experiment run EXPR-130 --being santiago-toddler-v12.4
yurtle-kanban experiment run EXPR-130 --being v12.4 --params "kbdd_rounds=3,wikidata=true"
yurtle-kanban experiment status EXPR-130 # Rich table of all runs
yurtle-kanban experiment status EXPR-130 --json # JSON for scripting
# Registry & validation
yurtle-kanban hdd registry # Generate cross-referenced REGISTRY.md
yurtle-kanban hdd validate # Check bidirectional links (papers ↔ hypotheses ↔ experiments)
yurtle-kanban hdd validate --strict # Warnings = errors (for CI)
yurtle-kanban hdd validate --json # JSON output
Each HDD item gets a fenced ```turtle knowledge block with RDF triples expressing
research relationships (hypothesis→paper, experiment→hypothesis, etc.). Creating a child
item automatically updates the parent's knowledge block with an inverse reference.
Learn more: See the HDD Methodology Guide for the full philosophy, worked examples, and integration patterns including agent fleet automation.
Custom: Define your own in themes/my-theme.yaml
MCP Server for AI Agents
yurtle-kanban includes an MCP (Model Context Protocol) server for Claude Code and other AI agents:
# Start the MCP server
yurtle-kanban-mcp
Available Tools
| Tool | Description |
|---|---|
kanban_list_items |
List items with optional filters |
kanban_get_item |
Get item by ID |
kanban_create_item |
Create new item |
kanban_move_item |
Move item to new status |
kanban_get_board |
Get full board state |
kanban_get_my_items |
Get items for assignee |
kanban_get_blocked |
Blocked items, as blocked --json (optional board, all) |
kanban_suggest_next |
Suggest next item to work on |
kanban_add_comment |
Add comment to item |
kanban_update_item |
Update item properties |
kanban_next_id |
Allocate next ID (prevents duplicates!) |
Critical: Using kanban_next_id for Multi-Agent Safety
When creating new work items, ALWAYS call kanban_next_id first:
// Step 1: Allocate ID
{
"name": "kanban_next_id",
"arguments": {
"prefix": "EXP",
"sync_remote": true
}
}
// Returns: {"success": true, "id": "EXP-609", "number": 609}
// Step 2: Create file using that ID
// File: work/EXP-609-My-Feature.md with id: EXP-609 in frontmatter
This prevents duplicate IDs when multiple agents work concurrently.
Claude Code Integration
Add to your MCP config:
{
"mcpServers": {
"kanban": {
"command": "yurtle-kanban-mcp",
"args": []
}
}
}
Then Claude can manage your kanban:
Agent: I'll check what I should work on next.
[Calls: kanban_suggest_next()]
Response: {
"suggestion": {"id": "FEAT-042", "title": "Add dark mode", "priority": "high"},
"message": "Suggested: FEAT-042 - Add dark mode"
}
Agent: Let me move that to in progress.
[Calls: kanban_move_item(item_id="FEAT-042", new_status="in_progress")]
Response: {
"success": true,
"message": "Moved FEAT-042 to in_progress"
}
Claude Code Skills
yurtle-kanban includes theme-specific Claude Code skills for multi-agent workflows. Skills are automatically installed by yurtle-kanban init based on your theme.
Skills by Theme
Theme-neutral (installed for all themes):
| Skill | Command | Purpose |
|---|---|---|
/sync |
Start of session | Pull latest, check handoffs, reviews, blocked items |
/status |
Show kanban board | See what's in progress, ready, blocked |
/release [patch|minor|major] |
Create release | Bump version, update CHANGELOG, create git tag |
Nautical theme (--theme nautical):
| Skill | Command | Purpose |
|---|---|---|
/expedition <title> |
Create expedition | Atomic create --push with EXP- prefix |
/work [EXP-XXX] |
Pick up work | Start work, create branch, update kanban |
/done [EXP-XXX] |
Complete work | Run tests, commit, push, create PR, update kanban |
/review EXP-XXX |
Review expedition | Verify tests, docs, merge readiness |
/handoff EXP-XXX agent |
Hand off work | Pass work to another agent with context |
/blocked EXP-XXX reason |
Mark blocked | Track why work is blocked and who can unblock |
Software theme (--theme software):
| Skill | Command | Purpose |
|---|---|---|
/feature <title> |
Create feature | Atomic create --push with FEAT- prefix |
/work [FEAT-XXX] |
Pick up work | Start work, create branch, update kanban |
/done [FEAT-XXX] |
Complete work | Run tests, commit, push, create PR, update kanban |
/review FEAT-XXX |
Review feature | Verify tests, docs, merge readiness |
/handoff FEAT-XXX agent |
Hand off work | Pass work to another agent with context |
/blocked FEAT-XXX reason |
Mark blocked | Track why work is blocked and who can unblock |
Multi-Agent Coordination
With multiple agents working concurrently, use these patterns:
Agent assignment tags (in work item frontmatter):
tags: [agent-a, gpu-required] # Assigned to Agent A, needs GPU
tags: [agent-b, mac-compatible] # Assigned to Agent B, runs on Mac
tags: [needs-coordination] # Requires multiple agents
tags: [any-agent] # Anyone can pick up
Handoff notes are created in kanban-work/handoffs/ when passing work between agents.
Session start ritual (/sync):
- Pull latest from main
- Check for handoffs addressed to you
- Check items in review
- Check blocked items
- Recommend next action
Installing Skills
Skills are automatically installed to .claude/skills/ when you run yurtle-kanban init:
yurtle-kanban init --theme nautical # Installs nautical skills (/expedition, etc.)
yurtle-kanban init --theme software # Installs software skills (/feature, etc.)
To install manually:
# Theme-neutral skills (always needed)
cp -r skills/sync skills/status skills/release .claude/skills/
# Theme-specific skills (pick one)
cp -r skills/nautical/* .claude/skills/ # Nautical theme
cp -r skills/software/* .claude/skills/ # Software theme
Agent Instructions (CLAUDE.md Snippet)
Add this to your project's CLAUDE.md (or equivalent copilot instructions) so AI agents use yurtle-kanban correctly:
## Work Tracking (yurtle-kanban)
This project uses yurtle-kanban for work tracking. Git is the database.
**Creating work items (IMPORTANT — prevents ID conflicts):**
```bash
# ALWAYS use --push when creating items. This is atomic and multi-agent safe.
yurtle-kanban create <type> "<title>" --push [--priority <p>] [--assign <name>]
# Examples:
yurtle-kanban create expedition "Research vectors" --push --priority high
yurtle-kanban create feature "Add dark mode" --push --assign Mini
```
The `--push` flag atomically: fetches latest → allocates ID → creates file → commits → pushes.
If another agent pushed first, it retries with a new ID. Never create items without `--push`.
**Viewing work:**
```bash
yurtle-kanban board # Kanban board
yurtle-kanban roadmap # Prioritized backlog
yurtle-kanban list --status in_progress # Filter by status
yurtle-kanban history --week # Recent completions
```
**Claiming and moving items:**
```bash
yurtle-kanban claim EXP-001 --agent <your-agent-name> # race-free claim
yurtle-kanban move EXP-001 review --agent <your-agent-name> # the holder moves it on
```
An item in progress can only be moved by its holder: pass `--agent` (or set
`YURTLE_AGENT`). To take over someone else's item, add `--take-over`.
Python API
from pathlib import Path
from yurtle_kanban import KanbanConfig, KanbanService, WorkItemType
# Load config
config = KanbanConfig.load(Path(".kanban/config.yaml"))
service = KanbanService(config, Path.cwd())
# List items
items = service.get_items(status=WorkItemStatus.READY)
# Create item
item = service.create_item(
item_type=WorkItemType.FEATURE,
title="New feature",
priority="high",
assignee="dev-1",
)
# Move item
service.move_item("FEAT-001", WorkItemStatus.DONE)
# Get board
board = service.get_board()
for col in board.columns:
print(f"{col.name}: {len(board.get_items_by_status(col.id))} items")
Export Formats
HTML (GitHub Pages compatible)
yurtle-kanban export --format html --output docs/board.html
Self-contained HTML with embedded CSS. Perfect for GitHub Pages.
Markdown
yurtle-kanban export --format markdown --output BOARD.md
Table format for embedding in README.
JSON
yurtle-kanban export --format json > board.json
For integrations and CI/CD.
GitHub Actions
Auto-close items on PR merge
When a PR merges, automatically move linked kanban items to done (or review).
Uses a reusable workflow shipped in this repo:
# .github/workflows/kanban-auto-close.yml
name: Auto-close kanban items
on:
pull_request:
types: [closed]
jobs:
auto-close:
if: github.event.pull_request.merged == true
uses: hankh95/yurtle-kanban/.github/workflows/kanban-auto-close.yml@main
with:
target-status: done # or "review"
kanban-version: main # yurtle-kanban git ref
How items are detected (two strategies, keywords take priority):
- PR body keywords —
Closes EXP-1023,Fixes CHORE-055,Resolves FEAT-042(case-insensitive, supports multiple items per PR) - Branch name fallback —
exp-1023-title→EXP-1023,chore-055-cleanup→CHORE-055
All item prefixes are supported (EXP, CHORE, FEAT, VOY, BUG, EPIC, ISSUE, TASK, IDEA, DIR, HAZ, SIG, LIT, PAPER, H, EXPR, M).
Held items: the merged PR is the authority. The workflow moves as
github-actions[bot] with --take-over, so an item an agent still holds is
closed too, and its history records kb:takenOverFrom the holder. A move that
fails prints the reason in the step's warning.
Graph provenance: Each auto-close records kb:closedBy <PR-URL> in the item's
Turtle status history block, making PR→item relationships graph-queryable:
<> kb:statusChange [
kb:status kb:done ;
kb:at "2026-03-03T12:34:56"^^xsd:dateTime ;
kb:by "github-actions[bot]" ;
kb:closedBy <https://github.com/owner/repo/pull/42> ;
] .
You can also use --closed-by manually:
yurtle-kanban move EXP-123 done --closed-by "https://github.com/owner/repo/pull/42"
Auto-update board on push
# .github/workflows/kanban-board.yml
name: Update Kanban Board
on:
push:
paths:
- 'work/**/*.md'
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install yurtle-kanban
- run: yurtle-kanban export --format html --output docs/board.html
- run: |
git config user.name "github-actions[bot]"
git add docs/board.html
git commit -m "chore: update kanban board" || exit 0
git push
Why Keep Work Items in Your Project?
| Benefit | Description |
|---|---|
| Single source of truth | Work items live with the code they describe |
| Git history together | Feature branch includes both code AND its work item |
| No external dependency | No Jira outage blocks your workflow |
| Offline-first | Works without internet |
| AI agent access | Agents read/write work items like any file |
| PR integration | Work item changes visible in pull requests |
Changelog
v2.0.0 (2026-03-05)
Queryable knowledge graph — SPARQL, semantic search, and hybrid NL queries.
The jump from file-based kanban CLI (1.x) to a queryable knowledge graph with semantic search. Every work item was already an RDF node — 2.0 connects them into a single queryable whole.
Added
querycommand — Three modes: raw SPARQL, pure semantic search, and hybrid natural language queries (#54)- Unified RDF Graph — Merges all per-file
WorkItem.graphinstances into a singlerdflib.Graph, materializes YAML frontmatter as queryable RDF triples (status, tags, assignee, numeric ID, dependencies, priority rank) - NL Decomposer — Rule-based extraction of structured filters (status, type, ID range, assignee, tag) from natural language; remainder drives semantic ranking
- Embedding Index — Semantic search using
sentence-transformerswith hash-based disk cache in.yurtle-kanban/embeddings/ - Hybrid Ranker — SPARQL narrows candidates, embeddings rank by cosine similarity to semantic intent
- Optional dependency groups —
pip install yurtle-kanban[search]for embeddings,[llm]for Claude API (future),[all]for everything - Python API —
QueryEngine,UnifiedGraph,EmbeddingIndex,NLDecomposerall importable fromyurtle_kanban - Full query documentation — docs/query.md with predicate reference, SPARQL examples, architecture diagram, and Python API guide
Example
yurtle-kanban query "not-done expeditions above 700 that improve brain functioning"
# Decomposes into: status != done, type = expedition, numericId > 700
# Then ranks remaining items by semantic similarity to "improve brain functioning"
v1.15.0 (2026-03-04)
Config-driven transition gates, priority filter on list.
Added
- Config-driven transition gates for the
movecommand (#53) --priorityfilter on thelistcommand (#52)
v1.14.0 (2026-03-03)
Auto-close on PR merge, security hardening, HDD methodology docs.
Added
- Auto-close kanban items on PR merge — Reusable GitHub Actions workflow
kanban-auto-close.ymlextracts item IDs from PR body keywords (Closes EXP-1023,Fixes CHORE-055) and branch names (exp-1023-*), then moves items to target status (#28, #48) --closed-byflag onmove— Records graph provenance (kb:closedBy <PR-URL>) in the TTL status history block, making PR→item closure relationships queryable (#28)pr_id_extractormodule — Testable Python helper for extracting kanban item IDs from PR bodies and branch names. Supports all 17 item prefixes (#28)--boardoption onlist— Filter items by board name in multi-board configurations (#45)compute_requirementfield — First-class field on work items for compute resource tracking (#44)- HDD
critical-pathcommand — Cross-board dependency engine for research item chains (#43) - HDD methodology guide — Full reference docs with worked examples and fleet automation (#46)
Security
- GitHub Actions SHA pinning — All 10 actions pinned to commit SHAs instead of floating version tags (#49)
- TTL injection prevention —
_validate_turtle_local_name()for prefixed names,_safe_uri()for angle-bracket URIs (#49) - HTML export XSS prevention —
html.escape()applied to all user-controlled values in HTML export (#49) - YAML frontmatter escaping — Title values escaped in
to_markdown()(#49) expr_idpath traversal validation — Regex validation before filesystem path construction (#49)closed_byURI sanitization — Rejects<,>, whitespace, backslash, and quote characters in URIs (#48)- Workflow script injection prevention — PR body passed via env var instead of
${{ }}interpolation (#49) - Least-privilege permissions —
contents: readadded to CI workflow (#49)
Fixed
- HDD state name preservation — Move write-back preserves original HDD state names (#42)
v1.13.0 (2026-02-28 → 2026-03-01)
Experiment run tracking, HDD registry & validation, priority ranking, board-aware move.
Added
experiment runcommand — Create timestamped run folders underresearch/runs/EXPR-ID/withconfig.yamlcontaining being, params, status. Supports--pushfor atomic commit (#40)experiment statuscommand — Show all runs for an experiment in a Rich table or--jsonoutput. Readsconfig.yaml+ optionalmetrics.jsonper run (#40)hdd registrycommand — Generate a cross-referencedREGISTRY.mdwith tables for papers, hypotheses, experiments, measures, ideas, literature, and orphaned items (#40)hdd validatecommand — Check bidirectional links (paper↔hypothesis↔experiment), detect broken references, unused measures, orphaned items.--stricttreats warnings as errors.--jsonfor CI (#40)hdd backfillcommand — Scan all HDD files, build expected RDF triples from frontmatter, diff against existing graph, and insert only missing triples as a fenced turtle block. Supports--dry-runfor preview. Idempotent at the triple level (#33)- Partial block consolidation — When backfilling a file that already has a turtle block, missing triples are merged into the existing block instead of appending a second one (#34)
priority_rankfield — Explicit priority rank (lower = higher priority) on work items.rankcommand to set rank + value summary (#39)roadmap --rankedoutput — Roadmap view sorts by priority rank when available (#39)- Board-aware
movecommand — Resolves correct theme (nautical vs HDD) per item type, applies per-board WIP limits, supports HDD column aliases (CHORE-079) - Highest-ID-first sorting —
listandboardcommands now sort items by descending numeric ID by default (#38)
Fixed
- Paper field normalization —
_normalize_paper_num()uses regex to handle130,Paper130,paper130,PAPER130correctly. Replaces fragilestr.replace("Paper", "")(#34) __init__.pyversion sync — Now matchespyproject.toml(was stuck at 1.11.0 since v1.12.0 release)- File routing in v2 mode —
BoardConfig.scan_pathsproperly parsed and aggregated in_load_v2. Irregular plural map handleshypothesis→hypotheses(#35) - HDD column-to-status mappings — Research board columns correctly map to HDD statuses (CHORE-079)
- Ruff lint — All lint errors resolved across
src/(CHORE-079)
v1.12.0 (2026-02-28)
Graph-native knowledge blocks and research tooling.
Added
- Multi-board support — Run multiple kanban boards in one repo (
board-add,board research,board --all,boards). Each board has its own theme, paths, and columns (#14) - HDD (Hypothesis-Driven Development) theme — Full research workflow: Idea → Literature → Paper → Hypothesis → Experiment → Measure. Preset available via
board-add --preset hdd(#14) - HDD CLI commands — Dedicated subcommands for research items:
idea create,literature create,paper create,hypothesis create,experiment create,measure create. Auto-allocate IDs, link relationships, support--push(#16) - HDD Claude Code skills —
/idea,/literature,/paper,/hypothesis,/experiment,/measureskills for AI agent workflows - Turtle knowledge blocks — HDD items get fenced
```turtleblocks with RDF triples expressing research relationships (hyp:paper,hyp:measuredBy,expr:hypothesis, etc.) (#25) - Campaign CLI —
voyage create/show/add(nautical) andepic create/show/add(software) for managing multi-item initiatives.board --campaign VOY-XXXfor filtered views (#24) - Research interlinks in
voyage show— When a voyage links HDD items,voyage showdisplays a Research Interlinks section with hypothesis targets, experiment status, and measure metadata parsed from Turtle blocks (#30) - Auto-update parent knowledge blocks — Creating a child item (hypothesis, experiment, literature) automatically adds an inverse RDF triple to the parent's Turtle block using rdflib (#31)
WorkItem.graph— Every work item now carries anrdflib.Graphwith triples from both YAML frontmatter and fenced Turtle blocks, queryable via SPARQL (#29)- Event-driven hooks —
kanban-hooks.yurtle.mdwithcreate_itemandnotifyactions, recursion guard, event wiring (#15, #17)
Changed
- rdflib is required — yurtle-kanban is a graph-native product. Importing without rdflib/yurtle-rdflib raises
ImportErrorwith a friendly message (#27) - Shared data resolution — Templates and themes resolve via
sys.prefixfor pip-installed environments (#19, #20, #23)
Fixed
- HDD item type routing in multi-board mode (#20)
- Template path resolution for pip-installed packages (#19)
v1.11.0
--jsonflag —showandvalidatecommands support--jsonoutput (#13)
v1.10.0
- Fail-closed rule evaluation — Unknown workflow conditions fail closed (deny) instead of open. Resolution fields (
resolution,superseded_by) for done items.--forcemoves are audited withkb:forcedMovein RDF status history (#11) - CLAUDE.md — Developer practices and PR workflow documentation
v1.9.0
- Theme-specific skills — Skills are now organized by theme (
skills/nautical/,skills/software/). Software theme gets/feature,/work,/done,/review,/handoff,/blockedwith FEAT-prefixed terminology. Theme-neutral skills (/sync,/status,/release) stay shared. - Auto-install skills on init —
yurtle-kanban initnow copies theme-matched skills to.claude/skills/automatically create --pushno-remote fix — Gracefully degrades to local commit when no git remote is configured (v1.8.1)
v1.8.0
create --push— Atomic create: fetch → allocate → create file → commit → push, with retry on conflict. Eliminates ID race conditions in multi-agent workflows.- Agent Instructions — README now includes a copyable CLAUDE.md snippet for AI agent projects
v1.7.0
initscaffolding — Creates type-specific directories with_TEMPLATE.mdfiles, auto-populatesscan_pathsin config (#7)roadmapcommand — Prioritized view of non-done items with--by-type,--type,--export md,--json(#1)historycommand — Completed work log with--week,--month,--since,--by-assignee,--by-type(#2)
v1.6.0
next-idfix — Now reads_ID_ALLOCATIONS.jsonas source of truth (was only scanning filesystem) (#8)createfile placement — Items go into theme-defined type directories (e.g.,kanban-work/expeditions/) with slugified filenames (#9)- Theme
path:field — Both nautical and software themes define explicit paths per item type (#10) - 17 new tests for ID allocation, file placement, slug generation, and directory resolution
v1.5.0
- Flow metrics with TTL status history tracking (
metricscommand) --forceflag onmoveto skip WIP limit checks- Increased WIP limits in nautical theme
v1.4.0
--assignand--export-boardoptions onmovecommand- Expedition-index export format with Work Trail and Dependency Tree
v1.3.0
- Expedition-index export format
v1.2.0
/releaseskill for semantic versioning- Modern Python 3.10+ type hints
v1.1.0
- Claude Code skills for multi-agent workflows (
/sync,/work,/done,/expedition, etc.)
v1.0.0
- Initial release: CLI, board, list, create, move, show, stats, next-id, export, validate, MCP server
Related Projects
- Yurtle Specification - Turtle RDF in Markdown
- yurtle-rdflib - RDFlib parser plugin
- nusy-nano - Neurosymbolic reasoning
License
MIT License - see LICENSE for details.
Metadata
Release files for yurtle-kanban 3.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| yurtle_kanban-3.0.0.tar.gz | 290.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| yurtle_kanban-3.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 609.7 kB
Release files / yurtle_kanban-3.0.0.tar.gz
| Download URL | yurtle_kanban-3.0.0.tar.gz |
|---|---|
| Size | 290.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
01031d17c59ae19df7b3df91f43e7e66172c9ab05d4caadacb6c671559c8b633
|
|
BLAKE2b-256 checksum How to use checksums |
8a1564849aecf0fb28f2a08c6704ddde0d34115638e2bb14bf4f762780d04742
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / yurtle_kanban-3.0.0-py3-none-any.whl
| Download URL | yurtle_kanban-3.0.0-py3-none-any.whl |
|---|---|
| Size | 319.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6fbebc017ae0cdee5dca9bdb40e5bd28eb5b2e9b6af4d1991eb72007944c5709
|
|
BLAKE2b-256 checksum How to use checksums |
c1467a3c611c699294dba5ff72c4579b2c7688c218e0ee92f6e64130112b66f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log