TrainFitter
CLAUDE.md2 starsChanged 4 months agoMITView on GitHub
Portfolio project: a multi-agent pipeline (personal-trainer domain) demonstrating agent orchestration, dual free/LLM engines, and a safety-gated human-in-the-loop design. Public repo: github.com/serpeigd/TrainFitter. - Language split: all repo content (code, comments, docs, commit messages, UI copy) is written in English. Chat with the user stays in Spanish. - Scoping exception: Python identifiers, dict/JSON keys, and schema/state literal values (e.g. perfil_cliente, revision_reforzada, generar_borrador_rutina) stay in Spanish — only prose/comments/docs were translated. Don't "fix" these; it's a deliberate, documented decision. - Git identity: repo-local…
- Reads credentials
In this repository2 other files it gives its agents.
- new-test-clientSkill
- update-knowledge-baseSkill
The file
We split this CLAUDE.md into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 9
Language split: all repo content (code, comments, docs, commit messages, UI copy) is written in English.
- Very specific: line 177
When proposing next steps, keep this the default.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
TrainFitter — Working Notes for Claude
Portfolio project: a multi-agent pipeline (personal-trainer domain) demonstrating agent orchestration, dual free/LLM engines, and a safety-gated human-in-the-loop design. Public repo: github.com/serpeigd/TrainFitter.
Standing conventions (do not re-ask)
- Language split: all repo content (code, comments, docs, commit messages, UI copy) is written in English. Chat with the user stays in Spanish.
- Scoping exception: Python identifiers, dict/JSON keys, and schema/state
literal values (e.g.
perfil_cliente,revision_reforzada,generar_borrador_rutina) stay in Spanish — only prose/comments/docs were translated. Don't "fix" these; it's a deliberate, documented decision. - Git identity: repo-local
user.emailis set to the GitHub noreply address (125498425+serpeigd@users.noreply.github.com). Already configured — new commits use it automatically. - Push future work to the
serpeigd/TrainFitterGitHub repo (public, portfolio). - Commit + push is automatic (2026-08-19, explicit standing authorization in
chat) — no confirmation step before it, for any change in this repo.
Previously every commit was confirmed via a question first; that step is
gone now. The bar for what gets committed is unchanged: tests pass, lint is
clean, docs (
CLAUDE.md/docs/decisiones.md) are updated in the same change,git fetch+ rebase againstorigin/masterfirst if it's moved. Still surface what changed and why after pushing, same as always — only the "should I commit this?" question is gone, not the summary. - Keep it short (2026-08-13, explicit request in chat). Too much text, too much explaining. Lead with the answer or the change; give reasoning only where it would change a decision. Don't recap work already visible in the diff, don't restate the question before answering it, and don't close with a summing-up line. Applies to chat, commit messages and PR bodies. Reference docs (README, this file) can be longer, but only where the length earns it.
- Full chronological decision log with rationale lives in
docs/decisiones.md— read it only if you need the why behind a past call; don't load it by default (it's long). docs/highlights.mdis the condensed, interview-ready version of the same log (22 decisions, ~2 pages) — update it when a change adds a genuinely new "defensible decision," not for routine work.- Scheduled documentation-sync runs (added 2026-08-07, explicit decision in
chat): standing authorization to merge doc-only PRs from that recurring task
yourself, without waiting for approval, once CI (
ci.yml) is green — same bar as any other merge, just no confirmation step for this specific, narrow case (README/docs/changes only, never product code). That scheduled run lands on a fresh randomly-named branch every time, so an unmerged PR from a previous run is never reused automatically. Before opening a new one, check for another open PR titled starting "docs: sync" — if found, fold any still-valid unique content from it into the new one, merge the more complete/accurate PR once CI is green, and close the other with a comment linking to the merged one. Don't leave two open at once.
Architecture (see docs/arquitectura.md for full detail)
Client intake JSON → routine_agent + diet_agent (motor="reglas"|"llm", same output schema)
→ validator_agent (ALWAYS rule-based, re-derives risk from raw profile)
→ verdict: aprobado_automatico | revision_reforzada
→ aprobado_automatico: sent automatically, zero clicks (mcp/gmail_client.py's
enviar_plan(), as of 2026-08-19 — see below)
→ revision_reforzada: human review, ALWAYS, before anything sends — but once
approved, "send" now means enviar_plan() directly too (a real send, no draft
in between); a Gmail draft is a secondary, explicit fallback button, not the
default path (see below)- Two interchangeable engines per generation agent:
"reglas"(default, free, no API key, deterministic per client — seeagents/variacion.py) vs"llm"(optional,ANTHROPIC_API_KEY, Claude tool-use forced output). Same output schema either way. - Validator is deliberately never LLM — deterministic safety gate,
defense-in-depth (cross-checks against
exercise_bank.py/food_bank.py, doesn't trust upstream agents' self-reported flags). - Orchestrator (
agents/orchestrator.py) is an explicit state machine:ficha_recibida → rutina_generada → dieta_generada → validado → (pendiente_aprobacion_humana | pendiente_revision_reforzada), pluserror. Takes anon_transitioncallback (default: console log) — this is what letsui/app.pyrender live progress without the orchestrator knowing Streamlit exists. ui/app.py(Streamlit): trainer-facing panel, ES/EN toggle viaTRANSLATIONS/OPTION_LABELSdicts +t()/opt()helpers. Widgets are standalone (notst.form) so conditional fields (e.g. injury detail) render immediately —st.formdoesn't rerun until submit.- Bilingual keyword matching in
perfil_utils.tags_lesiones()andfood_bank.etiquetas_excluidas()— safety-critical (injury/allergy detection), must match both Spanish and English free text.
Status
Phases 0–4 + 5-lite (Streamlit panel) done. Live demo at
trainfitter.streamlit.app (auto-redeploys
on push to master). 695 tests passing (pytest from repo root, wired into
CI), ~97% coverage on agents/+mcp/ (ui/app.py/main.py deliberately
excluded from coverage — verified live instead, same convention throughout).
What's built:
- Free rule engines (routine + diet,
agents/rutina_reglas.py/dieta_reglas.py) with an optionalmotor="llm"alternative, same output schema either way;agents/validator_agent.pyis a deliberately-never-LLM safety gate. agents/metodo.py: the trainer's volume/rest-time/calorie/macro knobs as a swappableMetodoEntrenadorconfig (Piece 1 of the "other trainers can self-host with their own judgment" plan — Fork A), threaded through both rule engines andejecutar_pipeline().METODO_POR_DEFECTOreproduces the project owner's own values unchanged. Piece 2a:cargar_metodo()reads a partialmetodo.json/METODO_JSONenv var (template:metodo.example.json) with strict safety-bound validation; an invalid método stops the pipeline inerrorinstead of falling back. The "Mi método" UI tab (2b) and a self-hosting guide (2c) aren't built yet.agents/food_bank.py(61 curated foods) +agents/planificador_comidas.pybuild a real 7-day meal plan (not just suggested-source lists) — synergy pairing, a shopping list, no-cook/quick-cook badges, and a client-set cuisine preference scoped to 1-2 days/week.ui/app.py(Streamlit): trainer panel (New Client / Revise Client / Clients dashboard, EN/ES toggle) plus a client-facing portal (magic link via a short Notion-stored reference code) — tab-based (Home/Meals/Routine/Check-in/Progress), with meal/exercise liking, adherence check-ins, a free monthly digest, and self-service link recovery.mcp/gmail_client.py: drafts (gmail.compose) plus real, deliberate, narrow sends (gmail.send) for the portal link,aprobado_automaticoauto-send, and therevision_reforzada"send directly" button —revision_reforzadais otherwise still always human-reviewed first, no exceptions.mcp/notion_connector.py: "Clients" + "Check-ins" databases, full-profile storage enabling "Revise client", per-client liked/disliked meals & exercises, cuisine preference.main.py(GitHub Actions cron,.github/workflows/inbox_trigger.yml): scans the inbox for adherence-checklist replies and new-client intake PDFs, fully automated, never sends or drafts anything itself.agents/pdf_generador.py/pdf_intake.py: fillable intake + checklist PDFs, styled diet/routine PDFs with the weekly meal table and shopping list.agents/analytics_parser.py: best-effort bloodwork-marker extraction, forcesrevision_reforzadaon out-of-range values.agents/suplementos_interacciones.py: curated supplement–medication interaction table backing the validator's generic check.- Competitor-research features (Kahunas.io): a YouTube search-results link
per exercise (
exercise_bank.enlace_video_demostracion(), portal + routine PDF), and per-exercise weekly weight logging in the check-in form → a progression chart in the portal's Progress tab (Check-ins' new "Exercise Logs (JSON)" property). - Exercise how-to text (
exercise_bank.instrucciones_ejercicio(), data inagents/exercise_instructions.json): ES/EN steps per exercise in a collapsed "How to do it" under each portal exercise. 41 entries adapt the MIT-licensed exercises-dataset text (hand-matched; seeTHIRD_PARTY_NOTICES.md), 31 are original. No GIFs/videos — that dataset's media is © Gym visual and not redistributable.agents/sugerir_contraindicaciones.pyprints contraindication suggestions from the muscle data for human review; it never edits the bank.
Known, accepted limitation: the Gmail OAuth token still expires every
7 days (Testing-mode publishing status) — attempted publishing to
Production (2026-09-02 to 09-07; a €10-15/year, this project's first real cost) — see
gh-pages branch hosts a privacy-policy
page at serpeigd.github.io/TrainFitter,
separate from master), but Google rejects a GitHub Pages user subdomain
for the app-homepage/privacy-policy requirement by policy (same excluded
category as Google Sites/Facebook/etc. — verifying a subpath isn't the
same as owning the platform), not a bug. Fixing it for real needs an
actually-owned domain (docs/status_history.md for the full trail and the exact steps to pick
this back up later. For now: re-authorize locally every ~7 days
(rm token.json, rerun the OAuth flow, update the GMAIL_TOKEN_JSON
Streamlit secret).
Full chronological development log — every session's changes, the direct
requests behind them, bugs found and fixed, and how each was verified —
lives in docs/status_history.md. Read it only
if you need the history behind a specific past decision, bug, or number
(when a feature shipped, why an earlier approach was abandoned, test
counts over time); don't load it by default, it's very long.
Free-only guardrail
The project's core promise is fully free, no paid API key required.
The only piece that would ever need one is the optional motor="llm"
path (pay-per-token Anthropic API) — it's designed but deliberately never
exercised against the real API. Every other planned addition (tests, deploy,
bloodwork parser, Gmail/Notion) uses local libraries or free-tier OAuth.
When proposing next steps, keep this the default; only touch motor="llm"
if the user explicitly opts in to spending money.
Key files
| Area | File |
| Routine rule engine | agents/rutina_reglas.py |
| Diet rule engine | agents/dieta_reglas.py |
| Trainer-configurable method (swappable volume/calorie/macro knobs) | agents/metodo.py |
| Weekly meal planner (breakfast/lunch/dinner/snacks, synergy pairing) | agents/planificador_comidas.py |
| Per-client seeded variety (exercise picks, phrasing) | agents/variacion.py |
| Validator | agents/validator_agent.py |
| Orchestrator | agents/orchestrator.py |
| Exercise/food banks | agents/exercise_bank.py, agents/food_bank.py |
Exercise how-to text + upstream muscle data (third-party notice: THIRD_PARTY_NOTICES.md) | agents/exercise_instructions.json |
| Supplement-medication interaction pairs | agents/suplementos_interacciones.py |
| Bloodwork parser | agents/analytics_parser.py |
| Diet/checklist PDF generation + reading | agents/pdf_generador.py |
| Intake PDF generation + reading | agents/pdf_intake.py |
| Adherence summary formatting (rating, Notion text, suggested next step) | agents/adherencia_parser.py |
| Gmail connector (draft + portal-link send + adherence-reply/new-intake search) | mcp/gmail_client.py |
| Notion connector (auto-save + check-ins + portal reference codes) | mcp/notion_connector.py |
| Automatic inbox trigger (cron; adherence + new intakes) | main.py, .github/workflows/inbox_trigger.yml |
| Streamlit UI | ui/app.py |
| Tests | tests/ (conftest.py fixture + test_*.py per module) |
| Example clients/outputs | examples/ |
| Knowledge base (RAG-level) | docs/base_conocimiento/*.md |
| Trainer's method (judgment-level) | docs/metodo_entrenador.md |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

