Skip to content

Commit 49573ae

Browse files
merge: resolve conflicts with main (local LLMs + PID safety)
Conflicts resolved: - .gitignore: combined both sets of exclusions - cli-reference.md: keep both --lan/--password and --agent ollama/lmstudio - cleanup.py: keep main's PID-recycling-safe kill (ps check before SIGTERM) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2 parents 48429bd + e4f4d9a commit 49573ae

36 files changed

Lines changed: 867 additions & 164 deletions

‎.gitignore‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,11 @@ site/
477477

478478
# Internal/planning docs (kept locally, not published)
479479
docs/internal/
480-
docs/plans/
481480
docs/local_repo_docs/
481+
docs/plans/
482482
docs/architecture/
483+
484+
# Demo recordings (large, local-only)
483485
demos/
484486

485487
# Agent workflow artefacts

‎agents/claude/socratic-mentor.md‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,9 @@ Exceptions: explicit "just show me", 4+ rounds stuck, pure syntax lookup, boiler
4949

5050
## Session State Management
5151

52-
At the start of each session, create the session state file:
53-
```bash
54-
mkdir -p ~/.config/studyctl
55-
cat > ~/.config/studyctl/session-state.json << 'EOF'
56-
{"energy": "medium", "topic": "", "pomodoro": null}
57-
EOF
58-
```
52+
Session state is created by `studyctl session start`. Do NOT manually create the file.
5953

60-
When the user specifies their energy level, update the state file:
54+
When the user specifies their energy level mid-session, update the state file:
6155
```bash
6256
python3 -c "import json; from pathlib import Path; p=Path.home()/'.config/studyctl/session-state.json'; d=json.loads(p.read_text()); d['energy']='LEVEL'; p.write_text(json.dumps(d))"
6357
```
@@ -71,8 +65,7 @@ This state is read by the Claude Code status line to show persistent session inf
7165

7266
Follow `agents/shared/session-protocol.md`. Summary:
7367

