Branch: hackathon/tuffy-cli-submission. Companion doc: HACKATHON_SUBMISSION.md
(fill that in as each item below lands — it's the source for the actual Devfolio submission).
- Local assistant (tuffy-cli itself) — the base product being submitted.
- Elastimem — the own-built memory framework as a whole (
~/Projects/elastimem,CodebyKumar/elastimem) is the centerpiece of the bet: temporally-versioned facts, hybrid episodic recall, background extraction/consolidation, the Memory Governor, and the newest addition, the graph layer. Upgrade tuffy-cli to the latest Elastimem and verify the whole framework actually works end-to-end inside tuffy-cli — not just that it imports/builds. - Claude API integration — wire Claude in as the default model, using the credits provided for the event, and verify tool use / Elastimem recall works through Claude specifically. This pairing (Elastimem + Claude, both proven live in tuffy-cli) is the actual submission.
- Online/offline mode — a real, enforced runtime toggle (startup selector +
/networkcommand) between cloud (Claude, requires network) and fully local (llama.cpp, zero network) operation, with tool availability and the model's own self-description changing accordingly. Demonstrates the local-first story isn't just "a local model exists" — it's a system that knows and honestly reports which mode it's in, and mechanically enforces it. - Stretch, only if 1–4 are solid with time left: Maya Research's native voice models —
would replace/augment the current Whisper STT + Piper TTS voice path. Not part of this
submission's theme claim (see
HACKATHON_SUBMISSION.md→ Theme fit) — treat as a bonus demo moment, not a pitch pillar.
Judging rewards a focused proof of the hardest part over many incomplete features — do not start the stretch goal until 1–3 are demo-ready.
Primary: Next frontier capability (Elastimem as a self-built memory architecture, not a
repackaging of vector-DB-plus-chatbot memory — the graph layer is one capability inside it, not
the headline). Secondary: Infrastructure everyone else will build on (Elastimem as a
standalone library already backing two products). See HACKATHON_SUBMISSION.md for the full
reasoning — don't stretch the pitch to cover themes that don't fit.
- Elastimem as a whole — versioned facts, hybrid FTS5+cosine episodic recall, governor-scaled budgets, background consolidation, and now graph-based entity/relationship recall — is a genuine capability gap in most local/terminal agents, not just the graph piece alone. Closest fit to "next frontier capability."
- Elastimem already exists and is architecturally sound — this is an upgrade-and-verify pass inside the 5-hour window, not a from-scratch build, which is what makes it achievable.
- Claude as the driving model for both the chat loop and the memory extraction pipeline makes AI "core," not decorative — matches the "AI Depth & Nativeness" judging criterion directly.
- The online/offline toggle turns "Claude integration" and "local-first" from a marketing claim into an enforced, demoable mechanism: switching modes actually swaps the active model, actually removes network tools from what the model is told it can do, and the model actually reports its own mode correctly when asked — not just a flag that quietly does nothing.
- Confirm which commit/tag in
~/Projects/elastimemis the latest (includes the graph layer,src/elastimem/graph.py) and whether it's been pushed toCodebyKumar/elastimemon GitHub. Localmainwas 8 commits ahead of origin — pushed (clean fast-forward) as58fc1a2. - Update tuffy-cli's
pyproject.tomlgit dependency pin forelastimemto that commit/tag. Pinned to58fc1a2c14c544da0bf9b5a75a142662761d5407;uv sync --extra voicereinstalled. - Read
src/memory.py(tuffy-cli's Elastimem adapter) and confirm it's using the current Elastimem surface. Callsmem.recall()/mem.remember()/mem.build_context()— but two real gaps found once verification went past "imports cleanly" to "actually reaches the model":src/prompts/templates.pynever read thegraph_contextsectionbuild_context()produces (fixed — added aRELATED TOPICSblock), and Elastimem'sworker_max_tokensdefault (96) was too small for the combined facts+graph extraction completion, truncating the JSON mid-payload and silently dropping the whole extraction (fixed — raised to 320 in bothelastimem.open(...)call sites insrc/memory.py). - Manually verify the full framework end-to-end in tuffy-cli — for real, not just imports.
Recorded a turn naming real entities, drained the worker, confirmed via direct SQLite queries
that
graph_nodes/graph_edgeswere actually populated (this is what caught the token-budget bug); then confirmed an entity-naming query populatesgraph_contextand renders as a real "RELATED TOPICS" block in the system prompt (this is what caught the templates.py gap). Also ran Elastimem's own upstream graph test suite (47/47 passing). - Run tuffy-cli's existing test suite against the upgraded dependency; fix any breakage. 140/140 passed throughout, including after both fixes.
- Pulled Elastimem's newer upstream commit (
7b56c92, "Raise LITE tier's episodic/graph floor") and re-pinned/reinstalled.graph_hopsat LITE is now 1 (was 0) — LITE performs real 1-hop read traversal against whatever graph already exists (writes still require STANDARD/FULL, since those need an LLM extraction call). Re-verified directly against this machine's real LITE tier (~2 GiB available RAM, noELASTIMEM_TIERoverride): seed detection and traversal both succeed against the live database. Rendering is still budget-capped at LITE (~10 tokens by default, 25% of LITE's small episodic share) — confirmed a short single-entity result renders correctly, and a larger multi-entity cluster correctly degrades to empty rather than truncating garbled output. Full tuffy-cli suite (141/141) still passes against the upgraded pin.
- Build a native Anthropic Messages API provider —
src/llm/anthropic_provider.py— not the OpenAI-compatible path (Anthropic's wire format differs: separate endpoint,x-api-key/anthropic-versionheaders, top-levelsystem, different SSE event shape). Registered as provider"anthropic"insrc/llm/__init__.py/src/models/registry.py. - Add Claude model entries —
src/models/configs/anthropic.py: Opus 5, Sonnet 5, Haiku 4.5. - Group
/modelsoutput by provider (Local / OpenAI-compatible API / Anthropic). -
ANTHROPIC_API_KEYadded to.env(confirmed gitignored before use). - Smoke-test tool use / Elastimem recall specifically against Claude with a real API key.
Live-verified: completion + streaming + system-prompt translation; full ReAct tool-use loop
(with self-correction) computing
47 × 89 = 4,183via actualrun_pythonexecution; Elastimem facts/episodic recall/build_context()all driven by Claude. Caught and fixed a real bug along the way — the adapter sent bothtemperatureandtop_p, which the Messages API rejects with a 400 (fixed by making them mutually exclusive inanthropic_provider.py). - Set a Claude model as the default active model.
DEFAULT_MODELinsrc/models/__init__.pyset toclaude-haiku-4-5-anthropic(fastest/cheapest Claude, matches "least model of Claude" ask)./modelsno-arg listing reordered to Local → Anthropic (Claude) → OpenAI-compatible API. Verified via the realload_agent()startup path — loads and completes correctly.
- Startup arrow-key selector (
select_one()insrc/cli/display.py) asks Online or Offline every launch, pre-selected on the last persisted choice (src/settings.py→get_network_mode()/set_network_mode()), defaulting to online on first run. Falls back to plain typed input on non-TTY/Windows (notermios/tty). -
src/network_mode.pyholds the live in-process mode (get_mode()/set_mode()/is_offline());main.pyreads it at startup to decide the active model,/network online|offline(src/cli/commands.py) changes it mid-session. - Offline is a hard restriction, not a hint:
main.pyrefuses to start an API model when offline (falls back toFALLBACK_MODELif the persisted default isn't local);/models switchrefuses to switch to a non-llama_cppmodel while offline;/network offlinemid-session auto-switches off an active API model toFALLBACK_MODEL. - Network-dependent tools (
web_search,translateinsrc/tools/research.py) are gated twice: dropped entirely from the system prompt's tool list while offline (src/tools/registry.py'stool_lines(exclude_names=...), wired fromsrc/prompts/__init__.py) so the model isn't told a tool exists that it can't use, and refused at call time with a same message if the model tries anyway. - Identity/self-model (
src/identity.py'sdescribe(),src/prompts/templates.py'sself_model()) now states current network mode explicitly in every system prompt, so the model never assumes "local" or "online" by default — matches the rewordedtuffypersona inpersonas.yaml. -
/statusnow reports live network mode alongside model/provider.
- Pick and rehearse one end-to-end scenario that shows graph-memory recall working through Claude, live — this is the centerpiece of the pitch.
- Second demo beat: show the online/offline toggle live — start online on Claude, flip to
/network offlinemid-session (watch it fall back to the local model and drop web_search/ translate from the tool list and system prompt), flip back online. - Capture a project image/snapshot and record the demo video.
- Write up sections 3–7 of
HACKATHON_SUBMISSION.mdfrom what was actually built.
- Look at Maya Research's native voice models as a possible swap-in for
src/voice/'s current Whisper STT + Piper TTS. - Scope a minimal integration (or explicitly decide it's demo-only / not worth the risk this close to the deadline).
- Re-run Devfolio MCP lookup once registration/check-in opens (
getUserActiveHackathons→getHackathonTracksAndPrizes→getProjectSubmissionGuide). - Decide track to apply to once tracks are fetchable.
- Submit via Devfolio MCP or dashboard before 4:30 PM IST deadline, well before the wire.