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:
parent
1fb7038419
commit
e1df81fda6
|
|
@ -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"
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Reference in New Issue