74-
1. Initialise the session state file (see above)
75-
2. Run system checks:
68+
1. Run system checks:
7669
```bash
7770
studyctl resume # Where you left off
7871
studyctl status # Check sync state
@@ -89,7 +82,7 @@ Follow `agents/shared/session-protocol.md`. Summary:
8982
## Session Types
9083

9184
- **Study session:** arrival → state check → system check → topic → Socratic session → record progress
92-
- **Spaced review:** `studyctl review` → quiz overdue topics (interleave if 2+ due) → record scores
85+
- **Spaced review:** `studyctl review` → quiz overdue topics (max 3 per session, interleave if 2+ due) → record scores
9386
- **Body doubling (active):** agree goal + time → start/mid/end check-ins
9487
- **Body doubling (async):** periodic low-demand check-ins, no teaching
9588
- **Ad-hoc question:** identify topic → respond Socratically
@@ -170,6 +163,13 @@ Requires: pandoc, @mermaid-js/mermaid-cli for markdown→PDF with diagram suppor
170163

171164
---
172165

166+
## Voice Output (study-speak)
167+
168+
The learner can toggle voice on/off with `/speak-start` and `/speak-stop`.
169+
Follow the full rules in `agents/shared/session-protocol.md` (Voice Output section).
170+
171+
---
172+
173173
## Anti-Patterns to Avoid
174174

175175
- **The Encyclopedia Response**: Too much information at once

‎agents/gemini/study-mentor.md‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,13 @@ Then follow `session-protocol.md`: combined state check (energy, mood, setup), a
6969
## Session Types
7070

7171
- **Study session:** arrival → state check → system check → topic → Socratic session → record progress
72-
- **Spaced review:** `studyctl review` → quiz overdue topics (max 3, interleave if 2+ due) → record
72+
- **Spaced review:** `studyctl review` → quiz overdue topics (max 3 per session, interleave if 2+ due) → record
7373
- **Body doubling:** agree goal + time → start/mid/end check-ins
7474
- **Ad-hoc question:** identify topic → respond Socratically
7575

7676
## AuDHD Support (Always Active)
7777

78-
- **Bottom-up processing**: Concrete example first, then pattern, then principle
79-
- **Executive function**: Explicit starting points, time-boxes, numbered steps, summaries every 3-5 exchanges
80-
- **RSD/Imposter syndrome**: Reframe mistakes as exploration, bridge to infrastructure experience
81-
- **Overload prevention**: Max 3-4 concepts, tables over prose, TL;DR at top, mermaid diagrams
82-
- **Hyperfocus**: Time warnings, exit points, hydration/food reminders
83-
- **Emotional regulation**: Micro-celebrations for genuine progress, sensory checks at 45+ min
84-
- **Transition support**: Summarise when switching, parking lot for tangents
78+
See `agents/shared/audhd-framework.md` for the complete methodology. Always active — bottom-up processing, executive function scaffolding, RSD management, PDA sensitivity, shutdown protocol, and hyperfocus support.
8579

8680
## End-of-Session Protocol
8781

@@ -90,14 +84,20 @@ Follow `wind-down-protocol.md`:
9084
2. End session: `studyctl session end --notes "<summary>"` — flushes parking lot to DB, exports to Obsidian
9185
3. Suggest next review based on spaced repetition intervals
9286
4. Offer calendar blocks: `studyctl schedule-blocks`
93-
5. If session was 25+ min, remind to take a break
87+
5. If session exceeds the energy-adaptive threshold (see `agents/shared/break-science.md`), remind to take a break
9488
6. Parking lot: note tangential topics worth revisiting
9589

9690
## Break Reminders
9791

98-
- 25 min: "Good time for a 5-minute break."
99-
- 50 min: "Take a proper break before continuing."
100-
- 90 min: "You should stop here and come back fresh."
92+
Follow the energy-adaptive schedule in `agents/shared/break-science.md`:
93+
- High energy: 25/50/90 min
94+
- Medium energy: 20/40/75 min
95+
- Low energy: 15/30/60 min
96+
97+
## Voice Output (study-speak)
98+
99+
The learner can toggle voice on/off with `@speak-start` and `@speak-stop`.
100+
Follow the full rules in `agents/shared/session-protocol.md` (Voice Output section).
101101

102102
## Anti-Patterns to Avoid
103103

‎agents/kiro/study-mentor/persona.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Run `studyctl config show` to see your configured notebook IDs.
3838
## Session Types
3939

4040
**Study session:** arrival → state check → system check → topic → Socratic session → record
41-
**Spaced review:** arrival → state check → `studyctl review` → quiz overdue topics (interleave if 2+ due) → record
41+
**Spaced review:** arrival → state check → `studyctl review` → quiz overdue topics (max 3 per session, interleave if 2+ due) → record
4242
**Body doubling (active):** agree goal + time → start/mid/end check-ins
4343
**Body doubling (async):** "I'm working, not studying. Check in on me." → periodic low-demand check-ins
4444
**Ad-hoc question:** identify topic → query NotebookLM → respond Socratically

‎agents/opencode/study-mentor.md‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,13 @@ Then follow `session-protocol.md`: combined state check (energy, mood, setup), a
7373
## Session Types
7474

7575
- **Study session:** arrival → state check → system check → topic → Socratic session → record progress
76-
- **Spaced review:** `studyctl review` → quiz overdue topics (max 3, interleave if 2+ due) → record
76+
- **Spaced review:** `studyctl review` → quiz overdue topics (max 3 per session, interleave if 2+ due) → record
7777
- **Body doubling:** agree goal + time → start/mid/end check-ins
7878
- **Ad-hoc question:** identify topic → respond Socratically
7979

8080
## AuDHD Support (Always Active)
8181

82-
- **Bottom-up processing**: Concrete example first, then pattern, then principle
83-
- **Executive function**: Explicit starting points, time-boxes, numbered steps, summaries every 3-5 exchanges
84-
- **RSD/Imposter syndrome**: Reframe mistakes as exploration, bridge to infrastructure experience
85-
- **Overload prevention**: Max 3-4 concepts, tables over prose, TL;DR at top, mermaid diagrams
86-
- **Hyperfocus**: Time warnings, exit points, hydration/food reminders
87-
- **Emotional regulation**: Micro-celebrations for genuine progress, sensory checks at 45+ min
88-
- **Transition support**: Summarise when switching, parking lot for tangents
82+
See `agents/shared/audhd-framework.md` for the complete methodology. Always active — bottom-up processing, executive function scaffolding, RSD management, PDA sensitivity, shutdown protocol, and hyperfocus support.
8983

9084
## End-of-Session Protocol
9185

@@ -94,14 +88,20 @@ Follow `wind-down-protocol.md`:
9488
2. End session: `studyctl session end --notes "<summary>"` — flushes parking lot to DB, exports to Obsidian
9589
3. Suggest next review based on spaced repetition intervals
9690
4. Offer calendar blocks: `studyctl schedule-blocks`
97-
5. If session was 25+ min, remind to take a break
91+
5. If session exceeds the energy-adaptive threshold (see `agents/shared/break-science.md`), remind to take a break
9892
6. Parking lot: note tangential topics worth revisiting
9993

10094
## Break Reminders
10195

102-
- 25 min: "Good time for a 5-minute break."
103-
- 50 min: "Take a proper break before continuing."
104-
- 90 min: "You should stop here and come back fresh."
96+
Follow the energy-adaptive schedule in `agents/shared/break-science.md`:
97+
- High energy: 25/50/90 min
98+
- Medium energy: 20/40/75 min
99+
- Low energy: 15/30/60 min
100+
101+
## Voice Output (study-speak)
102+
103+
The learner can toggle voice on/off with `@speak-start` and `@speak-stop`.
104+
Follow the full rules in `agents/shared/session-protocol.md` (Voice Output section).
105105

106106
## Anti-Patterns to Avoid
107107

‎agents/shared/session-protocol.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ If `studyctl streaks` shows a current streak, mention it: "Day [N] of your study
7878

7979
Based on state check + what's due, propose a session plan:
8080

81-
- If spaced repetition items are due → review session (interleave related topics)
81+
- If spaced repetition items are due → review session (max 3 topics per session, interleave related topics; if more due, prioritise longest-overdue)
8282
- If struggle topics detected → targeted practice with extra scaffolding
8383
- If nothing due + high energy → new material
8484
- If low energy or flat → body doubling or light review

‎docs/agent-install.md‎

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ How to set up the AI mentor agents for kiro-cli, Claude Code, Gemini CLI, OpenCo
1111
- [Gemini CLI Setup](#gemini-cli-setup)
1212
- [OpenCode Setup](#opencode-setup)
1313
- [Amp Setup](#amp-setup)
14+
- [Local LLMs (Ollama / LM Studio)](#local-llms-ollama--lm-studio)
1415
- [Agent Descriptions](#agent-descriptions)
1516
- [Skills Reference](#skills-reference)
1617
- [Uninstalling](#uninstalling)
@@ -276,6 +277,141 @@ amp
276277
# AGENTS.md is loaded automatically — just start asking for a study session
277278
```
278279

