CLI utility that summarizes single files into teaching briefs using DSPy
Project description
dspyteach – DSPy File Teaching Analyzer
What it does
dspyteach is a Python CLI that analyzes one file or many files and generates either:
- a teaching brief (
--mode teach, default), or - a refactor prompt template (
--mode refactor)
It supports:
- single files and recursive directory scans
- repeated include globs (
-g/--glob) - directory exclusions (
-ed/--exclude-dirs) - local providers such as Ollama and LM Studio
- OpenAI-compatible hosted endpoints
- mirrored output directory layouts when
--output-diris set
The package centers on:
dspy_file/analyze_file_cli.py– CLI entrypoint and provider setupdspy_file/file_analyzer.py– teaching pipelinedspy_file/refactor_analyzer.py– refactor template pipelinedspy_file/file_helpers.py– file discovery, ignore rules, renderingdspy_file/prompts/– bundled refactor prompt templates
Requirements
- Python
>=3.10,<3.12(frompyproject.toml) - a supported model backend:
- Ollama
- LM Studio
- OpenAI-compatible API
uvrecommended for local development
Install
Local development
uv venv -p 3.11
source .venv/bin/activate
uv sync
From PyPI
pip install dspyteach
Smoke check:
dspyteach --help
Provider setup
Ollama
Default provider is Ollama.
dspyteach path/to/file.md
The current default Ollama base URL is:
http://localhost:11434
LM Studio
LM Studio uses the OpenAI-compatible server at:
http://localhost:1234/v1
Example:
dspyteach path/to/project \
--provider lmstudio \
--model qwen_qwen3-4b-instruct-2507 \
--api-base http://localhost:1234/v1
More details:
Hosted OpenAI-compatible provider
dspyteach path/to/project \
--provider openai \
--model gpt-5 \
--api-base https://your-endpoint.example/v1 \
--api-key YOUR_KEY
Environment variables
The CLI loads .env automatically via python-dotenv.
Common settings:
DSPYTEACH_PROVIDER=ollama
DSPYTEACH_MODEL=hf.co/Mungert/osmosis-mcp-4b-GGUF:Q5_K_M
#DSPYTEACH_API_BASE=http://localhost:1234/v1
#DSPYTEACH_API_KEY=lm-studio
#OPENAI_API_KEY=
#DSPYTEACH_LOG_PATH=.dspyteach/logs/custom.log
#DSPYTEACH_MAX_TOKENS=4000
Notes:
DSPYTEACH_API_KEYfalls back toOPENAI_API_KEYwhenDSPYTEACH_PROVIDER=openaiDSPYTEACH_LOG_PATHcontrols the runtime log file destinationDSPYTEACH_MAX_TOKENScontrols the root LM token budget used during DSPy configuration
See:
Usage
Analyze a single file
dspyteach docs/example.md
Analyze a directory recursively
dspyteach ./repo -g '**/*.py' -g '**/*.md'
Write outputs to a separate mirrored tree
dspyteach ./repo \
-g '**/*.md' \
-o ./out
When --output-dir is set, the CLI mirrors the original relative directory layout inside the output directory and keeps the original filename.
Skip directories while scanning
dspyteach ./repo \
-g '**/*README*' \
-g '**/package.json' \
-g '**/pyproject.toml' \
-ed '.git,node_modules,.venv,dist,build' \
-o ./out
Confirm each file before analysis
dspyteach ./repo -g '**/*.md' --confirm-each
Print raw predictions
dspyteach docs/example.md --raw
Globs
Include globs are relative to the path you pass to dspyteach.
Good:
dspyteach ../../../ai-apps \
-g '**/README.md' \
-g '**/package.json' \
-g '**/pyproject.toml' \
-o ../../../ai-apps/.readMes/.out
Not recommended:
# full absolute paths inside --glob are not needed
-g '~/projects/temp/ai-apps/**/README.md'
Repeat -g once per pattern.
Modes
Teach mode
Default mode. Generates a teaching-oriented markdown brief.
dspyteach path/to/file.md --mode teach
Refactor mode
Generates a refactor-oriented prompt template.
dspyteach path/to/file.md --mode refactor
Refactor mode supports -p/--prompt:
dspyteach ./repo --mode refactor --prompt refactor_prompt_template
If multiple bundled templates are available and you do not pass --prompt, the CLI will prompt you to choose one.
Output behavior
Current behavior:
- if
--output-diris omitted, the CLI writes output underdspy_file/data/ - if
--output-diris provided, the CLI writes into that directory and mirrors the source tree - teaching mode appends
.teaching.md; refactor mode appends.refactor.md --in-placerequests source replacement, but real overwrites require per-file confirmation- if
--in-placeis combined with--output-dir, the CLI writes the original filename into that directory instead of overwriting the source
This keeps the original source files unchanged unless you explicitly approve each overwrite.
Example:
dspyteach ../../../ai-apps \
-m teach \
-g '**/*README*' \
-o ../../../ai-apps/.readMes/.out
Logging
Runtime logging is configured once at the CLI boundary.
Default log path pattern:
.dspyteach/logs/run-YYYYMMDD-HHMMSS-<pid>.log
Each CLI run now gets its own log file by default.
Override it with:
DSPYTEACH_LOG_PATH=/absolute/path/to/dspyteach.log
The logger uses a rotating file handler.
Run state, resume, and cleanup
Batch runs now persist resumable state under:
.dspyteach/runs/<run_id>/
A saved run includes:
manifest.jsonwith run-level settings and status- per-file checkpoint JSON files under
files/ - stage data for teaching-mode resume, so cancelled files can continue from the last completed stage
By default, a fresh run gets a generated run id. You can also name one explicitly:
dspyteach ./repo -g '**/*.py' --run-id docs-pass-1
Resume a saved run:
dspyteach ./repo -g '**/*.py' --resume docs-pass-1
Resume validation is intentionally strict. The CLI expects the resumed run to match the original path, mode, provider/model settings, and scan filters.
Inspect saved runs
List saved runs:
dspyteach --list-runs
Show one run and its per-file checkpoint stages:
dspyteach --show-run docs-pass-1
Machine-readable output is also available:
dspyteach --list-runs --json
dspyteach --show-run docs-pass-1 --json
Delete or prune saved runs
Delete a single saved run:
dspyteach --delete-run docs-pass-1
Preview which runs would be pruned without deleting them:
dspyteach --prune-runs --prune-status failed --dry-run
Delete completed runs older than 14 days:
dspyteach --prune-runs --prune-status completed --prune-older-than-days 14
Preview prune results as JSON:
dspyteach --prune-runs \
--prune-status failed,completed_with_errors \
--prune-older-than-days 7 \
--dry-run \
--json
Pruning requires at least one filter:
--prune-status--prune-older-than-days
This is intentional so pruning cannot accidentally behave like a delete-all command.
Local model cleanup
Unless --keep-provider-alive is set, the CLI attempts to free local resources after the run:
- Ollama – stops the active model
- LM Studio – unloads matching loaded instances
dspyteach ./repo --provider lmstudio --keep-provider-alive
Troubleshooting
- If Ollama cannot be reached, verify it is running on
http://localhost:11434 - If LM Studio cannot be reached, verify the local server is running on
http://localhost:1234/v1 - If you are scanning large trees, prefer
--output-dirplus--exclude-dirs - If one file fails during a batch, the CLI logs the exception and continues with the next file
- For debugging LM Studio integration, capture console output and inspect the runtime log file
Example verbose capture:
{ dspyteach ./repo -g '**/*.md'; } |& tee dspyteach.$(date +%Y%m%d-%H%M%S).log
Releasing
Maintainer release steps live in:
Tag workflow helper:
./scripts/tag-release.sh
Pushing a tag matching v* triggers:
.github/workflows/release.yml
Development notes
Targeted test runs used frequently in this repo:
uv run pytest -q
Focused examples:
uv run pytest -q tests/test_cli_connectivity.py
uv run pytest -q tests/test_file_helpers.py
uv run pytest -q tests/test_lmstudio_structured.py
Example data
Sample generated outputs live under:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dspyteach-0.1.7b46.tar.gz.
File metadata
- Download URL: dspyteach-0.1.7b46.tar.gz
- Upload date:
- Size: 40.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b648ad7495463b7550135dc1253fd74e635627247b401e6062dbaf92c8490961
|
|
| MD5 |
340eb5b424bee60a0820f0716ea2171b
|
|
| BLAKE2b-256 |
7a5a528a92e6c19ba7ce058b938f4f1573034b359469c35ea1f93cd139adecbf
|
File details
Details for the file dspyteach-0.1.7b46-py3-none-any.whl.
File metadata
- Download URL: dspyteach-0.1.7b46-py3-none-any.whl
- Upload date:
- Size: 36.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a1680457a73b97a21064c345d9a4097d06079b4afafd4093a1d9fe2bf88e54d
|
|
| MD5 |
97b601c265f46ea5805aaea4a6a9a69f
|
|
| BLAKE2b-256 |
5f73a57616386829a2d3d5f5f6085e006a1a1603c4f842533ac2866a0c5aa26d
|