Fathom Mode
A planning session. While active, don't execute — help the user build shared understanding via dialogue.
Resolving the script path
This skill bundle ships Python scripts in the scripts/ subdirectory next to this SKILL.md. To invoke them, construct the absolute path from the path you used to read this SKILL.md: take the SKILL.md absolute path, drop SKILL.md, append scripts/<script-name>.py. Use that absolute path with Bash. The scripts handle their own internal imports (each finds its sibling modules via Python's automatic sys.path).
State lives at ~/.fathom-mode/active_session.json regardless of where the bundle is installed (per the scripts' built-in path resolution). This means a session started in one environment can be continued in another that uses the same protocol.
In examples below, <scripts> stands for the resolved absolute path you computed above.
Starting a session
On the first user message, you MUST call both scripts before responding:
Step 1 — Create the session (no score returned):
python3 <scripts>/init_session.py --task "<user's task>"
The output has session_id, task, next_target_dimension, etc. It intentionally does NOT include score_block_str — scoring is step 2's job.
Step 2 — Score turn 1 — follow the Per-turn protocol below, treating the user's bootstrap message as turn 1. The score_block_str you place at the top of your response comes from THIS call (update_graph.py), not step 1.
Do not skip step 2. Both scripts run for the first user message.
Per-turn protocol
For each subsequent user message during an active fathom session, BEFORE responding, invoke update_graph.py via Bash with the user's message + your extracted nodes:
python3 <scripts>/update_graph.py <<'FATHOM_TURN_END'
{"user_input": "<user's verbatim message>", "nodes": [<your extracted nodes as JSON array>]}
FATHOM_TURN_END
The closing FATHOM_TURN_END must be at column 0 with no leading whitespace. JSON-encode user_input per JSON rules (escape " \ \n); the heredoc protects against shell escaping.
The script returns JSON with score_block_str, plan_hint_str, next_target_dimension, etc.
Format your response in three parts:
- Restate your understanding of the user's intent, surfacing any assumptions you have made, so the user can catch misinterpretations early.
- One insight that supplements a missing dimension, clarifies an ambiguity, corrects a technical misconception, or reframes the user's angle. 2-4 sentences; let the user's complexity set the length within that range.
- One question that advances a missing dimension (use the script's
next_target_dimensionfield as the target).
Place score_block_str verbatim at the top of your response. If plan_hint_str is non-empty, append it verbatim at the end.
Plan trigger
If the user expresses intent to plan, do NOT call update_graph.py this turn. Instead:
- Call:
python3 <scripts>/compile_plan.py - Read its stdout as the structured intent markdown — do NOT show it to the user verbatim.
- Write a plan for the user's task, grounded in every section of the structured intent. Do not introduce concerns absent from it.
- End your plan with: "Reply approve to proceed with this plan, reject to discard, or describe what to change."
Note: phrases like "plan a meeting" describe the session's content, not a request to plan — judge from context.
Approval flow
After presenting a plan, the next user message is a verdict on it. Do NOT call update_graph.py this turn. Judge the user's message:
-
If the user expresses approval of the plan: execute the plan using normal tools (Edit, Write, Bash, etc.). After execution completes, call:
python3 <scripts>/exit_session.py -
If the user describes changes to the plan: revise the plan inline, grounded in the same structured intent. Present the revised plan and end with "Reply approve to proceed with this plan, reject to discard, or describe what to change." You remain in the approval-waiting state.
-
If the user expresses intent to reject the plan: call:
python3 <scripts>/exit_session.py -
If the user's message is unrelated to the plan: answer the question directly, then add: "Still awaiting your response on the plan — reply approve to proceed, reject to discard, or describe what to change."
-
If the message is ambiguous: ask one clarifying question about which of the above the user intends.
Detecting which protocol mode you're in
Before each turn, check the session state file at ~/.fathom-mode/active_session.json. The awaiting_approval boolean indicates which mode applies:
awaiting_approval: false→ Per-turn protocolawaiting_approval: true→ Approval flow
If the file is absent and the user message looks like a fathom-trigger (matches this skill's description), bootstrap a session via Starting a session above.
Extraction: --nodes JSON
Array of node dicts. Each:
{
"id": "n1",
"dimension": "why",
"node_type": "goal",
"content": "<your distilled understanding>",
"raw_quote": "<verbatim substring from user's message>",
"confidence": 0.85
}
Use fresh n1, n2 per turn — the script auto-prefixes with the turn label.
Dimensions: WHO people/roles/stakeholders · WHAT subject/object/content · WHY purpose/motivation/values · WHEN time/deadline · WHERE physical location/spatial only (NOT "where in life") · HOW method/approach/risks/conditions.
Purpose ("in order to…") → WHY, not WHERE. Subject → WHAT, method → HOW.
node_type: fact / belief / value / intent / constraint / emotion / assumption / goal
Discipline
raw_quoteMUST be a verbatim substring of the user's message. If you can't point to the exact words, don't create that node.- Never assert CAUSAL unless the user explicitly used causal language ("because", "leads to", "causes", "due to", "so that"). Otherwise use
relation_type: supportsordependency. - Don't extract from confirmations. If the user's whole message is purely a confirmation or acknowledgment with no new content, skip the script call entirely and ask one follow-up question.
- Anchor user's main task on turn 1. Always emit at least one INTENT or GOAL node.
Tangential handling
If the user's message is clearly unrelated to the active task:
- Prefix response with
[tangential - not updating the graph]. - Answer briefly.
- Do NOT call update_graph.py. Do NOT show the Score block.
- End with:
(Fathom session unaffected, score still N%. Ready when you want to return to <current topic>.)
Task-type (optional)
Pass --task-type if you can categorize: thinking (decision/tradeoffs) / creation (artifact) / execution (action) / learning (skill) / general. Omit if unclear.
Reference docs
For deeper detail (read these via the same path-resolution pattern as scripts — references/ is sibling of scripts/):
references/three-part-turn.md— 5 example sessions covering all 4 insight styles + meta-rulesreferences/score-interpretation.md— depth-band questioning patterns for different Score levelsreferences/plan-format.md— 5-section structured plan template