skills/python-notebooks-async/SKILL.md
Use when writing or reviewing asyncio code in Jupyter notebooks or '#%%' cell workflows — structuring event-loop ownership, orchestrating async tasks, or choosing compatibility strategies. Also use when hitting RuntimeError: This event loop is already running, asyncio.run() failures in cells, or tasks silently never completing.
npx skillsauth add ahgraber/skills python-notebooks-asyncInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Notebook kernels own the event loop; async code must cooperate with that ownership rather than fight it.
This skill covers orchestration patterns, top-level await, and compatibility constraints for .ipynb and #%% workflows.
Treat these recommendations as preferred defaults. When project constraints require deviation, call out tradeoffs and compensating controls.
asyncio.run() raises RuntimeError inside a notebook cell.gather, TaskGroup) in IPython kernels.python-concurrency-performance.python-runtime-operations.await instead of asyncio.run() in notebook cells.asyncio.gather() or asyncio.TaskGroup..py modules, imported into notebooks.nest_asyncio only as a constrained compatibility fallback, not a default.await or collect results explicitly.asyncio.run() in a notebook cell.
The kernel already runs a loop; asyncio.run() tries to start a second one and raises RuntimeError.
Use await directly instead.nest_asyncio globally by default.
It patches the loop to allow reentrant calls but masks design problems and can hide subtle concurrency bugs.
Reserve it for legacy compatibility..py files.await silently produces a never-executed coroutine object, with no error until results are missing downstream.requests.get() block the event loop, starving concurrent tasks.
Use aiohttp, httpx, or asyncio.to_thread().python-design-modularity.references/notebooks-async.mddevelopment
Use when writing or reviewing tests for Python behavior, contracts, async lifecycles, or reliability paths. Also use when tests are flaky, coupled to implementation details, missing regression coverage, slow to run, or when unclear what tests a change needs. Use for multi-Python version testing (nox) and free-threaded Python thread-safety validation.
development
Use when the user wants rigorous, non-sycophantic editorial feedback on a draft, essay, blog post, or argument through back-and-forth dialogue — pressure-testing thesis, structure, argument, clarity, tone, and evidence. Triggers: "be my sparring partner", "pressure-test this draft", "poke holes in my argument", "is this ready to publish", "sharpen this post", "where is this weak". Not for one-shot copyediting, proofreading, or ghostwriting.
testing
Use when distilling the through-line gist of one or more sources — the spine, argument, tension, or recurring frame running through a set of documents, notes, research, or transcripts, OR across the ideas within a single rich piece — into a few concise paragraphs. Triggers: "synthesize", "what's the through-line/gist", "extract the insight", "pull these together". Not for faithful summary or condensation that covers what a source says, nor for comparisons or catalogs where enumeration is the deliverable.
development
Use when writing or reviewing tests in any language, or diagnosing a suite that is slow, brittle, or hard to read. Triggers: "write tests", "how should I test this", "what kind of test", "test is flaky/fragile", "should I mock this", "test is hard to read". For Python-specific guidance see `python-testing`.