Major:
- Extract all inline <style> blocks from 22 Jinja2 templates into
static/css/mission-control.css — single cacheable stylesheet
- Add tox lint check that fails on inline <style> in templates
Minor:
1. Connection status indicator in topbar (green/amber/red dot) reflecting
WebSocket + Ollama reachability, with auto-reconnect
2. Jinja2 {% macro panel(title) %} in macros.html — eliminates repeated
.card.mc-panel markup; index.html converted as example
3. SVG favicon (purple T + orange dot)
4. 30-second TTL cache on _check_ollama() to avoid blocking the event loop
on every health poll (asyncio.to_thread was already in place)
5. Toast notification system (McToast.show) for transient status messages —
wired into connection status for Ollama/WebSocket state changes
Enforcement:
- CLAUDE.md updated with conventions 11-14 (no inline CSS, use panel macro,
use toasts, never block the event loop)
- tox lint + pre-push environments now fail on inline <style> blocks
https://claude.ai/code/session_014FQ785MQdyJQ4BAXrRSo9w
Co-authored-by: Claude <noreply@anthropic.com>
6.4 KiB
CLAUDE.md — AI Assistant Guide for Timmy Time
Tech stack: Python 3.11+ · FastAPI · Jinja2 + HTMX · SQLite · Agno · Ollama · pydantic-settings · WebSockets · Docker
For agent roster and conventions, see AGENTS.md.
Architecture Patterns
Config access
from config import settings
url = settings.ollama_url # never use os.environ.get() directly in app code
Singletons
from dashboard.store import message_log
from infrastructure.notifications.push import notifier
from infrastructure.ws_manager.handler import ws_manager
HTMX response pattern
return templates.TemplateResponse(
"partials/chat_message.html",
{"request": request, "role": "user", "content": message}
)
Graceful degradation
Optional services (Ollama, Redis, AirLLM) degrade gracefully — log the error, return a fallback, never crash.
Route registration
New routes: src/dashboard/routes/<name>.py → register in src/dashboard/app.py.
Development Environments (tox)
tox is the single source of truth for all Python environments.
Never run poetry run directly — always go through tox. All environment
config (deps, markers, flags) lives in tox.ini. The Makefile and CI
both delegate to tox.
Quick reference
tox -e unit # Fast unit tests (default pre-commit gate)
tox -e ci # Full CI suite with coverage + JUnit XML
tox -e lint # black --check + isort --check + bandit
tox -e format # Auto-format (black + isort)
tox -e dev # Start dashboard with auto-reload
All tox environments
| Environment | Purpose |
|---|---|
lint |
Check formatting + imports + security |
format |
Auto-format code |
typecheck |
mypy static analysis |
unit |
Fast unit tests, parallel |
integration |
Integration tests, parallel |
functional |
Functional tests, sequential |
e2e |
End-to-end tests |
fast |
unit + integration combined |
ollama |
Live LLM tests (requires Ollama) |
ci |
Coverage + JUnit XML (mirrors GitHub Actions) |
coverage |
Coverage terminal + XML |
coverage-html |
Coverage HTML report |
pre-push |
Lint + full CI suite (mirrors GitHub Actions exactly) |
dev |
uvicorn with auto-reload |
all |
All tests, parallel |
Testing notes
- Stubs in conftest:
agno,airllm,pyttsx3,telegram,discordstubbed viasys.modules.setdefault()— tests run without those packages - Test mode:
TIMMY_TEST_MODE=1set automatically in conftest - FastAPI testing: Use the
clientfixture - Async:
asyncio_mode = "auto"— async tests detected automatically - Coverage threshold: 73% (
fail_underinpyproject.toml)
Key Conventions
- Tests must stay green. Run
tox -e unitbefore committing. Runtox -e pre-pushbefore pushing (mirrors CI exactly). - No cloud AI dependencies. All inference on localhost.
- Keep the root directory clean. No new top-level files without purpose.
- Follow existing patterns — singletons, graceful degradation, pydantic config.
- Security defaults: Never hard-code secrets.
- XSS prevention: Never use
innerHTMLwith untrusted content. - Keep routes thin — business logic lives in the module, not the route.
- Prefer editing existing files over creating new ones.
- Use
from config import settingsfor all env-var access. - Use tox for everything. Never run
poetry rundirectly — usetox -e <env>. - No inline CSS in templates. All styles go in
static/style.css(base theme) orstatic/css/mission-control.css(page-specific).{% block extra_styles %}must stay empty. If you need new styles, append them to the appropriate CSS file. - Use the panel macro for repeated
.card.mc-panelmarkup:{% from "macros.html" import panel %}/{% call panel("TITLE") %}...{% endcall %}. Seemacros.htmlfor kwargs (id, hx_get, etc.). - Toast for transient messages. Use
McToast.show(msg, level)(info/warn/error) instead of rendering errors inline in the chat log. The toast container lives inbase.html. - Never block the event loop. Wrap synchronous I/O (HTTP calls, file reads) in
asyncio.to_thread(). Cache health-check results with a TTL when polling external services.
Frontend Architecture
Stylesheets
| File | Purpose |
|---|---|
static/style.css |
Base theme: palette, layout, header, chat, Bootstrap overrides, mobile breakpoints |
static/css/mission-control.css |
Page-specific styles (tasks, briefing, swarm, calm, etc.), toast system, connection indicator |
Rule: No <style> blocks in Jinja2 templates. All CSS lives in the two static files above. The {% block extra_styles %} hook exists for emergencies only and must remain empty in committed code.
CSS custom properties
Defined in :root in style.css. Use these — never hard-code colours:
var(--green) var(--amber) var(--red) var(--purple) var(--orange)
var(--text-bright) var(--text) var(--text-dim)
var(--bg-deep) var(--bg-panel) var(--bg-card) var(--border)
Jinja2 macros
src/dashboard/templates/macros.html — reusable components:
{% from "macros.html" import panel %}
{% call panel("TITLE", hx_get="/endpoint", hx_trigger="every 10s") %}
<p>Panel body content</p>
{% endcall %}
Toast notifications (JS)
McToast.show('Ollama reconnected', 'info'); // green border
McToast.show('Connection lost', 'warn'); // amber border
McToast.show('Request failed', 'error'); // red border
Security-Sensitive Areas
src/timmy_serve/— API server, payment configuration- Any file handling secrets or authentication tokens
Entry Points
| Command | Module | Purpose |
|---|---|---|
timmy |
src/timmy/cli.py |
Chat, think, status |
timmy-serve |
src/timmy_serve/cli.py |
API server (port 8402) |
Module Map (8 packages)
| Package | Purpose |
|---|---|
timmy/ |
Core agent, personas, agent interface, semantic memory |
dashboard/ |
FastAPI web UI, routes, templates |
infrastructure/ |
WebSocket, notifications, events, LLM router |
integrations/ |
Discord, Telegram, Siri Shortcuts, voice NLU |
spark/ |
Event capture and advisory engine |
brain/ |
Identity system, memory interface |
timmy_serve/ |
API server |
config.py |
Pydantic settings (foundation for all modules) |