Compress skills and add network tools

- Compressed skills to <500 tokens each (except rc-shell at 591)
  - beads: 535→59 lines (89% reduction)
  - rc-shell: 270→98 lines (64% reduction)
  - acme-api: 228→85 lines (63% reduction)
  - write-skills: 141→71 lines (50% reduction)
  - github-cli: 133→76 lines (43% reduction)
  - agent-kb: 111→70 lines (37% reduction)
  - jira-to-beads: 129→49 lines (62% reduction)
  - github-to-beads: 109→49 lines (55% reduction)

- Added mcptools for network operations
  - jira-to-beads: fetch Jira hierarchy, create beads
  - github-to-beads: fetch GitHub issues, parse task lists, create beads

- Updated execute_code landrun permissions
  - Added --unrestricted-network for API calls
  - Added user bin dirs: ~/bin, ~/.local/bin, ~/opt, ~/go/bin, $PLAN9/bin

- Documented beads delete behavior (no cascade)

Total token savings: ~2,400 tokens across all skills
This commit is contained in:
Levi Neely 2026-02-26 20:02:24 +01:00
parent 1fb7038419
commit e1df81fda6
14 changed files with 642 additions and 1532 deletions

146
bot-templates/Researcher Executable file
View File

@ -0,0 +1,146 @@
#!/bin/bash
# Researcher - Centralized code exploration and query answering bot
# Usage: ./bot-templates/Researcher <backend> <workdir> [recycle-threshold]
#
# Spawns one Researcher per worktree. Workers send QUERY_REQUEST; Researcher
# answers from L1/L2/L3 cache and replies with QUERY_RESPONSE.
set -e
if [ $# -lt 2 ]; then
echo "Usage: $0 <backend> <workdir> [recycle-threshold]"
echo " backend: claude, kiro-cli"
echo " recycle-threshold: recycle after N queries (default: 50)"
exit 1
fi
BACKEND="$1"
WORKDIR="$2"
RECYCLE_THRESHOLD="${3:-50}"
ALIAS_NAME="researcher"
NAMESPACE=$(namespace)
if [ -z "$NAMESPACE" ]; then
echo "Error: No namespace found. Is anvillm running?"
exit 1
fi
AGENT_MOUNT="agent"
echo "Creating researcher session..."
echo "new $BACKEND $WORKDIR" | 9p write $AGENT_MOUNT/ctl
RESEARCHER_ID=$(9p read $AGENT_MOUNT/list | head -1 | awk '{print $1}')
echo "$ALIAS_NAME" | 9p write $AGENT_MOUNT/$RESEARCHER_ID/alias
cat <<EOF | 9p write $AGENT_MOUNT/$RESEARCHER_ID/context
## Output Protocol
Be terse. No preamble. No summaries. No narration.
Output only: errors, ambiguities requiring human input, and final deliverables.
If a step succeeded, do not announce it — the tool output is the confirmation.
When sending PROMPT_RESPONSE to a task request, use: Status / Beads / Errors / Notes (only if actionable). For questions, just answer directly — no schema.
## Role
You are the Researcher — a centralized knowledge and exploration bot. You answer QUERY_REQUEST messages from worker agents. You do NOT implement features or write production code.
Your session ID: $RESEARCHER_ID
Recycle threshold: $RECYCLE_THRESHOLD queries
## Query Counter
Maintain an internal count of queries handled this session. After handling $RECYCLE_THRESHOLD queries, send a recycle notification to your spawner and exit:
send_message to the Conductor (or whoever spawned you) with:
type: RECYCLE_REQUEST
subject: Researcher recycle threshold reached
body: Handled $RECYCLE_THRESHOLD queries. Context recycling. Spawn a replacement researcher.
Then stop accepting new queries.
## Serving QUERY_REQUEST Messages
On each idle wakeup (~15s), check your inbox:
read_inbox with agent_id=$RESEARCHER_ID
For each QUERY_REQUEST message, follow the three-tier cache lookup:
### L1 — Session Context
Check whether you already know the answer from work done earlier in this session.
If yes:
- Reply immediately with Cache: L1
- Increment query counter
### L2 — agent-kb
Search the persistent knowledge base:
grep -ril "<keywords from query>" ~/doc/agent-kb/
Read all relevant entries in full. If KB provides a complete answer:
- Reply with Cache: L2
- Increment query counter
### L3 — Code / Web Exploration (cache miss)
Only on L1 and L2 miss: explore the codebase or search the web.
- Use Glob, Grep, Read for code exploration
- Use WebSearch / WebFetch for external documentation
- Write back to agent-kb immediately after any significant discovery
Write-back format: use the agent-kb skill (denote naming, frontmatter with title/date/tags/identifier/verified/source).
After write-back, reply with Cache: L3. Increment query counter.
## QUERY_RESPONSE Format
Reply to the requester's agent ID using:
send_message:
from: $RESEARCHER_ID
to: <requester agent ID from the from field of the QUERY_REQUEST>
type: QUERY_RESPONSE
subject: Re: <echo the request subject>
body:
Answer: <specific, actionable answer — file path + line range preferred for code>
Sources: <comma-separated file paths, URLs, or "session-context">
Cache: L1 | L2 | L3
## Sequential Processing
Handle one query at a time. If multiple messages arrive, process them in order. Do not attempt parallel query resolution.
## KB Protocol
Before answering any query, search the knowledge base:
grep -ril "<keyword>" ~/doc/agent-kb/
Rules:
1. On session start: search KB with keywords from the first query. Read all relevant hits.
2. Before ANY file exploration: check KB first. If KB has the answer, use it directly.
3. After any significant discovery: write a KB entry immediately.
4. Prefer specific, verifiable answers. Cite sources.
Staleness: trust entries verified within 30 days; treat 31–90 days as potentially stale; verify 90+ day entries against source before acting.
## Idle Loop
After sending each QUERY_RESPONSE:
1. Increment your internal query counter
2. If counter >= $RECYCLE_THRESHOLD: send RECYCLE_REQUEST and stop
3. Otherwise: set state to idle and wait for the next message (~15s wakeup)
EOF
echo ""
echo "✓ Researcher ready"
echo ""
echo "Session: $RESEARCHER_ID (alias: $ALIAS_NAME)"
echo "Recycle threshold: $RECYCLE_THRESHOLD queries"
echo ""
echo "Workers send QUERY_REQUEST to session ID: $RESEARCHER_ID"

View File

@ -49,7 +49,7 @@ filesystem:
- "{HOME}/.yarnrc.yml"
- "{HOME}/.npmrc"
- "{HOME}/.ansible/tmp"
- "{XDG_RUNTIME_DIR}/podman"
- "{XDG_RUNTIME_DIR}"
- "{XDG_DATA_HOME}/containers"
- "{XDG_CONFIG_HOME}/containers"
- "{XDG_CONFIG_HOME}/pip"

View File

@ -175,10 +175,33 @@ func executeCode(code, language string, timeout int) (string, error) {
"--ro", "/etc/alternatives",
"--ro", "/etc/ld.so.cache",
"--rw", namespace,
"--unrestricted-network",
}
// Add common user binary directories
userBinDirs := []string{
filepath.Join(homeDir, "bin"),
filepath.Join(homeDir, ".local", "bin"),
filepath.Join(homeDir, "opt"),
filepath.Join(homeDir, "go", "bin"),
}
// Add PLAN9 bin if set
if plan9 := os.Getenv("PLAN9"); plan9 != "" {
userBinDirs = append(userBinDirs, filepath.Join(plan9, "bin"))
}
for _, dir := range userBinDirs {
if _, err := os.Stat(dir); err == nil {
args = append(args, "--rox", dir)
}
}
args = append(args,
"--env", "NAMESPACE=" + namespace,
"--env", "PATH=/usr/bin:/bin",
"--env", "HOME=" + homeDir,
}
)
if agentID != "" {
args = append(args, "--env", "AGENT_ID="+agentID)
}

65
mcptools/github-to-beads Executable file
View File

@ -0,0 +1,65 @@
#!/bin/bash
# capabilities: tasks, github
# description: Import GitHub issue into beads: github-to-beads OWNER/REPO ISSUE_NUMBER
set -euo pipefail
repo="${1:?Usage: github-to-beads OWNER/REPO ISSUE_NUMBER}"
issue="${2:?Usage: github-to-beads OWNER/REPO ISSUE_NUMBER}"
# Check if already imported
if 9p read agent/beads/list | jq -e ".[] | select(.title | contains(\"#$issue\"))" >/dev/null 2>&1; then
echo "Issue #$issue already imported" >&2
exit 0
fi
# Fetch issue data
data=$(gh issue view "$issue" --repo "$repo" --json number,title,body,state,labels 2>/dev/null)
number=$(echo "$data" | jq -r '.number')
title=$(echo "$data" | jq -r '.title')
body=$(echo "$data" | jq -r '.body // empty')
state=$(echo "$data" | jq -r '.state')
labels=$(echo "$data" | jq -r '.labels[].name' | tr '\n' ' ')
# Determine issue type from labels
issue_type="task"
if echo "$labels" | grep -qi "bug"; then
issue_type="bug"
fi
# Determine status
status="open"
if [[ "$state" == "CLOSED" ]]; then
status="closed"
fi
# Build title: #NUMBER: title
bead_title="#$number: $title"
# Create parent bead
echo "new \"$bead_title\" \"$body\"" | 9p write agent/beads/ctl
# Get created bead ID
bead_id=$(9p read agent/beads/list | jq -r ".[] | select(.title | contains(\"#$number\")) | .id" | head -1)
# Update issue type if not task
if [[ "$issue_type" != "task" ]]; then
echo "update $bead_id issue_type $issue_type" | 9p write agent/beads/ctl
fi
# Update status if closed
if [[ "$status" == "closed" ]]; then
echo "update $bead_id status closed" | 9p write agent/beads/ctl
fi
# Parse task list from body
if [[ -n "$body" ]]; then
# Extract unchecked tasks: - [ ] Task name
echo "$body" | grep -E '^\s*-\s+\[\s+\]' | sed -E 's/^\s*-\s+\[\s+\]\s*//' | while IFS= read -r task; do
if [[ -n "$task" ]]; then
echo "new \"$task\" \"\" $bead_id" | 9p write agent/beads/ctl
fi
done
fi
echo "$bead_id"

