attune-help
Lightweight help runtime with progressive depth and audience adaptation. Read project help templates generated by attune-ai.
Install
pip install attune-help
Quick Start
from 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")) # reference
How It Works
Each 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.
Renderers
# 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.
Template Directory
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 init
Or create them manually — any markdown file with
feature, depth, and source_hash frontmatter
fields works.
Demo Templates
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.
Discovery
engine.list_topics() # all slugs
engine.list_topics(type_filter="concepts") # filter by type
engine.search("security") # [(slug, score), ...]
engine.suggest("secrity-audit") # ranked slugs
Miss 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)
Progressive Depth Controls
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 topics
Topics 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.
MCP Server
Install with the plugin extra and use as an MCP server:
pip install attune-help[plugin]
attune-help-mcp # stdio transport
Exposed 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).
API
HelpEngine
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
SessionStorage Protocol
Session depth state defaults to LocalFileStorage (per-user JSON files
under ~/.attune-help/sessions/, 4-hour TTL). Implement the protocol to
plug in any backend:
from attune_help import SessionStorage
class MyStorage(SessionStorage):
def get_session(self, user_id: str) -> dict: ...
def set_session(self, user_id: str, state: dict) -> None: ...
BackendSessionStorage — bring your own key/value store
For cross-host continuity without writing the protocol yourself, inject
any key/value backend (an attune_redis backend, attune's
MemoryBackend, or a custom object exposing stash/retrieve).
attune-help imports none of these, so this adds no required
dependency (ADR-002 stays intact):
from attune_help import BackendSessionStorage, HelpEngine
class KVBackend: # your store — e.g. wrap Redis
def stash(self, key: str, value: str) -> bool: ...
def retrieve(self, key: str) -> str | None: ...
storage = BackendSessionStorage(my_backend) # same schema + 4h TTL
engine = HelpEngine(storage=storage)
Schema, TTL, and legacy migration match LocalFileStorage exactly —
only the transport (a backend key instead of a file) differs. Backend
errors never propagate into the runtime: reads fall back to defaults,
writes log-and-continue.
Staleness Detection (moved to attune-author)
Staleness tracking — manifest loading, SHA-256 + semantic hashing, and
freshness symbol extraction — moved to
attune-author in 0.11.0.
The deprecated attune_help.manifest / staleness / freshness
re-export shims were removed in 0.12.0; import from attune_author.*
directly:
from attune_author.manifest import load_manifest
from attune_author.staleness import check_staleness
manifest = load_manifest(".help")
report = check_staleness(manifest, help_dir=".help", project_root=".")
for entry in report.stale_features:
print(f"{entry} is stale — regenerate with attune-ai")
Semantic hashing (contract-only hashes for pure-Python features) is documented in the attune-author README.
Corpus validation
A 3-sweep validation harness ships in scripts/validate_against_corpus.py
(a maintainer tool — requires attune-author installed):
# Validate against any repo with a .help/features.yaml
python scripts/validate_against_corpus.py --repo /path/to/your/repo
Sweeps: (1) parse integrity — all .py files parse cleanly; (2)
determinism — identical hashes on two consecutive calls; (3) HEAD vs
HEAD^ — classifies symbol changes as signature drift / body-only /
add / remove.
Template aliases
Templates can declare aliases: in their frontmatter to cover
retrieval gaps — synonyms and alternate phrasings that keyword search
would otherwise miss:
---
type: concept
feature: tool-planning
aliases:
- how to plan tools
- tool design principles
- when to use tools
---
aliases is a YAML list of strings. The retrieval engine scores alias
hits the same as title hits, so a query that uses a synonym routes to
the right template even when the canonical slug has no token overlap.
License
Apache 2.0
Metadata
Release files for attune-help 0.13.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| attune_help-0.13.0.tar.gz | 433.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| attune_help-0.13.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / attune_help-0.13.0.tar.gz
| Download URL | attune_help-0.13.0.tar.gz |
|---|---|
| Size | 433.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b380aafddae0dfc7dd6546e1114aafb0ea3008254ef02aa70ead817f241a69ef
|
|
BLAKE2b-256 checksum How to use checksums |
965150951fac0519c24d4641a5d2c78e678e21a1294bcd2cde710f64002aeb75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.
Transparency logRelease files / attune_help-0.13.0-py3-none-any.whl
| Download URL | attune_help-0.13.0-py3-none-any.whl |
|---|---|
| Size | 712.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a2a015bac29bd9422256bf1523f4b3da9c7bf320e1457d95fe8e3eaaf74c9da9
|
|
BLAKE2b-256 checksum How to use checksums |
cf0f8bb49d301a6a0d55ae8f1f601e48bbb83bcbbf40e76cc836437c940c121d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.
Transparency log