A terminal IPython extension that adds Claude Agent SDK powered prompting
Editable install:
pip install -e ipyant
Run tests:
cd ipyant
./tools/test.sh
Capture fresh Claude SDK shape samples:
cd ipyant
./tools/capture_samples.sh
The wrappers intentionally keep setup small:
tools/test.sh sets XDG_CONFIG_HOME and CLAUDE_CONFIG_DIR to repo-local temp dirs, then runs pytesttools/capture_samples.sh regenerates the committed Claude SDK stream-shape artifacts under samples/outputs/python MCP tool, partial-stream normalization, synthetic session writingipyant console entry point. is rewritten into %ipyant.IPyAIExtension.run_prompt() reconstructs recent code/output/note context from IPython history.$nameand shell refs like `!`cmd are injected above the prompt.ClaudeBackend.stream_turn() opens a fresh ClaudeSDKClient, optionally resumes a prior Claude session ID, and streams partial events.astream_to_stdout() renders the response through Rich in TTY mode and stores the final transcript text locally.There are two layers of state:
ipyant uses:
claude_prompts for AI prompt historysessions.remark JSON for cwd, provider, and provider_session_idIf prompt history was restored from an explicit notebook load and provider_session_id is still missing, ipyant synthesizes a Claude transcript JSONL file once and resumes from that instead of replaying the full prompt history turn-by-turn.
Notebook save/load is explicit only:
%ipyant save <filename>%ipyant load <filename>There is no implicit startup.ipynb behavior.
The custom tool story is intentionally small:
pythonBash, Edit, Read, Skill, WebFetch, WebSearch, Writepython does not call back into InteractiveShell.run_cell*. It delegates to pyrun from safepyrun, looked up in shell.user_ns, matching the old ipycodex direct-call boundary and avoiding nested IPython cell execution.
The ipyant CLI loads safepyrun before ipyant, so normal terminal sessions get pyrun automatically.
Skills are Claude-native:
Skill tool is enabledsetting_sources=["user", "project"].claude/plugins up the cwd parent chainThe samples/ directory exists so stream-shape spelunking does not need to be repeated.
Artifacts currently committed:
samples/outputs/text_stream.jsonsamples/outputs/python_tool_stream.jsonThose captures are useful when working on:
StreamEvent shape changesSystemMessage.init payload changesThe test suite is intentionally small and integration-heavy.
Current coverage focuses on:
There is also one real Claude-side integration point in the tests: synthetic session files are verified through claude_agent_sdk.get_session_messages() rather than only through local mocks.
ipyant resolves config paths via XDG.XDG_CONFIG_HOME so config writes stay out of a normal user config tree.samples/.claude/ directory for Claude session artifacts.