Lightweight help runtime with progressive depth and audience adaptation. Read project help templates generated by attune-ai.
pip install attune-helpfrom attune_help import HelpEngine
engine = HelpEngine(template_dir=".help/templates")
# Progressive depth: concept -> task -> reference
print(engine.lookup("security-audit")) # concept
print(engine.lookup("security-audit")) # task
print(engine.lookup("security-audit")) # referenceEach topic has three depth levels:
| Level | Type | What you get |
|---|---|---|
| 0 | Concept | What is it? When to use it? |
| 1 | Task | Step-by-step how-to |
| 2 | Reference | Full detail, edge cases |
Repeated lookups on the same topic auto-advance. A new topic resets to concept.
# Plain text (default)
engine = HelpEngine(renderer="plain")
# Rich terminal output (requires `pip install attune-help[rich]`)
engine = HelpEngine(renderer="cli")
# Claude Code inline format
engine = HelpEngine(renderer="claude_code")
# Structured JSON (for apps, web, tests)
engine = HelpEngine(renderer="json")
# Auto-detect environment (CLAUDE_CODE → claude_code,
# interactive TTY + rich → cli, otherwise → plain)
engine = HelpEngine(renderer="auto")
# Switch renderer at runtime
engine.set_renderer("cli")Passing an unknown renderer name raises ValueError.
Templates are markdown files with YAML frontmatter:
.help/templates/
security/
concept.md
task.md
reference.md
api/
concept.md
task.md
reference.md
Generate templates with attune-ai:
pip install attune-ai
# Then in Claude Code:
/coach initOr create them manually — any markdown file with
feature, depth, and source_hash frontmatter
fields works.
The package includes a demo feature showing the progressive depth format:
from attune_help import get_demo_path
# Copy to your project
import shutil
shutil.copytree(
get_demo_path() / "security-audit",
".help/templates/security-audit",
)The security-audit/ demo contains concept.md,
task.md, and reference.md — the three depth
levels that /coach init generates for each feature.
engine.list_topics() # all slugs
engine.list_topics(type_filter="concepts") # filter by type
engine.search("security") # [(slug, score), ...]
engine.suggest("secrity-audit") # ranked slugsMiss handling:
# Returns None by default
engine.lookup("typoed-slug")
# Returns "No help for 'typoed-slug'. Did you mean: ..."
engine.lookup("typoed-slug", suggest_on_miss=True)engine.lookup("security-audit") # concept
engine.lookup("security-audit") # task
engine.lookup("security-audit") # reference (depth 2)
engine.simpler("security-audit") # step back to task
engine.simpler("security-audit") # step back to concept
engine.reset("security-audit") # clear one topic
engine.reset() # clear all topicsTopics are tracked independently — interleaving
lookup("a") / lookup("b") / lookup("a") does not
reset a's depth. An LRU cap of 32 topics keeps session
state bounded.
Install with the plugin extra and use as an MCP server:
pip install attune-help[plugin]
attune-help-mcp # stdio transportExposed tools (all prefixed lookup_ for namespace
hygiene against other plugins):
| Tool | Purpose |
|---|---|
lookup_topic |
Progressive depth lookup |
lookup_simpler |
Step a topic one level back |
lookup_reset |
Clear a single topic or full session |
lookup_status |
Read session state (topics + LRU order) |
lookup_list |
Category-grouped topic enumeration |
lookup_list_topics |
Flat slug enumeration (optionally by type) |
lookup_search |
Fuzzy slug search with scores |
lookup_suggest |
"Did you mean" slug suggestions |
lookup_warn |
File-context warnings for a path |
lookup_preamble |
"Use X when..." one-liner for a feature |
All tools that render help content accept the same
renderer set as the Python API: plain, claude_code,
cli, marketplace, json (the auto sentinel is
excluded because auto-detection is meaningless over a
protocol boundary).
HelpEngine(
template_dir=None, # Override template path
storage=None, # Session storage backend
renderer="plain", # Output renderer
user_id="default", # Session tracking ID
)Methods:
lookup(topic, *, suggest_on_miss=False)— Progressive depth lookup with optional "did you mean" on misssimpler(topic)— Step back one depth levelreset(topic=None)— Clear depth history for one topic or alllist_topics(type=None, limit=None)— Enumerate slugssearch(query, limit=10)— Fuzzy-search slugssuggest(topic, limit=5)— Ranked slug suggestionsget(template_id)— Direct template accesslookup_raw(topic)— ReturnsPopulatedTemplatedataclassget_summary(skill)— One-line skill summary (falls back to bundled when an override lacks it)precursor_warnings(file_path)— File-aware warnings (supports Python, JS/TS, Rust, Go, Ruby, Java, …)set_renderer(name)— Change renderer at runtime
Implement custom storage backends:
from attune_help import SessionStorage
class RedisStorage(SessionStorage):
def load(self, user_id: str) -> dict: ...
def save(self, user_id: str, state: dict) -> None: ...Apache 2.0