https://github.com/smart-ai-memory/attune-help
Lightweight .help/ runtime reader with progressive depth. Python package for the attune-docs help platform.
https://github.com/smart-ai-memory/attune-help
Last synced: about 2 months ago
JSON representation
Lightweight .help/ runtime reader with progressive depth. Python package for the attune-docs help platform.
- Host: GitHub
- URL: https://github.com/smart-ai-memory/attune-help
- Owner: Smart-AI-Memory
- License: other
- Created: 2026-04-09T16:01:34.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-01T11:04:02.000Z (about 2 months ago)
- Last Synced: 2026-05-01T12:05:31.173Z (about 2 months ago)
- Language: Python
- Size: 919 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# attune-help
Lightweight help runtime with progressive depth and
audience adaptation. Read project help templates
generated by [attune-ai](https://pypi.org/project/attune-ai/).
## Install
```bash
pip install attune-help
```
## Quick Start
```python
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
```python
# 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](https://pypi.org/project/attune-ai/):
```bash
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:
```python
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
```python
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:
```python
# 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
```python
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:
```bash
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`
```python
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 miss
- `simpler(topic)` — Step back one depth level
- `reset(topic=None)` — Clear depth history for one topic
or all
- `list_topics(type=None, limit=None)` — Enumerate slugs
- `search(query, limit=10)` — Fuzzy-search slugs
- `suggest(topic, limit=5)` — Ranked slug suggestions
- `get(template_id)` — Direct template access
- `lookup_raw(topic)` — Returns `PopulatedTemplate`
dataclass
- `get_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
Implement custom storage backends:
```python
from attune_help import SessionStorage
class RedisStorage(SessionStorage):
def load(self, user_id: str) -> dict: ...
def save(self, user_id: str, state: dict) -> None: ...
```
## Staleness Detection
`attune-help` tracks whether your help templates are up to date with
your source code using SHA-256 hashes stored in template frontmatter.
### Basic usage
```python
from attune_help import load_manifest, 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 (v0.10+)
For pure-Python features, `compute_source_hash` automatically uses
**semantic hashing**: only public-symbol *contracts* (parameters, return
types, decorators, base classes) contribute to the hash. Docstring
edits, body rewrites, and formatter passes (`black`, `ruff`) are
ignored. This eliminates spurious template regenerations when nothing
meaningful changed.
```python
from attune_help import compute_source_hash, compute_semantic_hash
from attune_help.manifest import Feature
feat = Feature(name="auth", description="", files=["src/auth/**"])
# compute_source_hash uses semantic hashing automatically for .py-only features
hash1, files = compute_source_hash(feat, project_root=".")
# Call compute_semantic_hash directly when you need the semantic hash
# regardless of file mix (e.g. for reporting)
hash2, files = compute_semantic_hash(feat, project_root=".")
```
Mixed-content features (Python + Jinja, YAML, etc.) and features with
syntax errors in their source files fall back to byte-level SHA
automatically — no configuration required.
### Corpus validation
A 3-sweep validation harness ships in `scripts/validate_against_corpus.py`:
```bash
# 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:
```yaml
---
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