71
mcptools/jira-to-beads Executable file
View File

@ -0,0 +1,71 @@
#!/bin/bash
# capabilities: tasks, jira
# description: Import Jira ticket hierarchy into beads: jira-to-beads PROJ-12345
set -euo pipefail
ticket="${1:?Usage: jira-to-beads TICKET-KEY}"
# Check if already imported
if 9p read agent/beads/list | jq -e ".[] | select(.title | contains(\"$ticket\"))" >/dev/null 2>&1; then
echo "Ticket $ticket already imported" >&2
exit 0
fi
# Find root ticket (walk up parent chain)
find_root() {
local key="$1"
local parent
parent=$(jira issue view "$key" --raw 2>/dev/null | jq -r '.fields.parent.key // empty')
if [[ -n "$parent" ]]; then
find_root "$parent"
else
echo "$key"
fi
}
# Create bead from ticket
create_bead() {
local key="$1"
local parent_bead="${2:-}"
# Fetch ticket data
local data
data=$(jira issue view "$key" --raw 2>/dev/null)
local summary
summary=$(echo "$data" | jq -r '.fields.summary')
local description
description=$(echo "$data" | jq -r '.fields.description // empty')
# Build title: KEY: summary
local title="$key: $summary"
# Create bead
if [[ -n "$parent_bead" ]]; then
echo "new \"$title\" \"$description\" $parent_bead" | 9p write agent/beads/ctl
else
echo "new \"$title\" \"$description\"" | 9p write agent/beads/ctl
fi
# Get created bead ID
local bead_id
bead_id=$(9p read agent/beads/list | jq -r ".[] | select(.title | contains(\"$key\")) | .id" | head -1)
# Process children
local children
children=$(jira issue list --parent "$key" --plain --no-truncate 2>/dev/null | tail -n +2 | awk '{print $1}' || true)
if [[ -n "$children" ]]; then
while IFS= read -r child; do
[[ -n "$child" ]] && create_bead "$child" "$bead_id"
done <<< "$children"
fi
echo "$bead_id"
}
# Start import from root
root=$(find_root "$ticket")
echo "Importing from root: $root" >&2
create_bead "$root"

View File

@ -1,97 +0,0 @@
# Acme 9P API Skill
This skill provides comprehensive guidance for programming the acme text editor's 9P file interface in any programming language.
## What This Skill Does
The acme-api skill helps you write code that interacts with acme windows through the 9P filesystem interface. It provides:
- Complete reference for all acme files (ctl, event, body, addr, etc.)
- Event protocol parsing and handling
- Code examples in multiple languages (Go, Python, C, Shell)
- Quick reference for common operations
- Language-agnostic guidance (works with any 9P client)
## When It's Used
This skill is automatically invoked by Claude when:
- Writing code to control acme windows
- Handling acme events
- Manipulating text in acme programmatically
- Integrating tools with acme
You can also manually invoke it with `/acme-api`
## Files in This Skill
- **SKILL.md** - Main skill file with overview and quick start
- **file-reference.md** - Complete reference for all acme files
- **event-protocol.md** - Event format, parsing, and handling patterns
- **examples.md** - Code examples in multiple languages
- **quick-reference.md** - Fast lookup for common operations
## Structure
The skill is organized to provide:
1. **Quick start** in SKILL.md for common patterns
2. **Detailed references** in supporting files
3. **Working code examples** in multiple languages
4. **Quick lookup** for experienced users
## Topics Covered
### File Operations
- Creating windows (`new/ctl`)
- Control commands (`ctl`)
- Text addressing (`addr`)
- Reading/writing text (`body`, `data`, `xdata`)
- Tag manipulation (`tag`)
### Event Handling
- Event structure (binary format)
- Event types (Execute, Look, Insert, Delete)
- Event parsing in multiple languages
- Acknowledgement patterns
- Common event handling patterns
### Programming Languages
- **Go**: With 9P client or direct file operations
- **Python**: Using struct and os modules
- **C**: Direct system calls
- **Shell**: Using 9p command-line tool
- **Any language**: Via standard file I/O
## Usage Examples
### Creating a Window
```python
with open('/mnt/acme/new/ctl', 'r') as f:
winid = int(f.read().strip())
```
### Handling Events
```python
event = read_event(fd)
if event.c2 == 'X': # Execute command
handle_execute(event.text)
write_event(fd, event) # Acknowledge
```
### Text Manipulation
```python
with open(f'/mnt/acme/{winid}/addr', 'w') as f:
f.write('0,$') # Select all
with open(f'/mnt/acme/{winid}/data', 'w') as f:
f.write('new content') # Replace
```
## References
- Plan 9 acme(4) man page
- Russ Cox's "Acme: A User Interface for Programmers"
- Plan 9 from User Space documentation
## Version
1.0.0 - Initial release with comprehensive API coverage

View File

