Feature Management Recipes¶
Create Feature¶
Problem: Create a new feature to track work.
Solution:
from htmlgraph import SDK
sdk = SDK(agent="claude")
# Simple feature
feature = sdk.features.create("Add dark mode toggle")
# Feature with details
feature = sdk.features.create("User Authentication") \
.set_priority("high") \
.set_description("Implement OAuth 2.0 with JWT tokens") \
.add_steps([
"Research OAuth providers",
"Implement auth routes",
"Add JWT middleware",
"Create user profile endpoint",
"Write integration tests"
]) \
.add_tags(["security", "backend"]) \
.save()
print(f"Created: {feature.id}")
print(f"Steps: {len(feature.steps)}")
Explanation:
- Fluent API for building features
- Auto-generates ID with timestamp
- Creates HTML file in .htmlgraph/features/
- Ready to start working immediately
Mark Steps Complete¶
Problem: Track progress as you complete steps.
Solution:
from htmlgraph import SDK
sdk = SDK(agent="claude")
# Mark single step complete (0-indexed)
with sdk.features.edit("feature-123") as f:
f.steps[0].completed = True
# Mark multiple steps at once
with sdk.features.edit("feature-123") as f:
f.steps[0].completed = True
f.steps[1].completed = True
f.steps[2].completed = True
# Mark step and add notes
with sdk.features.edit("feature-123") as f:
f.steps[3].completed = True
f.steps[3].agent = "claude"
f.steps[3].timestamp = datetime.now()
Explanation: - Context manager auto-saves changes - Steps are 0-indexed (first step = 0) - Can add agent and timestamp for audit trail - Changes immediately visible in dashboard
Best Practice: Mark steps complete IMMEDIATELY after finishing them, not all at the end.
Add Dependencies¶
Problem: Express that one feature blocks another.
Solution:
from htmlgraph import SDK
sdk = SDK(agent="claude")
# Method 1: Add single dependency
sdk.features.add_dependency(
blocked_id="feature-auth", # Feature that's blocked
blocker_id="feature-database", # Feature that blocks it
relationship="blocks"
)
# Method 2: Add multiple dependencies
auth = sdk.features.get("feature-auth")
database = sdk.features.get("feature-database")
sessions = sdk.features.get("feature-sessions")
sdk.features.add_dependency(auth.id, database.id, "blocks")
sdk.features.add_dependency(auth.id, sessions.id, "blocks")
# Method 3: Add when creating feature
feature = sdk.features.create("API Endpoints") \
.blocked_by(["feature-auth"]) \
.save()
Explanation: - Dependencies create graph edges - Used for bottleneck analysis - Determines parallel work capacity - Visualized in dashboard graph view
Query Features¶
Problem: Find features matching specific criteria.
Solution:
from htmlgraph import SDK
sdk = SDK(agent="claude")
# By status
in_progress = sdk.features.where(status="in-progress")
todo = sdk.features.where(status="todo")
done = sdk.features.where(status="done")
# By priority
high_priority = sdk.features.where(priority="high")
# Multiple criteria
urgent = sdk.features.where(status="todo", priority="high")
# By tag
security_features = sdk.features.where(tags__contains="security")
# Get single feature
feature = sdk.features.get("feature-123")
# Get all features
all_features = sdk.features.all()
# Count features
count = len(sdk.features.where(status="todo"))
print(f"{count} todo features")
Explanation:
- where() returns list of matching features
- get() returns single feature by ID
- Can filter by any field (status, priority, tags, etc.)
- Use tags__contains for tag filtering
Update Feature Status¶
Problem: Change feature status as work progresses.
Solution:
from htmlgraph import SDK
sdk = SDK(agent="claude")
# Method 1: Direct edit
with sdk.features.edit("feature-123") as f:
f.status = "in-progress"
# Method 2: Use CLI
# htmlgraph feature start feature-123
# htmlgraph feature complete feature-123
# Method 3: Batch update multiple features
sdk.features.batch_update(
["feature-001", "feature-002", "feature-003"],
{"status": "done"}
)
# Update with validation
with sdk.features.edit("feature-123") as f:
if all(step.completed for step in f.steps):
f.status = "done"
else:
print(f"Warning: {len([s for s in f.steps if not s.completed])} steps incomplete")
Explanation: - Status can be: "todo", "in-progress", "done", "blocked" - Context manager validates and auto-saves - Batch updates are more efficient for multiple features - Hooks may track status changes automatically
Add Notes and Activity¶
Problem: Document decisions and progress.
Solution:
from htmlgraph import SDK
from datetime import datetime
sdk = SDK(agent="claude")
# Add activity log entry
with sdk.features.edit("feature-123") as f:
if not hasattr(f, 'activity_log'):
f.activity_log = []
f.activity_log.append({
"timestamp": datetime.now().isoformat(),
"agent": "claude",
"action": "decision",
"description": "Chose GitHub OAuth over Google due to simpler integration"
})
# Add notes to description
with sdk.features.edit("feature-123") as f:
f.content += "\n\n## Decision Log\n"
f.content += "- 2024-12-24: Selected Supabase for auth provider\n"
f.content += "- 2024-12-24: Decided to use row-level security\n"
Explanation: - Activity log preserves decision context - Useful for onboarding and retrospectives - Timestamped entries show progression - Content field supports markdown
Clone a Feature¶
Problem: Create a similar feature based on an existing one.
Solution:
from htmlgraph import SDK
sdk = SDK(agent="claude")
# Get existing feature
template = sdk.features.get("feature-template")
# Create new feature with same structure
new_feature = sdk.features.create(f"{template.title} (v2)") \
.set_priority(template.priority) \
.add_steps([step.description for step in template.steps]) \
.add_tags(template.tags) \
.save()
print(f"Cloned to: {new_feature.id}")
Explanation: - Useful for repeated workflows - Preserves structure but creates new ID - Steps start uncompleted - Can modify before saving
Archive Completed Features¶
Problem: Clean up completed work while preserving history.
Solution:
from htmlgraph import SDK
import shutil
import os
sdk = SDK(agent="claude")
# Create archive directory
os.makedirs(".htmlgraph/archive/features", exist_ok=True)
# Get completed features older than 30 days
from datetime import datetime, timedelta
cutoff = datetime.now() - timedelta(days=30)
done_features = sdk.features.where(status="done")
for f in done_features:
if f.updated < cutoff:
# Move to archive
src = f".htmlgraph/features/{f.id}.html"
dst = f".htmlgraph/archive/features/{f.id}.html"
shutil.move(src, dst)
print(f"Archived: {f.id}")
# Rebuild index
# htmlgraph index rebuild
Caution: - Archived features won't appear in queries - Rebuild index after archiving - Keep archives in git for full history