280+
## Local LLMs (Ollama / LM Studio)
281+
282+
studyctl can use local LLMs as the study mentor backend instead of cloud Claude. This uses Claude Code as the frontend but points it at a local model server via environment variables.
283+
284+
### Honest expectations
285+
286+
Local models are a **cost/privacy trade-off with significant capability regression**:
287+
288+
- **Works well**: Simple tasks, single-turn questions, code explanation, light review
289+
- **Works poorly**: Multi-file refactors, complex agentic loops, subagent coordination, test-fix cycles
290+
- **Rough quality**: Best local models (Qwen3-Coder 30B, Devstral 24B) are approximately Claude Haiku 3.5 quality for agentic tasks
291+
292+
If you need reliable multi-step study sessions, cloud Claude is substantially better. Local LLMs are best for privacy-sensitive work, offline use, or cost-free experimentation.
293+
294+
### API compatibility
295+
296+
Claude Code requires the **Anthropic Messages API format** (`/v1/messages`). Not all local backends support this:
297+
298+
| Backend | Anthropic API? | Notes |
299+
|---------|---------------|-------|
300+
| **LM Studio 0.4.1+** | Native | Simplest path. Just load a model and point studyctl at it. |
301+
| **llama.cpp server** | Native (since Nov 2025) | Low-level, good for headless servers. |
302+
| **LiteLLM proxy** | Translates | Bridges Ollama's OpenAI API to Anthropic format. |
303+
| **Ollama (direct)** | No | Only speaks OpenAI format. Needs LiteLLM as a proxy. |
304+
305+
### Recommended models
306+
307+
Models ranked by suitability for studyctl's agentic, multi-turn workflow:
308+
309+
| Model | VRAM/RAM | Context | Best for |
310+
|-------|----------|---------|----------|
311+
| **Qwen3-Coder 30B** | ~19 GB | 256K | Best open-source for coding. Explicit tool-use training. |
312+
| **Devstral 24B** | ~14 GB | 128K | Top SWE-bench open-source. Runs on 32 GB Mac. Apache 2.0. |
313+
| **DeepSeek-Coder-V2 16B** | ~9 GB | 160K | Good at the 16B weight class. |
314+
315+
**Minimum context window**: 64K tokens. Claude Code's system prompt, CLAUDE.md, tool definitions, and file reads consume 20K-50K tokens before your conversation even starts. Models with <32K context will truncate constantly.
316+
317+
**Not recommended**: CodeLlama (superseded), minimax m2.7 (known freeze bug), anything <10B parameters.
318+
319+
### Option A: LM Studio (simplest)
320+
321+
1. Install [LM Studio](https://lmstudio.ai) (0.4.1+)
322+
2. Download and load a model (e.g., Qwen3-Coder 30B)
323+
3. Start the local server (LM Studio > Developer tab > Start Server)
324+
4. Run studyctl:
325+
326+
```bash
327+
studyctl study "Python decorators" --agent lmstudio
328+
```
329+
330+
Config (`~/.config/studyctl/config.yaml`):
331+
```yaml
332+
agents:
333+
priority: [lmstudio, claude] # prefer local, fall back to cloud
334+
lmstudio:
335+
model: qwen3-coder # must match what's loaded in LM Studio
336+
# base_url: http://localhost:1234 # default
337+
```
338+
339+
### Option B: Ollama via LiteLLM proxy
340+
341+
Ollama doesn't speak Anthropic API natively. You need [LiteLLM](https://docs.litellm.ai/) as a translation layer.
342+
343+
1. Install Ollama and pull a model:
344+
```bash
345+
ollama pull qwen3-coder:30b
346+
```
347+
348+
2. Install and configure LiteLLM:
349+
```bash
350+
pip install litellm
351+
```
352+
353+
Create `litellm-config.yaml`:
354+
```yaml
355+
model_list:
356+
- model_name: qwen3-coder
357+
litellm_params:
358+
model: ollama_chat/qwen3-coder:30b
359+
api_base: http://localhost:11434
360+
```
361+
362+
3. Start LiteLLM:
363+
```bash
364+
litellm --config litellm-config.yaml --port 4000
365+
```
366+
367+
4. Run studyctl:
368+
```bash
369+
studyctl study "SQL window functions" --agent ollama
370+
```
371+
372+
Config:
373+
```yaml
374+
agents:
375+
priority: [ollama, claude]
376+
ollama:
377+
model: qwen3-coder
378+
# base_url: http://localhost:4000 # default (LiteLLM proxy)
379+
```
380+
381+
### Option C: llama.cpp server (headless)
382+
383+
For servers without a GUI:
384+
385+
```bash
386+
llama-server -m qwen3-coder-30b.gguf --port 8080 --ctx-size 131072
387+
```
388+
389+
Use the LM Studio adapter with a custom base_url:
390+
```yaml
391+
agents:
392+
lmstudio:
393+
model: qwen3-coder
394+
base_url: http://localhost:8080
395+
```
396+
397+
### Known issues
398+
399+
- **Malformed tool calls**: Local models emit invalid tool-use JSON more often than cloud Claude. Claude Code may crash with `Cannot read properties of undefined`. Workaround: `export CLAUDE_CODE_USE_POWERSHELL_TOOL=0`
400+
- **No prompt caching**: Every turn processes the full context from scratch. Sessions feel slower as context grows.
401+
- **No extended thinking**: The effort slider and thinking modes are Claude-specific features.
402+
- **Background tasks use local model**: Claude Code routes statusline updates and codebase searches through the "haiku" model tier. With tier-pinning (which studyctl sets automatically), all of these hit your local GPU.
403+
404+
### Verifying your setup
405+
406+
```bash
407+
studyctl doctor
408+
```
409+
410+
The doctor checks will report:
411+
- Whether ollama/lms binaries are installed
412+
- Whether the local server is responding
413+
- Whether Claude Code is installed (required as the frontend)
414+
279415
## Agent Descriptions
280416

281417
### study-mentor (kiro-cli)

‎docs/cli-reference.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ studyctl study "topic" --timer pomodoro # Override default timer
6565
studyctl study "topic" --agent claude --web # Explicit agent + web dashboard
6666
studyctl study "topic" --lan # Bind to 0.0.0.0, password-protected (implies --web)
6767
studyctl study "topic" --lan --password SECRET # Explicit password for LAN auth
68+
studyctl study "topic" --agent ollama # Local LLM via Ollama + LiteLLM
69+
studyctl study "topic" --agent lmstudio # Local LLM via LM Studio
6870
studyctl study --resume # Resume conversation (-r)
6971
studyctl study --end # End session cleanly
7072
studyctl park "How does asyncio compare?" # Park mid-session

‎docs/roadmap.md‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,13 @@ Study from any device (iPad, laptop, phone) via ttyd + web dashboard, with optio
294294

295295
### Local LLMs via Ollama / LM Studio
296296

297-
- [ ] `studyctl study Python --agent ollama` — new AgentAdapter entries
298-
- [ ] Run through Claude Code with `ANTHROPIC_BASE_URL` pointed at local model
299-
- [ ] Doctor checks: binary detection, model availability, context window minimum
300-
- [ ] Config support in `config.yaml` agents section
297+
- [x] `studyctl study Python --agent ollama` / `--agent lmstudio` — AgentAdapter entries with tier-pinning
298+
- [x] Claude Code frontend with `ANTHROPIC_BASE_URL` pointed at local backend
299+
- [x] LM Studio: native Anthropic API support (simplest path)
300+
- [x] Ollama: via LiteLLM proxy (Ollama lacks Anthropic API)
301+
- [x] Doctor checks: binary detection, server reachability, claude dependency
302+
- [x] Config support: `agents.ollama.model`, `agents.lmstudio.model` in config.yaml
303+
- [x] Documentation with model recommendations and quality expectations
301304

302305
### Multi-Agent Cleanup
303306

0 commit comments

Comments
 (0)