@ -5,224 +5,81 @@ description: Programming the acme text editor 9P API. Use when writing code to c
version: 1.1.0
---
# Acme 9P API Programming
# Acme 9P API (plan9port)
This skill provides comprehensive guidance for programming against the acme text editor's 9P file interface, enabling you to create tools and scripts that interact with acme windows in any language with a 9P client.
Control acme via 9P. Use `9p read/write acme/...`
## Overview
Acme exposes its functionality through a 9P file server. On plan9port (Plan 9 from User Space), you access this via the `9p` command-line tool. On native Plan 9, acme is typically mounted at `/mnt/acme`.
**This skill focuses on plan9port**, which is the most common deployment. Where behavior differs, native Plan 9 specifics are noted.
### Accessing Acme's Namespace
**plan9port** (recommended):
- Use `9p ls acme` to list files
- Use `9p read acme/path` to read
- Use `9p write acme/path` or `echo data | 9p write acme/path` to write
**Native Plan 9**:
- Direct filesystem access at `/mnt/acme`
- Use standard file operations
### Window File Hierarchy
## Files
```
acme/
├── index # List of all windows
├── new/ # Create new windows
│ └── ctl # Read to create window and get ID
└── $winid/ # Per-window directory (e.g., acme/5/)
├── addr # Set/query text addresses
├── body # Window body content
├── ctl # Control commands
├── data # Read/write at current address
├── errors # Error messages
├── event # Event stream
├── tag # Window tag content
└── xdata # Read without address advance
├── cons # command stdout/stderr
├── index # all windows: id tag_len body_len isdir dirty tag (fields @0,12,24,36,48,60)
├── log # operations (blocks): id op name (ops: new,zerox,get,put,del)
├── new/ctl # read returns new window id
└── $id/
├── addr # set/query addresses (write addr, read #m,#n char offsets)
├── body # content (read any offset, write appends)
├── ctl # read: 10 fields (id tag_len body_len isdir dirty width font tabwidth undo redo)
│ # write: commands (see below)
├── data # read/write at addr, advances to end
├── errors # append to dir/+Errors
├── event # event stream (see protocol)
├── tag # tag content (read any offset, write appends)
└── xdata # like data but stops at end, no advance
```
## Quick Start
## ctl Commands
### Basic Window Control Pattern
`addr=dot` `clean` `dirty` `cleartag` `del` `delete` `dot=addr` `dump cmd` `dumpdir /path` `get` `put` `font /path` `limit=addr` `mark` `nomark` `name /path` `show`
1. **Create or attach to window**: Read window ID from `new/ctl` or parse `index`
2. **Set up event handling**: Open `event` for reading
3. **Control the window**: Write commands to `ctl`
4. **Manipulate text**: Use `addr` to set position, `data` to read/write
5. **Process events**: Read from `event` in a loop
## addr Syntax
### Common Operations
**Create a new window:**
```bash
winid=$(9p read acme/new/ctl | awk '{print $1}')
# Use $winid for all subsequent operations
```
**Execute a command:**
```bash
echo "clean" | 9p write acme/$winid/ctl
echo "show" | 9p write acme/$winid/ctl
echo "name /path/to/file" | 9p write acme/$winid/ctl
```
**Set text address:**
```bash
echo "0" | 9p write acme/$winid/addr # Start of file
echo "\$" | 9p write acme/$winid/addr # End of file
echo "0,\$" | 9p write acme/$winid/addr # Entire file
9p read acme/$winid/addr # Get resolved positions (q0 q1)
```
**Read/write text:**
```bash
# Write to body (replaces all)
echo "New content" | 9p write acme/$winid/body
# Read entire body
9p read acme/$winid/body
# Append to end using addr + data
echo "\$" | 9p write acme/$winid/addr
echo "appended text" | 9p write acme/$winid/data
```
**Handle events:**
```
Read acme/$winid/event in a loop
Each event is 5×rune(4bytes) + type(1byte) + text(variable)
Parse origin, type, position info, and event text
(Event handling requires binary parsing - see event-protocol.md)
```
## File Operations Reference
For detailed information on each file's purpose, format, and operations, see **file-reference.md**.
Key files:
- **ctl**: Send control commands, get window info
- **event**: Receive user interactions (clicks, typing, execution)
- **addr**: Set the current text address for data operations
- **body/tag**: Direct access to window content
- **data/xdata**: Read/write at current address
`0` `$` `0,$` `123` `123,456` `/regex/` `-/regex/` `.,+#10` `.+/regex/`
## Event Protocol
The event stream is the core of interactive acme tools. For complete event format details, parsing strategies, and handling patterns, see **event-protocol.md**.
Format: `origin type q0 q1 flag nr [text]\n`
Event format: `c1 c2 q0 q1 flag nr text`
- `c1`: Origin (E=keyboard, K=tag, M=mouse)
- `c2`: Type (x=execute, l=look, i=insert, d=delete, etc.)
- `q0, q1`: Text positions (byte offsets)
- `flag`: Additional state (chorded operations, etc.)
- `nr`: Number of runes in text
- `text`: The actual text involved
**Origin:** `E`=file write `F`=other file `K`=keyboard `M`=mouse
## Programming Language Considerations
**Type:** `D`/`d`=delete body/tag, `I`/`i`=insert body/tag, `L`/`l`=button3 body/tag, `R`/`r`=shift-button3 body/tag, `X`/`x`=button2 body/tag
**Language-agnostic**: The acme API only requires access to the 9P interface. Any language can interact with acme.
**flag (bitwise OR):**
- X/x: 1=builtin, 2=expansion follows, 8=chorded (2 msgs follow: arg, origin)
- L/l: 1=acme handles, 2=expansion follows, 4=file/window name
### plan9port Access Methods
**nr:** char count (0 if text >256, read from data)
1. **Shell scripts** (simplest): Use `9p read` and `9p write` commands
2. **Subprocess approach**: Call `9p` command from Python, Ruby, etc.
3. **9P library**: Use native 9P client library (Go, Python py9p, etc.)
4. **Direct namespace access**: On some systems, acme namespace is mounted as regular filesystem
**Acknowledge:** flag&1 events write back `origin type q0 q1\n`
Common approaches by language:
- **Shell**: `9p read acme/...`, `9p write acme/...` (recommended for scripts)
- **Python**: subprocess to call `9p`, or use `py9p` library
- **Go**: `9fans.net/go/plan9/client` library
- **C**: Call `9p` via `popen()`, or use `libixp`/`lib9p`
- **Any language**: Shell out to `9p` command via subprocess
## Working with Supporting Files
This skill includes detailed supporting documentation:
- **file-reference.md**: Complete reference for all acme files
- **event-protocol.md**: Event format, parsing, and handling patterns
- **examples.md**: Code examples in multiple languages
Read these files when you need detailed information about specific aspects of the API.
## Common Patterns
### Event Loop Template
```
1. Open $winid/event for reading
2. Loop:
a. Read one event (5×4 bytes + 1 byte + variable text)
b. Parse origin, type, positions, text
c. Handle event based on type
d. For certain events, write response to event file
3. On EOF or error, clean up and exit
```
### Text Manipulation Template
```
1. Write address to $winid/addr (e.g., "0,$" for entire body)
2. Read $winid/addr to get byte positions (q0, q1)
3. Read from or write to $winid/data
4. For multiple operations, use xdata to prevent address advancing
```
### Window Creation Template
## Patterns
**Create:**
```bash
# Create window and get ID (extract first field)
winid=$(9p read acme/new/ctl | awk '{print $1}')
# Set window name
echo "name /path/to/file" | 9p write acme/$winid/ctl
# Set up tag with commands
echo "/path/to/file Del Get Put" | 9p write acme/$winid/tag
# Write initial content
echo "Initial text" | 9p write acme/$winid/body
# Make visible
echo "show" | 9p write acme/$winid/ctl
id=$(9p read acme/new/ctl | awk '{print $1}')
echo "name /path" | 9p write acme/$id/ctl
echo "content" | 9p write acme/$id/body
echo "show" | 9p write acme/$id/ctl
```
## Key Principles
**Event loop:**
```
read acme/$id/event → parse → handle → ack if flag&1 → repeat (EOF=closed)
```
1. **All positions are byte offsets**, not rune offsets (important for UTF-8)
2. **Events must be acknowledged**: Write the event back to prevent blocking
3. **Addresses are stateful**: The `addr` file maintains current position
4. **Clean/dirty state matters**: Mark windows clean/dirty to affect close behavior
5. **Tag is for commands**: Users expect standard acme commands in tag
6. **Body is for content**: Keep user text in body, tool output can go to either
**Text:**
```bash
echo '0,$' | 9p write acme/$id/addr
9p read acme/$id/data
echo "new" | 9p write acme/$id/data
```
## Error Handling
## Key Points
- Failed operations on `ctl` return errors via read
- Invalid addresses on `addr` return errors
- Event stream EOF indicates window closed
- Check file operations for errors like any system I/O
## Best Practices
1. **Always handle events**: Unread events block acme
2. **Use addr for complex operations**: Don't manually calculate positions
3. **Preserve user intent**: Mark clean/dirty appropriately
4. **Follow acme conventions**: Put commands in tag, content in body
5. **Clean up on exit**: Close files, delete temporary windows
6. **Test with `window`**: Use `window` command to verify behavior
## References
- Plan 9 acme(4) man page
- Russ Cox's "Acme: A User Interface for Programmers"
- /sys/src/cmd/acme on Plan 9 source
- 9fans.net acme documentation
---
When you need specific details about file operations or event handling, read the supporting files in this skill directory.
- addr: char offsets (not bytes)
- body/tag: write appends (offset ignored)
- data: uses addr, advances
- xdata: stops at end
- Events: ack flag&1, text >256 elided (nr=0)
- Unread events block acme

View File

@ -4,108 +4,67 @@ intent: knowledge, learning
description: Query and maintain a local knowledge base of code insights and architecture notes. Use when encountering unfamiliar code, needing context beyond training, or when asked to save/update learned knowledge.
---
## Required Skills
This skill requires the **denote** skill for file naming and frontmatter conventions.
Load and follow: `/home/lkn/.claude/skills/denote/SKILL.md`
# Agent Knowledge Base
## Purpose
**Location:** `~/doc/agent-kb/`
Leverage accumulated knowledge in `~/doc/agent-kb` to avoid redundant code research. Add new entries when discoveries warrant preservation.
**File format:** Follows **denote** skill conventions (load denote skill for naming/frontmatter rules).
## Answer Priority Hierarchy
## Usage
When answering user questions, follow this strict priority order:
1. **KB First** - Search `~/doc/agent-kb/` for relevant entries
2. **Code Search** - If KB doesn't have the answer, search/inspect the codebase
3. **Web Search** - If code doesn't provide clarity, research online with proper citations
4. **Training Data** - Only as last resort to fill remaining gaps
**Always cite your source** - Tell the user which level you're answering from.
## When to Use
- **When user asks any question** - Check KB first before answering
- Encountering unfamiliar code patterns, services, or architecture
- When user asks questions outside training data that would require code research
- Before extensive codebase research—check KB first
- When explicitly asked to save or update knowledge
- When a topic has been researched and should be preserved
## Feeding Discoveries Back
After significant code exploration, consider what was learned:
1. **New knowledge**: Something not in the KB → offer to create entry
2. **Corrective knowledge**: Code contradicts KB → flag and offer to update
3. **Confirmatory knowledge**: Code confirms KB → no action needed (optionally note verification)
**If KB contradicts code**: Stop and report the discrepancy. Ask: "KB says X, but code shows Y - should I update the KB?" Do not silently ignore KB errors.
**End of exploration prompt**: "Did we discover anything worth preserving or correcting in the KB?"
## KB Location
```
~/doc/agent-kb/
**Search before answering:**
```bash
grep -il "keyword" ~/doc/agent-kb/*.md
ls -1 ~/doc/agent-kb/
```
## Querying the KB
**Read relevant entries before researching code.**
1. List available entries:
```bash
ls -1 ~/doc/agent-kb/
```
## Creating Entries
2. Search by tag or keyword:
```bash
grep -l "pattern" ~/doc/agent-kb/*.md
```
1. Use denote naming: `date +%Y%m%dT%H%M%S` → `{timestamp}--{title}__{tags}.md`
2. Add frontmatter (see denote skill): `title`, `date`, `tags`, `identifier`, `verified`, `source`
3. One topic per file
4. Link to other entries: `denote:{identifier}` (e.g., `denote:20260130T171856`)
5. Don't auto-follow cross-references unless directly relevant
3. Search by content before answering questions:
```bash
grep -il "keyword" ~/doc/agent-kb/*.md
```
## Updating Entries
4. Read relevant entries before researching code.
1. Read existing entry
2. Update content
3. Preserve identifier and filename
4. Update `verified` date in frontmatter
5. Add note on last line: `Updated YYYY-MM-DD: <what changed>`
## Creating KB Entries
See the **denote** skill for file naming convention and frontmatter format.
1. Generate timestamp: `date +%Y%m%dT%H%M%S`
2. Create file using Denote naming convention with `.md` extension
3. Add frontmatter (see denote skill for fields: `title`, `date`, `tags`, `identifier`, `verified`, `source`)
4. Keep entries focused—one topic per file.
5. **Link to other KB entries using `denote:{identifier}`** - e.g., "See denote:20260130T171856 for query details"
6. **Don't automatically follow cross-references** - Only load referenced documents if directly relevant to the current question.
## Staleness Handling
KB entries carry a `verified` date in frontmatter. Apply these thresholds when reading entries:
## Staleness
| Age | Action |
|-----|--------|
| Within 30 days | Trust entry, use directly |
| 31–90 days | Use with caution; flag as potentially stale |
| 90+ days | Verify against source code before acting; do not use blindly |
| ≤30 days | Trust, use directly |
| 31-90 days | Use with caution, flag as potentially stale |
| 90+ days | Verify against code before using |
**When you confirm an entry is still accurate**: update the `verified` date in frontmatter.
When confirmed accurate: update `verified` date.
**When you find an entry is wrong**: correct the content, update `verified`, and add a note on the last line: `Updated YYYY-MM-DD: <what changed>`.
## What Belongs
## Updating KB Entries
**YES:**
- Code patterns, architecture, service behavior
- API contracts, data schemas, integration points
- Non-obvious implementation details
- Verified facts from code/docs
When knowledge becomes stale or incomplete:
1. Read the existing entry
2. Update content in place
3. Preserve the original identifier and filename
4. **Update `verified` date** in frontmatter if re-confirmed against code
5. **Add `verified` and `source` fields** to frontmatter if missing from older entries
**NO:**
- Speculation or design proposals
- "We could do X" alternatives
- Unverified assumptions
- Temporary workarounds
## What Belongs in the KB
## Feedback Loop
- **Only verifiable knowledge from authoritative sources** - code inspection, official documentation, or properly cited research. No speculation, design alternatives, or "we could do X" proposals.
After code exploration:
- New knowledge → offer to create entry
- KB contradicts code → stop, report discrepancy, ask to update
- KB confirmed → optionally note verification
**If KB contradicts code:** Stop and report. Don't silently ignore KB errors.

View File

@ -6,530 +6,55 @@ description: Manage tasks using the beads 9P interface. Use when creating, updat
# Beads Task System
## Purpose
Beads is a hierarchical task tracking system accessed via 9P. Use it to track work items, their status, and dependencies. All operations persist immediately to a Dolt database, providing crash resilience and resumability.
## When to Use
- Creating or managing tasks
- Tracking work progress
- Setting up task hierarchies (parent/child)
- Managing blockers/dependencies
- Finding ready (unblocked) work
## Atomic Operations
Beads emphasizes atomic, single-purpose operations via the 9P control file:
### Claiming Work
```bash
# Atomically sets assignee and status to in_progress
# MUST pass your agent ID (available as $AGENT_ID)
echo "claim bd-abc $AGENT_ID" | 9p write agent/beads/ctl
```
### Completing Work
```bash
# Atomically closes the bead
echo "complete bd-abc" | 9p write agent/beads/ctl
```
### Single-Purpose Commands
Each control command does exactly one thing:
- `new` - Create a bead
- `claim` - Claim a bead (sets assignee + status)
- `complete` - Complete a bead
- `fail` - Fail a bead with reason
- `update` - Update a single field
- `dep` - Add a dependency
- `undep` - Remove a dependency
- `delete` - Delete a bead
- `comment` - Add a comment
- `label` - Add a label
- `unlabel` - Remove a label
### Immediate Feedback
After write operations, read back state to confirm:
```bash
echo "claim bd-abc" | 9p write agent/beads/ctl
9p read agent/beads/bd-abc/json | jq .status
# Output: "in_progress"
```
### No Batch Operations
Process beads one at a time in sequence:
```bash
# Correct: Sequential atomic operations
echo "claim bd-abc" | 9p write agent/beads/ctl
# ... do work ...
echo "complete bd-abc" | 9p write agent/beads/ctl
# Incorrect: Don't try to batch multiple beads
```
## Dependency-Aware Workflow
### Finding Ready Work
Use the `ready` endpoint to get beads with no blockers:
```bash
9p read agent/beads/ready | jq
# Returns JSON array of unblocked beads
```
### Creating Dependencies
Add a dependency so parent blocks child:
```bash
# Child bd-xyz is blocked by parent bd-abc
echo "dep bd-xyz bd-abc" | 9p write agent/beads/ctl
```
### Hierarchical Tasks
Create children with automatic hierarchical IDs:
```bash
# Create parent
echo "new 'Implement feature' 'Add new capability'" | 9p write agent/beads/ctl
# Get parent ID (e.g., bd-abc)
# Create children - they get IDs bd-abc.1, bd-abc.2, etc.
echo "new 'Design API' 'Define interfaces' bd-abc" | 9p write agent/beads/ctl
echo "new 'Write tests' 'Add test coverage' bd-abc" | 9p write agent/beads/ctl
```
### Checking Blockers
Read the blockers field to see explicit dependencies blocking a bead:
```bash
9p read agent/beads/bd-xyz/json | jq .blockers
# Output: ["bd-abc"] - only shows explicit dependencies added via "dep" command
```
**Important**: The blockers field only contains beads added as explicit dependencies using `echo "dep <child> <parent>" | 9p write agent/beads/ctl`. Child beads do NOT appear in the parent's blockers field.
### Checking Outstanding Child Work
To determine if a parent bead has incomplete child tasks, query the children endpoint and filter by status:
```bash
# Get all non-closed children of bd-abc
9p read agent/beads/children/bd-abc | jq '[.[] | select(.status != "closed")]'
# Count open children
9p read agent/beads/children/bd-abc | jq '[.[] | select(.status != "closed")] | length'
# Check if any children remain open
9p read agent/beads/children/bd-abc | jq 'any(.status != "closed")'
```
### Recommended Workflow
1. Check ready work: `9p read agent/beads/ready`
2. Claim an unblocked bead: `echo "claim bd-xyz $AGENT_ID" | 9p write agent/beads/ctl`
3. Search KB for relevant context: `grep -ril "<keyword>" ~/doc/agent-kb/`
4. Do the work (using KB-sourced file paths and patterns where available)
5. Before completing, check for child beads: `9p read agent/beads/children/bd-xyz | jq .`
6. If children exist: claim, work on, and complete each child before proceeding (see [Hierarchical Completion Protocol](#hierarchical-completion-protocol))
7. Verify all children closed: `9p read agent/beads/children/bd-xyz | jq 'all(.status == "closed")'`
8. Only then complete the bead: `echo "complete bd-xyz" | 9p write agent/beads/ctl`
9. Completing a bead unblocks its dependents
## Leaving Context for Future Agents
Beads serve as dynamic/temporal memory for agent execution. Beyond status tracking, they capture decisions, dead ends, discoveries, and rationale — context that helps future agents working on related tasks avoid repeated mistakes and build on prior work.
This is distinct from `agent-kb` (stable, reusable architectural knowledge). Beads hold *execution-time context*: what was tried, what failed, what was discovered, and why a particular approach was chosen.
### When to Comment
Comment on your bead as you work — not just at completion. Record:
- **Decisions**: "Chose approach Z because X failed due to Y."
- **Dead ends**: "Tried X, failed because Y. Avoided."
- **Discoveries**: "Found that endpoint /foo also rotates the refresh token."
- **Constraints**: "Avoided approach A because of constraint B (see bd-xyz)."
Comments may come from agents or humans (e.g., a human reviewing work, recording a constraint, or explaining a decision). Treat both equally as authoritative context.
```bash
echo "comment bd-abc \"Tried X first but hit rate limits. Switched to Y which batches requests.\"" | 9p write agent/beads/ctl
```
### When to Search Past Beads
Before starting any non-trivial task, search completed beads for related terms to surface prior decisions and gotchas:
```bash
9p read agent/beads/search/authentication | jq '.[].title'
9p read agent/beads/search/refresh-token | jq '.[].description'
```
When a bead looks relevant, read its full event history to see comments — this is where the most valuable context lives, including human-authored notes:
```bash
9p read agent/beads/bd-abc/events | jq '.[] | select(.type == "comment") | .body'
```
### What NOT to Do
- ❌ **NEVER create "knowledge beads"** solely to record information — this pollutes the task system with non-task entries
- ❌ Don't leave your bead with only status updates — rationale and discoveries are more valuable to future agents than "completed X"
Context belongs *in your task bead*, recorded as comments during execution.
## Description Quality and File Addressing
### What Makes a Good Description
Every bead description must enable a bot to complete the task cold — no codebase exploration, no guessing. The beads server enforces this with lint warnings emitted to stderr on `new`. A high-quality description:
- Starts with an **imperative verb**: Fix, Add, Update, Refactor, Implement, ...
- Names at least one **file path** with a recognized extension (.go, .py, .ts, .js, .rs) or path component (/internal/, /cmd/, /src/, /pkg/)
- Identifies a **precise location**: function name in backticks, or an Acme file address (see below)
- Wraps all identifiers in **backticks**: `` `lintDescription()` ``, `` `--no-lint` ``, `` `TypeName` ``
- Includes a **"how" signal**: "following the pattern in X", "same as Y", "mirrors Z"
- States an **observable acceptance criterion**: "must return ...", "should emit ...", "returns ..."
- Avoids **vague language**: somehow, maybe, etc., stuff, try to, a bit
- Avoids **first-person voice**: I need, we want, I'll
- For descriptions > 150 chars, includes a **cross-reference**: `bd-XXX` or a URL
### File Addressing
When referencing source locations, use **Acme/sam address syntax** — not the common but incorrect hyphen form.
**Correct forms (from `/home/lkn/plan9/plumb/fileaddr`):**
```
beads.go:123 line 123
beads.go:123,125 lines 123 to 125 (comma range)
beads.go:/funcName/ regex search (pattern ≥ 4 chars)
beads.go:#4096 character offset 4096
```
**Never use:**
```
beads.go:123-125 ✗ hyphen range is invalid in Acme — use comma
```
The linter warns when it detects the hyphen form. The Conductor cold-completion gate also checks for correct Acme syntax before assigning P1/P2 beads.
### Lint Rules Summary
The server checks descriptions against these rules (warnings go to stderr; bypass with `--no-lint`):
| Rule | Signal checked |
|------|---------------|
| File path | `.go`/`.py`/etc. or `/internal/`/`/cmd/`/... |
| Location | `func()`, Acme address, `L123`, `:123`, `#123` |
| Minimum length | ≥ 80 characters |
| Acceptance criterion | should / must / returns / displays / assert / verify / accept / expect |
| Acme address format | No `file:N-N` hyphen ranges |
| Imperative start | Not "Need to" / "Should" / "We need" / "The X" |
| Vague language | No somehow / maybe / etc. / stuff / try to |
| How signal | following / same as / pattern from / similar to / mirrors |
| First-person | No I need / I want / we should / we'll |
| Forbidden phrases | No "fix this" / "update this" / "make it work" |
| Inline code | Backtick identifier required when file path present |
| Cross-reference | `bd-XXX` or URL required for descriptions > 150 chars |
## JSON Output for Programmatic Use
All read endpoints return JSON for easy parsing.
### Available Endpoints
**List Operations:**
- `agent/beads/list` - All beads
- `agent/beads/ready` - Beads with no blockers
- `agent/beads/blocked` - Beads that have blockers
- `agent/beads/stale` - Beads 30+ days old
- `agent/beads/stats` - Statistics (counts by status)
**Query Operations:**
- `agent/beads/query` - Query beads (write JSON filter, then read results)
- `agent/beads/search/<term>` - Search beads by term
- `agent/beads/by-ref/<ref>` - Find bead by external reference
- `agent/beads/label/<label>` - Beads with specific label
- `agent/beads/children/<id>` - Child beads of parent
**Bead Details:**
- `agent/beads/<id>/json` - Single bead with full details
- `agent/beads/<id>/events` - Event history
- `agent/beads/<id>/dependencies-meta` - Dependencies with metadata
- `agent/beads/<id>/dependents-meta` - Dependents with metadata
### Structured Fields
Each bead JSON contains:
```json
{
"id": "bd-abc",
"title": "Task title",
"description": "Detailed description",
"status": "open",
"priority": 2,
"issue_type": "task",
"assignee": "agent-123",
"blockers": [],
"created_at": "2026-02-20T21:00:00Z",
"updated_at": "2026-02-20T21:30:00Z"
}
```
### Parsing with jq
Extract fields using jq:
```bash
# Get bead ID
9p read agent/beads/bd-abc/json | jq -r .id
# Get all blocker IDs
9p read agent/beads/bd-abc/json | jq -r .blockers[]
# Get status
9p read agent/beads/bd-abc/json | jq -r .status
# Get all ready bead IDs
9p read agent/beads/ready | jq -r .[].id
```
### Critical Rule
**NEVER parse human-readable output.** Only consume JSON from `9p read` endpoints.
## Persistence and Session Lifecycle
### Storage
Beads persist in a Dolt database at `.beads/` directory:
- MVCC (Multi-Version Concurrency Control)
- ACID transactions
- Version control built-in
### Crash Resilience
All operations immediately persist to the database. Agents can resume work after crashes without data loss.
### Session Workflow
1. **Start**: Read ready work
```bash
9p read agent/beads/ready | jq
```
2. **Claim**: Atomically claim a bead
```bash
echo "claim bd-abc $AGENT_ID" | 9p write agent/beads/ctl
```
3. **Before You Start**: Search the knowledge base for relevant context before doing anything else
```bash
# Extract keywords from the bead title and description (technical terms, file names, feature names)
grep -ril "<keyword>" ~/doc/agent-kb/
```
Read all matching entries in full. If KB has a file path or function name relevant to the task, use it directly — do not perform speculative file reads when KB provides the answer.
Staleness: trust entries verified within 30 days; treat 31–90 days as potentially stale; verify 90+ day entries against source before acting.
4. **Work**: Perform the task
4. **Check children**: Before completing, verify no open children remain
```bash
9p read agent/beads/children/bd-abc | jq 'any(.status != "closed")'
# Must return false before proceeding
```
5. **Complete**: Atomically complete the bead (only after all children are closed)
```bash
echo "complete bd-abc" | 9p write agent/beads/ctl
```
### Event History
View the event history for a bead:
```bash
9p read agent/beads/bd-abc/events
# Returns JSON array of events (created, claimed, updated, completed)
```
### Critical Rule
**NEVER manually access `.beads/` directory.** Always use the 9P interface. Direct database modification breaks consistency.
## Hierarchical Completion Protocol
**Every agent must follow this protocol when completing any bead.** This applies universally — whether you are a worker bot, an orchestrator, or a standalone agent.
Before marking a bead complete, always verify its children are resolved:
```bash
# 1. Check for children
9p read agent/beads/children/bd-abc | jq .
# 2. If children exist, work through each one:
# a. Claim it
echo "claim bd-abc.1 $AGENT_ID" | 9p write agent/beads/ctl
# b. Do the work (recurse: check bd-abc.1's children too)
# c. Complete it
echo "complete bd-abc.1" | 9p write agent/beads/ctl
# 3. Verify ALL children closed before proceeding
9p read agent/beads/children/bd-abc | jq 'all(.status == "closed")'
# Must output: true
# 4. Only then complete the parent
echo "complete bd-abc" | 9p write agent/beads/ctl
```
This protocol applies recursively. If a child has grandchildren, resolve them before completing the child.
## Anti-Patterns and Warnings
### ❌ NEVER manually edit `.beads/` directory
**Why**: Direct database modification breaks consistency and can corrupt data.
**Instead**: Use `9p write agent/beads/ctl` for all modifications.
### ❌ NEVER parse non-JSON output
**Why**: Human-readable formats change and are unreliable for programmatic use.
**Instead**: Only consume JSON from `9p read` endpoints.
### ❌ NEVER create markdown TODOs instead of beads
**Why**: TODOs in markdown are not tracked, searchable, or dependency-aware.
**Instead**: Use `echo "new 'title' 'desc'" | 9p write agent/beads/ctl`.
### ❌ NEVER bypass the 9P interface
**Why**: Direct SQL queries or Dolt commands bypass validation and event logging.
**Instead**: Always use `9p read` and `9p write agent/beads/ctl`.
### ❌ NEVER ignore blockers
**Why**: Working on blocked tasks wastes effort if dependencies aren't met.
**Instead**: Check `9p read agent/beads/ready` and respect dependency order.
### ❌ NEVER leave tasks unclaimed while working
**Why**: Other agents may claim the same work, causing conflicts.
**Instead**: Always `echo "claim bd-xxx $AGENT_ID" | 9p write agent/beads/ctl` before starting.
### ❌ NEVER complete a bead that has open children
**Why**: Completing a parent before its children are done orphans in-progress work and misrepresents task completion.
**Instead**: Check `9p read agent/beads/children/bd-abc | jq 'all(.status == "closed")'` and wait until it returns `true`.
## Quick Command Reference
### List ready work
```bash
9p read agent/beads/ready | jq
```
### Create bead
```bash
echo "new \"Implement feature\" \"Add new capability\"" | 9p write agent/beads/ctl
```
The server emits lint warnings to stderr if the description is missing quality signals (file path, function name/line, acceptance criterion, minimum length). Suppress with `--no-lint` or prefix the title with `IDEA:`:
```bash
# Bypass lint for idea-type or trivial beads
echo "new \"IDEA: Explore caching\" \"Some rough thoughts\" --no-lint" | 9p write agent/beads/ctl
```
### Create child bead
```bash
echo "new \"Design API\" \"Define interfaces\" bd-abc" | 9p write agent/beads/ctl
```
### Claim bead
```bash
echo "claim bd-abc $AGENT_ID" | 9p write agent/beads/ctl
```
### Complete bead
```bash
echo "complete bd-abc" | 9p write agent/beads/ctl
```
### Fail bead with reason
```bash
echo "fail bd-abc \"Cannot reproduce issue\"" | 9p write agent/beads/ctl
```
### Update field
```bash
echo "update bd-abc priority 1" | 9p write agent/beads/ctl
```
### Add dependency (parent blocks child)
```bash
echo "dep bd-xyz bd-abc" | 9p write agent/beads/ctl
```
### Remove dependency
```bash
echo "undep bd-xyz bd-abc" | 9p write agent/beads/ctl
```
### Check stale beads
```bash
9p read agent/beads/stale | jq
```
### Read single bead
```bash
9p read agent/beads/bd-abc/json | jq
```
### Query with JSON filter
```bash
# Find all open bugs assigned to you
echo '{"status":"open","issue_type":"bug","assignee":"agent-123"}' | 9p write agent/beads/query
9p read agent/beads/query | jq
# Find high priority tasks (priority 1-2)
echo '{"priority_min":1,"priority_max":2}' | 9p write agent/beads/query
9p read agent/beads/query | jq
# Find beads with specific label
echo '{"labels":["urgent"]}' | 9p write agent/beads/query
9p read agent/beads/query | jq
# Find unassigned open tasks
echo '{"status":"open","no_assignee":true}' | 9p write agent/beads/query
9p read agent/beads/query | jq
```
### Add comment
```bash
echo "comment bd-abc \"Fixed the bug\"" | 9p write agent/beads/ctl
```
### Add label
```bash
echo "label bd-abc bug" | 9p write agent/beads/ctl
```
### Remove label
```bash
echo "unlabel bd-abc bug" | 9p write agent/beads/ctl
```
## Bead Fields
| Field | Type | Description |
|-------|------|-------------|
| id | string | Auto-generated (e.g., `bd-abc`, `bd-abc.1` for children) |
| title | string | Short task description |
| description | string | Detailed info |
| status | string | `open`, `in_progress`, `closed` |
| priority | int | 1-5 (1=highest) |
| assignee | string | Agent or user ID |
| blockers | array | IDs of blocking beads |
| issue_type | string | `task`, `bug`, etc. |
| created_at | string | ISO 8601 timestamp |
| updated_at | string | ISO 8601 timestamp |
## Complete Workflow Example
```bash
# Find ready work
9p read agent/beads/ready | jq
# Claim a bead
echo "claim bd-abc $AGENT_ID" | 9p write agent/beads/ctl
# Verify claim
9p read agent/beads/bd-abc/json | jq '.status, .assignee'
# Do the work...
# Complete the bead
echo "complete bd-abc" | 9p write agent/beads/ctl
# Verify completion
9p read agent/beads/bd-abc/json | jq .status
```
Hierarchical task tracking via 9P. Persists to Dolt immediately.
## Commands
All via `9p write agent/beads/ctl`:
- `claim bd-abc $AGENT_ID` - claim and start
- `complete bd-abc` - finish
- `fail bd-abc "reason"` - fail with reason
- `new "title" "desc" [parent]` - create (child if parent given)
- `update bd-abc <field> <value>` - modify field
- `dep <child> <parent>` - add blocker
- `comment bd-abc "text"` - leave context
- `label bd-abc <label>` - tag
- `delete bd-abc` - delete (does NOT cascade to children)
**Note:** Delete does not cascade. To delete a parent and all children, delete children first, then parent.
## Queries
All via `9p read`:
- `agent/beads/ready` - unblocked work
- `agent/beads/<id>/json` - single bead
- `agent/beads/children/<id>` - child beads
- `agent/beads/search/<term>` - search
- `agent/beads/<id>/events` - history
## Workflow
1. Find a ready task
2. Claim the ticket being worked on
3. Use agent-kb skill to search the knowledge base.
4. Do work
5. Verify all children completed
6. Only if all children completed, complete the parent. Otherwise, work on other unblocked child tasks.
## Rules
- Claim before working
- Complete children before parent
- Only parse JSON output
- Never access `.beads/` directly
- Comment during work (decisions, dead ends, discoveries)
- Search past beads before starting
## Description Quality
Enable cold completion. Include:
- Imperative verb + file path + `` `funcName()` `` or Acme address (`file:123,125` not `file:123-125`)
- "How" signal (following X, same as Y) + acceptance criterion (must/should/returns)
- Backticked identifiers + cross-ref for >150 chars
Bypass lint: `IDEA:` prefix.

View File

@ -1,133 +1,76 @@
---
name: gh-cli
name: github-cli
intent: github, vcs
description: Interact with GitHub repositories, issues, PRs, workflows, and more using the gh CLI. Use for GitHub operations like creating issues/PRs, managing repos, checking workflow runs, and browsing GitHub resources.
---
# GitHub CLI (gh)
## Purpose
**CRITICAL:** Run `gh` commands from within the git repository directory. Use `--repo owner/name` only when operating on a different repo.
Execute GitHub operations directly from the command line using the `gh` CLI tool.
## Commands
## When to Use
**Repository:**
- Create repo: `gh repo create <name>`
- Clone repo: `gh repo clone <repo>`
- View repo: `gh repo view [repo]`
- Fork repo: `gh repo fork [repo]`
- Creating, viewing, or managing issues and pull requests
- Repository operations (clone, create, view, fork)
- Checking GitHub Actions workflow runs and caches
- Managing releases, gists, and secrets
- Searching GitHub for repos, issues, or PRs
- Opening GitHub resources in the browser
- Making authenticated GitHub API calls
**Issues:**
- Create: `gh issue create --title "..." --body "..."`
- List: `gh issue list`
- View: `gh issue view <number>`
- Close: `gh issue close <number>`
## Core Commands
**Pull Requests:**
- Create: `gh pr create`
- List: `gh pr list`
- View: `gh pr view <number>`
- Checkout: `gh pr checkout <number>`
- Merge: `gh pr merge <number>`
- Status: `gh pr status`
### Repository Management
```bash
gh repo create <name> # Create a new repository
gh repo clone <repo> # Clone a repository
gh repo view [repo] # View repository details
gh repo fork [repo] # Fork a repository
```
**Actions:**
- List runs: `gh run list`
- View run: `gh run view <run-id>`
- Watch run: `gh run watch <run-id>`
- List workflows: `gh workflow list`
- View workflow: `gh workflow view <workflow>`
### Issues
```bash
gh issue create # Create a new issue
gh issue list # List issues
gh issue view <number> # View issue details
gh issue close <number> # Close an issue
```
**Releases:**
- Create: `gh release create <tag>`
- List: `gh release list`
- View: `gh release view <tag>`
### Pull Requests
```bash
gh pr create # Create a new PR
gh pr list # List PRs
gh pr view <number> # View PR details
gh pr checkout <number> # Checkout a PR locally
gh pr merge <number> # Merge a PR
gh pr status # Show status of PRs
```
**Search:**
- Repos: `gh search repos <query>`
- Issues: `gh search issues <query>`
- PRs: `gh search prs <query>`
### GitHub Actions
```bash
gh run list # List workflow runs
gh run view <run-id> # View run details
gh run watch <run-id> # Watch a run in real-time
gh workflow list # List workflows
gh workflow view <workflow> # View workflow details
```
**Browse:**
- Open repo: `gh browse`
- Open issue/PR: `gh browse <number>`
### Releases
```bash
gh release create <tag> # Create a release
gh release list # List releases
gh release view <tag> # View release details
```
### Search
```bash
gh search repos <query> # Search repositories
gh search issues <query> # Search issues
gh search prs <query> # Search pull requests
```
### Browse
```bash
gh browse # Open repo in browser
gh browse <number> # Open issue/PR in browser
```
### API Access
```bash
gh api <endpoint> # Make authenticated API request
gh api repos/:owner/:repo/issues # Example: list issues via API
```
**API:**
- Call endpoint: `gh api <endpoint>`
- Example: `gh api repos/:owner/:repo/issues`
## Common Flags
- `--repo <owner/repo>` - Specify repository
- `--json` - Output as JSON
- `--jq <query>` - Filter JSON output with jq
- `--web` - Open in web browser
- `--help` - Show help for any command
`--repo owner/repo` `--json` `--jq <query>` `--web` `--help`
## Authentication
## Auth
Check authentication status:
```bash
gh auth status
```
Login (if needed):
```bash
gh auth login
```
- Check: `gh auth status`
- Login: `gh auth login`
## Examples
```bash
# Create an issue in current repo
gh issue create --title "Bug: Login fails" --body "Description here"
# List open PRs with JSON output
gh issue create --title "Bug" --body "Description"
gh pr list --state open --json number,title,author
# View workflow run details
gh run view 12345
# Clone a repository
gh repo clone owner/repo
# Search for Rust repositories
gh search repos --language rust --sort stars
# Make a custom API call
gh api graphql -f query='query { viewer { login } }'
```
## Notes
- Most commands work in the context of the current git repository
- Use `--repo owner/name` to operate on a different repository
- Authentication is required for most operations
- Use `gh <command> --help` for detailed command documentation

View File

@ -6,104 +6,44 @@ description: Import GitHub issues and PRs into beads task tracking. Use when use
# GitHub to Beads
## Purpose
Import GitHub issues into beads.
Import GitHub issue hierarchies into beads, creating a task tree for agent work tracking.
## Usage
```bash
github-to-beads OWNER/REPO ISSUE_NUMBER
```
**What it does:**
1. Fetches issue data via `gh` CLI
2. Creates bead: `#NUMBER: title` → title, body → description
3. Maps labels to issue_type (bug label → bug type)
4. Sets status (closed issues → closed status)
5. Parses task list (`- [ ]` items) as child beads
6. Skips if already imported
## When to Use
- User asks to "pull" or "import" a GitHub issue or PR
- User asks to "pull" or "import" a GitHub issue
- User wants to define work based on a GitHub issue
- User asks to create beads/tasks from GitHub
## When NOT to Use
- User just wants to view issue info (use `gh issue view` directly)
- User wants to modify GitHub issues (this is pull-only)
- Just viewing issue info (use `gh issue view`)
- Modifying GitHub issues (this is pull-only)
- General bead management (use `beads` skill)
## GitHub CLI
Use the `gh` CLI:
## Manual GitHub Commands
```bash
# View issue (human readable)
gh issue view 123 --repo owner/repo
# View issue (JSON for parsing)
gh issue view 123 --repo owner/repo --json number,title,body,state,labels,assignees
# List linked issues (via API)
gh api repos/owner/repo/issues/123 --jq '.body'
gh issue view 123 --repo owner/repo # human readable
gh issue view 123 --repo owner/repo --json number,title,body # JSON
```
## Import Process
## After Import
### 1. Check Existing Beads
```bash
9p read agent/beads/list | grep "#123"
```
Skip if already tracked.
### 2. Parse Issue Body for Task Lists
GitHub issues may contain task lists in markdown:
```markdown
- [ ] Task 1
- [x] Task 2 (completed)
- [ ] Task 3
```
Parse unchecked items as subtasks.
### 3. Create Beads Top-Down
Create parent issue first, then subtasks with parent ID. See `beads` skill for commands.
**CRITICAL**: Include issue number in title: `#123: <title>`
## Field Mapping
| GitHub Field | Bead Field | Notes |
|--------------|------------|-------|
| number + title | title | Format: `#123: title` |
| body | description | **MUST include issue body** |
| - | status | `open` for open issues, `closed` for closed |
| labels | issue_type | Map `bug` label to `bug`, default to `task` |
**CRITICAL**: The bead description MUST contain the GitHub issue body. This provides essential context for working on the task.
## Parsing Task Lists
Check issue body for task lists. Create as children of that issue's bead.
**Create subtasks for:**
- `- [ ]` unchecked checkboxes
**Skip:**
- `- [x]` checked boxes (done)
## Example
```bash
# Fetch issue
gh issue view 123 --repo owner/repo --json number,title,body,state
# Create parent bead
echo "new '#123: Add new feature' 'Issue body here'" | 9p write agent/beads/ctl
# Get parent ID
ROOT=$(9p read agent/beads/list | jq -r '.[] | select(.title | contains("#123")) | .id')
# Create subtasks from task list
echo "new 'Implement API endpoint' '' $ROOT" | 9p write agent/beads/ctl
echo "new 'Add tests' '' $ROOT" | 9p write agent/beads/ctl
```
## Human Review
After import, reviewer may:
Review and adjust:
- Remove beads bot doesn't need
- Adjust descriptions
- Refine descriptions
- Add context

View File

@ -6,124 +6,44 @@ description: Import Jira tickets into beads task tracking. Use when user asks to
# Jira to Beads
## Purpose
Import Jira ticket hierarchies into beads.
Import Jira ticket hierarchies into beads, creating a task tree for agent work tracking.
## Usage
```bash
jira-to-beads PROJ-12345
```
**What it does:**
1. Finds root ticket (walks up parent chain)
2. Creates beads top-down (parent → children)
3. Maps fields: `KEY: summary` → title, description → description
4. Recursively imports entire hierarchy
5. Skips if already imported
## When to Use
- User asks to "pull" or "import" a Jira ticket
- User wants to define work based on a Jira epic or story
- User wants to define work based on a Jira epic/story
- User asks to create beads/tasks from Jira
## When NOT to Use
- User just wants to view ticket info (use `jira issue view` directly)
- User wants to modify Jira tickets (this is pull-only)
- Just viewing ticket info (use `jira issue view`)
- Modifying Jira tickets (this is pull-only)
- General bead management (use `beads` skill)
## Jira CLI
Use the `jira` CLI (not `atlassian-cli`):
## Manual Jira Commands
```bash
# View ticket (human readable)
jira issue view PROJ-12345 --plain
# View ticket (JSON for parsing)
jira issue view PROJ-12345 --raw
# List child tickets
jira issue list --parent PROJ-12345 --plain --no-truncate
jira issue view PROJ-12345 --plain # human readable
jira issue view PROJ-12345 --raw # JSON
jira issue list --parent PROJ-12345 # list children
```
## Import Process
## After Import
### 1. Check Existing Beads
```bash
9p read agent/beads/list | grep "PROJ-12345"
```
Skip if already tracked.
### 2. Find Root Ticket
```bash
jira issue view PROJ-12345 --raw | jq '.fields.parent.key // empty'
```
Recursively fetch ancestors until no parent. Build tree top-down from root.
### 3. Build Task Tree
```bash
jira issue list --parent PROJ-12345 --plain --no-truncate
```
Recursively fetch children until reaching leaves.
### 4. Create Beads Top-Down
Create parent first, then children with parent ID. See `beads` skill for commands.
**CRITICAL**: Include Jira key in title: `PROJ-XXXXX: <summary>`
## Field Mapping
| Jira Field | Bead Field | Notes |
|------------|------------|-------|
| key + summary | title | Format: `PROJ-XXXXX: summary` |
| description | description | **MUST include ticket body** (truncate if very long) |
| parent ticket | parent_id | Pass parent bead ID |
| - | status | Always `open` initially |
**CRITICAL**: The bead description MUST contain the Jira ticket body/description. This provides essential context for working on the task. Extract plain text from the Jira ADF format.
## Including Comments and Linked Pages
### Comments
Include significant information from ticket comments in the bead description:
- Guidance or clarifications
- Decisions made
- Technical notes or constraints
- Skip routine status updates or acknowledgments
### Linked Confluence Pages
If the ticket links to Confluence pages (design docs, specs, etc.):
1. Fetch the page using `fetch-confluence` skill
2. Extract key information relevant to the task
3. Include summary in bead description
## Parsing Action Items
Check descriptions for actionable items. Create as children of that ticket's bead.
**Only parse items under task-related sections:**
- `TODO`, `Tasks`, `Action Items`, or similar headings
- Do NOT parse items under `QA`, `Testing`, `Notes`, `Questions`, or other non-task sections
**Create subtasks for:**
- `:white_circle:` or `⚪` (open items)
- `- [ ]` unchecked checkboxes
**Skip:**
- `:check_mark:` or `✅` (done)
- `:question_mark:` or `❓` (questions)
- `- [x]` checked boxes (done)
## Example
```bash
# Fetch ticket hierarchy
jira issue view PROJ-456 --raw | jq '{key: .key, summary: .fields.summary, parent: .fields.parent.key}'
# Create beads (see beads skill for syntax)
echo "new 'PROJ-123: Feature epic' 'Epic'" | 9p write agent/beads/ctl
ROOT=$(9p read agent/beads/list | jq -r '.[] | select(.title | contains("PROJ-123")) | .id')
echo "new 'PROJ-456: Feature story' 'Story' $ROOT" | 9p write agent/beads/ctl
```
## Human Review
After import, reviewer may:
Review and adjust:
- Remove beads bot doesn't need
- Adjust descriptions
- Refine descriptions
- Add context

View File

@ -5,266 +5,94 @@ description: Plan 9 rc shell scripting syntax and conventions. Use when writing
user-invocable: false
---
# Plan 9 rc Shell Scripting
# Plan 9 rc Shell Syntax
Reference for writing shell scripts using Plan 9 rc syntax (`.rc` files).
Shebang: `#!/usr/bin/env rc` Extension: `.rc`
## File Setup
## Variables
**Shebang:**
```
#!/usr/bin/env rc
```
Always use `/usr/bin/env rc` (not a direct path like `/usr/local/plan9/bin/rc`) because plan9port installation locations vary across systems.
**File extension:** `.rc`
## Core Syntax Differences from Bash/sh
### Variables
**Assignment** (NO spaces around `=`):
```
name=value
path=(/bin /usr/bin)
name=value # NO spaces around =
files=(a b c) # lists in parens
$name $files(1) $files(2-) # substitute, 1st element, from 2nd onward
$files(2-4) # range
$#files # count
$"files # join with spaces
$^files # concat (no spaces)
```
**Reference** (NO `$` for simple cases in some contexts, but use `$` for safety):
## Command Substitution
```
echo $name
for(file in *.txt) echo $file
result=`{command} # backticks, NOT $()
result=`split{command} # split using 'split' instead of $ifs
```
**Lists** (space-separated in parentheses):
```
files=(foo.txt bar.txt baz.txt)
echo $files # prints all elements
echo $files(1) # prints first element (1-indexed)
echo $files(2-) # prints from second element onward
```
## Control Flow
### Command Substitution
**Backticks** (like classic sh):
```
files=`{ls *.txt}
date=`{date}
```
### Quoting
**Single quotes** for literals:
```
echo 'hello $world' # prints: hello $world
```
**Double quotes** are NOT special in rc - use single quotes or concatenation.
### Control Structures
**if statement** (note: condition is a command, `if not` is a separate statement):
```
if(test -f file.txt) {
echo 'file exists'
if(test -f file) {
echo exists
}
if not {
echo 'file does not exist'
if not { # separate statement, new line
echo missing
}
# Single statement form
if(test -f file.txt)
echo 'exists'
if not
echo 'does not exist'
```
for(i in 1 2 3) { echo $i }
for(i) { echo $i } # iterates over $* if no list
**for loop:**
```
for(file in *.txt) {
echo $file
}
while(test $n -lt 10) { n=`{echo $n + 1 | bc} }
for(i in 1 2 3 4 5) {
echo iteration $i
}
```
**while loop:**
```
while(test $count -lt 10) {
echo $count
count=`{echo $count + 1 | bc}
}
```
**switch statement:**
```
switch($file) {
case *.txt
echo 'text file'
case *.md
echo 'markdown file'
echo text
case *
echo 'other file'
echo other
}
```
### Functions
**Definition:**
```
fn myfunction {
echo 'arguments:' $*
echo 'first arg:' $1
}
# Call it
myfunction foo bar baz
```
**Local variables** (use `local` keyword or just assign):
```
fn myfunction {
local=(old $local)
# ... function body
}
```
### Exit Status
**Check exit status:**
```
if(grep -q pattern file.txt) {
echo 'found'
}
```
**Explicit status check:**
```
command
status=$status
if(~ $status 0) {
echo 'success'
}
```
### Pattern Matching
**The `~` operator:**
```
if(~ $file *.txt) {
echo 'text file'
}
if(~ $#list 0) {
echo 'empty list'
}
```
### Pipelines and Redirection
**Standard pipelines:**
```
cat file.txt | grep pattern | sort
```
**Redirection:**
```
echo hello >file.txt # write
echo world >>file.txt # append
command >[2=1] # redirect stderr to stdout
command >[2]/dev/null # redirect stderr to /dev/null
```
### Important Operators
- `~` - pattern match
- `$#var` - count elements in list
- `$var(N)` - Nth element of list (1-indexed)
- `$var(N-)` - elements from N onward
- `$^var` - concatenate list elements (no spaces)
- `$$var` - pid of command
### Comments
## Functions & Pattern Matching
```
# This is a comment
echo hello # inline comment
fn name { echo $* $1 } # define (all args, first arg)
fn name # remove definition
~ $file *.txt # pattern match (sets $status)
if(~ $#list 0) { echo empty }
```
## Common Patterns
## Redirection & Pipes
### Check if variable is set
```
if(~ $#var 0) {
echo 'var is not set'
}
>out >>out <in <<EOF # stdout, append, stdin, here doc
>[2]err >[2=1] >[2=] # fd 2 to file, fd 2 to fd 1, close fd 2
<[0=3] # fd 0 from fd 3
<{cmd} >{cmd} <>{cmd} # process substitution
cmd1 | cmd2 # pipe
|[2] |[1=2] # pipe fd 2, pipe fd 2 to fd 1
```
### Iterate over arguments
```
fn process {
for(arg in $*) {
echo processing $arg
}
}
```
## Operators
### Build path list
```
path=($home/bin /usr/local/bin /usr/bin /bin)
```
`; & && || ! @` - sequence, async, and, or, invert, subshell
`^` - concatenate (auto-inserted without whitespace)
### Conditional execution
```
test -f file.txt && echo 'exists'
test -f file.txt || echo 'does not exist'
```
## Special Variables
### Here documents
```
cat <<EOF
line 1
line 2
EOF
```
`$*` `$status` `$apid` `$pid` `$ifs` `$path` `$home`
## Built-ins
`. file` `cd` `eval` `exec` `exit` `shift` `wait` `whatis`
## Key Differences from Bash
1. **No `$()` syntax** - use backticks for command substitution
2. **Lists are first-class** - use parentheses for lists
3. **1-indexed arrays** - `$list(1)` is first element
4. **`if not` instead of `else`** - written as a separate statement, not on same line
5. **No `[[ ]]` or `[ ]`** - use `test` command or `~` operator
6. **Pattern matching with `~`** - not `==` or `=`
7. **`$#var` for count** - not `${#var}`
8. **Different redirection** - `>[2=1]` not `2>&1`
9. **No parameter expansion** - no `${var:-default}` syntax
10. **Functions use `fn`** - not `function` keyword
## Best Practices
1. Always use `#!/usr/bin/env rc` shebang
2. Use meaningful variable names
3. Quote variables when word splitting matters
4. Use `~` for pattern matching
5. Remember lists are 1-indexed
6. Write `if not` as a separate statement on a new line
7. Prefer `test` for file/string comparisons
8. Use `$#var` to check if variable is set
9. Leverage list operations for cleaner code
10. Keep scripts simple and readable
## Common Gotchas
- **NO spaces around `=`** in assignments
- **Double quotes are NOT special** - use single quotes
- **Arrays are 1-indexed**, not 0-indexed
- **`if not` is a separate statement** - write it on a new line, not `} if not {`
- **No `${}` parameter expansion**
- **Different redirection syntax** from bash
- **`test` command behavior** may differ from bash `test`
## Resources
For detailed documentation, see `9 man rc` or the Plan 9 documentation.
- Backticks `{cmd}`, not `$(cmd)`
- Lists `(a b c)`, 1-indexed
- `if not` on new line
- `test` or `~`, not `[[ ]]`
- `$#var` not `${#var}`, `$"var` not `"$*"`
- `>[2=1]` not `2>&1`
- No `${var:-default}`
- `fn name` not `function name`
- Single quotes only (double quotes not special)
- Free carets: `$x.c` → `$x^.c`

View File

@ -1,141 +1,71 @@
---
name: write-skills
intent: meta, skills
description: Guide for authoring new Agent Skills. Use when creating, updating, or reviewing skills / SKILL.md files. Always prefer the skill-creator skill if available.
description: Guide for authoring new Agent Skills. Use when creating, updating, or reviewing skills / SKILL.md files.
---
# Write Skills (Meta Skill)
# Write Skills
## Purpose
This skill provides guidance for authoring high-quality Agent Skills. Use it when creating new skills or improving existing ones.
## Skill Structure
Each skill is a directory containing:
## Structure
```
my-skill/
├── SKILL.md # Required - frontmatter + instructions
├── reference.md # Optional - detailed documentation
├── examples.md # Optional - usage examples
├── scripts/ # Optional - helper utilities
└── templates/ # Optional - file templates
skill-name/
├── SKILL.md # required: frontmatter + instructions
├── reference.md # optional: detailed docs
└── examples.md # optional: usage examples
```
## SKILL.md Format
```markdown
```yaml
---
name: skill-name # must match the folder name of the skill!
description: Brief description of what this skill does and when to use it.
allowed-tools: Tool1, Tool2 # Optional - restrict available tools
name: skill-name # lowercase, hyphens, match directory
intent: category, subcategory # for discovery
description: What it does and when to use it (max 1024 chars)
---
# Skill Name
## Purpose
What the skill accomplishes.
## When to Use
Conditions that trigger this skill.
## Instructions
Step-by-step guidance for Agent.
## Examples
Concrete usage examples.
Brief, actionable instructions.
```
## Frontmatter Requirements
## Frontmatter
| Field | Rules |
|-------|-------|
| `name` | Lowercase letters, numbers, hyphens only. Max 64 chars. Match directory name. |
| `description` | Required. Max 1024 chars. Include *what* and *when*. |
| `allowed-tools` | Optional. Comma-separated tool names to restrict access. |
- `name` - `[a-z0-9-]`, max 64 chars, match directory
- `intent` - comma-separated categories (tasks, workflow, editor, messaging, etc.)
- `description` - what + when, max 1024 chars
## Writing Effective Descriptions
## Writing Guidelines
The `description` field determines when Agent invokes your skill. Include:
**Description:** Include capability and trigger conditions.
- Good: "Manage tasks using beads 9P interface. Use when creating, updating, listing, or deleting tasks/beads."
- Bad: "A useful skill" (vague, no trigger)
1. **What** the skill does (capability)
2. **When** to use it (trigger conditions)
**Instructions:**
- Imperative voice ("Do X" not "You should")
- Single responsibility
- Clear boundaries (when to use / not use)
- Concrete examples
- Reference companion files: `[reference.md](reference.md)`
Good examples:
- "Use the `fetch-markdown` CLI tool to retrieve a URL and extract readable Markdown for quoting, summarization, and analysis."
- "Guide for authoring new Agent Skills. Use when creating, updating, or reviewing SKILL.md files."
Bad examples:
- "A useful skill" (too vague)
- "Helps with things" (no trigger condition)
## Writing Instructions
- Be clear and step-by-step
- Use imperative voice ("Do X", not "You should do X")
- Include "When to Use" vs "When NOT to Use" sections
- Provide concrete examples
- Reference companion files with relative paths: `[reference.md](reference.md)`
## Best Practices
1. **Single responsibility**: One skill, one purpose
2. **Progressive disclosure**: Put details in companion files, not SKILL.md
3. **Actionable guidance**: Tell Agent exactly what to do
4. **Clear boundaries**: Define when to use and when NOT to use
5. **Test your skill**: Verify Agent invokes it correctly
## Creating a New Skill
### 1. Find the skills directory
## Creating Skills
```bash
agent-skills path
# Find skills directory
9p ls agent/skills
# Create
mkdir -p ./skills/skill-name
# Write SKILL.md with frontmatter
# Verify
9p ls agent/skills | grep skill-name
```
This returns colon-separated paths. Use the first writable one (typically `~/src/agent-q/skills/`).
## Validation
### 2. Create the skill directory and file
```bash
mkdir -p <skills-path>/<skill-name>
# Then create SKILL.md with the required format
```
### 3. Verify the skill is registered
```bash
agent-skills list | grep <skill-name>
```
### 4. Test loading
```bash
agent-skills load <skill-name>
```
## Skill Locations
| Type | Path | Use Case |
|----------|-------------------------|------------------------------------|
| Agent-Q | `~/src/agent-q/skills/` | Shared team skills |
## Restricting Tools
Use `allowed-tools` for read-only or limited-scope skills:
```yaml
allowed-tools: Read, Grep, Glob
```
When active, Agent should only use those tools without permission prompts.
## Validation Checklist
- [ ] Directory name matches `name` field
- [ ] `name` uses only `[a-z0-9-]`, max 64 chars
- [ ] `description` is present and under 1024 chars
- [ ] `description` explains what AND when
- [ ] Instructions are clear and actionable
- [ ] Companion files are referenced correctly
- [ ] Directory = `name` field
- [ ] `name` matches `[a-z0-9-]`, ≤64 chars
- [ ] `intent` present
- [ ] `description` present, ≤1024 chars, includes what + when
- [ ] Instructions clear and actionable