ClaudeスキルでStarlette 1.0を試す
Simon Willisonは、FastAPIの基盤であるPython ASGIフレームワーク『Starlette』の1.0リリースについて、ライフサイクル管理の変更点と移行ガイドを解説している。
キーポイント
Starlette 1.0の公式リリースとFastAPIとの関係性
長らく非公開アルファ版が続いていたが、FastAPIの基盤技術として広く利用されてきたStarletteがついに1.0を公式リリースし、ブランド認知度と実使用量の乖離が解消された。
ライフサイクル管理のアーキテクチャ変更
従来のon_startup/on_shutdownパラメータに代わり、Python標準のasynccontextmanagerを用いたlifespan機構へ移行。これにより起動・終了処理の記述が標準化され、コードの可読性と保守性が向上した。
プロジェクト管理権の移管と安定性へのコミット
創設者Kim Christieから主要コントリビューターMarcelo TrylesinskiのGitHubアカウントへプロジェクトが移管され、長期的なメンテナンス体制とスポンサーシップ受領の基盤が整備された。
Python ASGIエコシステムにおける位置づけ
Django REST Frameworkの作者による設計思想を受け継ぎ、FlaskとDjangoの良いところを融合した非同期ネイティブフレームワークとして、現代Python Web開発の標準選択肢の一つに昇格した。
影響分析・編集コメントを表示
影響分析
Starlette 1.0のリリースは、FastAPIを筆頭とする現代Python Web開発エコシステムに直接的な影響を与える。ライフサイクル管理の標準化により、新規プロジェクトの設計指針が明確になり、既存システムからの移行コストも現実的な範囲に収まる。AIモデルのAPI提供やエージェント基盤構築において、堅牢なバックエンド基盤としての一層の普及が期待される。
編集コメント
技術ブログ特有の深い実装解説であり、FastAPI利用者は移行ガイドを必ず確認すべき内容である。タイトルにある「Claude skills」との関連は本文切れだが、AIエージェントのバックエンド基盤としてStarlette 1.0が活用される可能性は高い。
Starlette 1.0 がリリースされました!これは本当に大きな出来事です。私は、Starlette は比較的低いブランド認知度に対して使用実績が最も多い Python フレームワークの一つではないかと考えています。その理由は、Starlette が FastAPI の基盤となっているためで、FastAPI は多大な注目を集め、かえって Starlette 自体の存在が影を薄めてしまったように見えるからです。
Kim Christie は 2018 年に Starlette の開発を開始し、すぐに新しい世代の Python ASGI フレームワークの中で私の最愛のものとなりました。私が自身の Datasette プロジェクトの基盤としてこれを使わなかった唯一の理由は、まだ安定性を約束していなかったからです。私は Datasette 独自のプラグインに対して安定した API を提供することに固執していました……とはいえ、私自身もまだ勇気が出ず、26 回ものアルファ版を経て現在に至るまで、1.0 リリースを公開できていません!
その後、2025 年 9 月に Marcelo Trylesinski が Starlette と Uvicorn を自身の GitHub アカウントへ移管することを発表しました。これは彼らの長年にわたる貢献を認めるとともに、これらのプロジェクトに対するスポンサーシップを受け取りやすくするためでした。
1.0 バージョンは 0.x シリーズと比較していくつかの破壊的変更を含んでおり、これらは 2 月に発表された 1.0.0rc1 のリリースノート で説明されています。
最も目立つ変更点は、起動時とシャットダウン時にコードが実行される方法の変更です。以前は on_startup および on_shutdown パラメータで処理されていましたが、新しいシステムでは lifespan メカニズムを採用し、これは async context manager を中心に構成されています:
@contextlib.asynccontextmanager
async def lifespan(app):
async with some_async_resource():
print("Run at startup!")
yield
print("Run on shutdown!")
app = Starlette(
routes=routes,
lifespan=lifespan
)
もしあなたが以前に Starlette を試したことがないなら、私には asyncio ネイティブの Flask と Django の中間のようなものと感じられます。これは驚くべきことではありません。なぜなら、創設者の Kim Christie は Django REST Framework の作成者でもあるからです。決定的な点は、これにより Flask スタイルで単一の Python ファイルとしてほとんどのアプリケーションを記述できるということです。
これにより、LLM が単一のプロンプトから動作する Starlette アプリケーションを生成するのは*非常に*簡単になります。
しかし、そこにはただ一つの問題があります。1.0 版がモデルが学習してきた既存の Starlette コードとの互換性を破る場合、どのようにして 1.0 版で動作するコードをそれらに生成させることができるでしょうか?
私はこれを Skill を使って実現できるかどうか試してみることにしました。
Claude でスキルを構築する
claude.ai 上の通常の Claude チャットには「スキル」機能が備わっており、そのデフォルトスキルの一つに skill-creator スキル が含まれています。つまり、Claude は自分自身でスキルを構築する方法を知っているのです。
そこで私は チャットセッションを開始し、以下のように指示しました:
GitHub から Starlette をクローンしてください。ちょうど 1.0 リリースが行われたばかりです。このリリースのすべての機能に関するコード例を含む、スキル用 Markdown ドキュメントを構築してください。
リポジトリの場所まで具体的に指示しませんでした。Starlette は十分に知られたプロジェクトなので、自力で見つけられるだろうと予想したからです。
Claude が実行したのは git clone https://github.com/encode/starlette.git というコマンドでした。これは実は古いリポジトリ名ですが、GitHub 側で自動的にリダイレクト処理が行われるため、問題なく動作しました。
作成されたスキルドキュメント は私には非常に網羅的に見えました。そして、以前見たことのない「Copy to your skills」というラベルの新しいボタンが上部にあることに気づきました。そこで私はそのボタンをクリックしました:

すると、通常の Claude チャットでもそのスキルにアクセスできるようになりました!
作業管理デモアプリの構築
私は 新しい会話を開始し、以下のようにプロンプトしました:
Starlette を使用して作業管理アプリを構築してください。プロジェクト、タスク、コメント、ラベルの機能を持つものにしてください。
Claude はまさにその通りに行い、Starlette 1.0 を用いたシンプルな GitHub Issues クローンを作成しました。これには SQLite データベース(aiosqlite を経由)と Jinja2 テンプレートが使用されています。
Claude はさらに、以下のように手動でアプリをテストしました:
cd /home/claude/taskflow && timeout 5 python -c "
import asyncio
from database import init_db
asyncio.run(init_db())
print('DB initialized successfully')
" 2>&1
pip install httpx --break-system-packages -q \
&& cd /home/claude/taskflow && \
python -c "
from starlette.testclient import TestClient
from main import app
client = TestClient(app)
r = client.get('/api/stats')
print('Stats:', r.json())
r = client.get('/api/projects')
print('Projects:', len(r.json()), 'found')
r = client.get('/api/tasks')
print('Tasks:', len(r.json()), 'found')
r = client.get('/api/labels')
print('Labels:', len(r.json()), 'found')
r = client.get('/api/tasks/1')
t = r.json()
print(f'Task 1: "{t["title"]}" - {len(t["comments"])} comments, {len(t["labels"])} labels')
r = client.post('/api/tasks', json={'title':'Test task','project_id':1,'priority':'high','label_ids':[1,2]})
print('Created task:', r.status_code, r.json()['title'])
r = client.post('/api/comments', json={'task_id':1,'content':'Test comment'})
print('Created comment:', r.status_code)
r = client.get('/')
print('Homepage:', r.status_code, '- length:', len(r.text))
print('\nAll tests passed!')
"
Claude Code に関する話題が盛り上がる中、Claude 自体もすでにコーディングエージェントとしてカウントされるようになり、自身が書くコードの作成からテストまでを完全に実行できるようになっているという事実を見落としがちです。
その結果できたアプリの外観は以下の通りです。コードはこちらの研究リポジトリにあります taskflow。

Tags: open-source, python, ai, asgi, kim-christie, generative-ai, llms, ai-assisted-programming, claude, coding-agents, skills, agentic-engineering, starlette
原文を表示
Starlette 1.0 is out! This is a really big deal. I think Starlette may be the Python framework with the most usage compared to its relatively low brand recognition because Starlette is the foundation of FastAPI, which has attracted a huge amount of buzz that seems to have overshadowed Starlette itself.
Kim Christie started working on Starlette in 2018 and it quickly became my favorite out of the new breed of Python ASGI frameworks. The only reason I didn't use it as the basis for my own Datasette project was that it didn't yet promise stability, and I was determined to provide a stable API for Datasette's own plugins... albeit I still haven't been brave enough to ship my own 1.0 release (after 26 alphas and counting)!
Then in September 2025 Marcelo Trylesinski announced that Starlette and Uvicorn were transferring to their GitHub account, in recognition of their many years of contributions and to make it easier for them to receive sponsorship against those projects.
The 1.0 version has a few breaking changes compared to the 0.x series, described in the release notes for 1.0.0rc1 that came out in February.
The most notable of these is a change to how code runs on startup and shutdown. Previously that was handled by on_startup and on_shutdown parameters, but the new system uses a neat lifespan mechanism instead based around an async context manager:
@contextlib.asynccontextmanager
async def lifespan(app):
async with some_async_resource():
print("Run at startup!")
yield
print("Run on shutdown!")
app = Starlette(
routes=routes,
lifespan=lifespan
)If you haven't tried Starlette before it feels to me like an asyncio-native cross between Flask and Django, unsurprising since creator Kim Christie is also responsible for Django REST Framework. Crucially, this means you can write most apps as a single Python file, Flask style.
This makes it *really* easy for LLMs to spit out a working Starlette app from a single prompt.
There's just one problem there: if 1.0 breaks compatibility with the Starlette code that the models have been trained on, how can we have them generate code that works with 1.0?
I decided to see if I could get this working with a Skill.
Building a Skill with Claude
Regular Claude Chat on claude.ai has skills, and one of those default skills is the skill-creator skill. This means Claude knows how to build its own skills.
So I started a chat session and told it:
Clone Starlette from GitHub - it just had its 1.0 release. Build a skill markdown document for this release which includes code examples of every feature.
I didn't even tell it where to find the repo, Starlette is widely enough known that I expected it could find it on its own.
It ran git clone https://github.com/encode/starlette.git which is actually the old repository name, but GitHub handles redirects automatically so this worked just fine.
The resulting skill document looked very thorough to me... and then I noticed a new button at the top I hadn't seen before labelled "Copy to your skills". So I clicked it:

And now my regular Claude chat has access to that skill!
A task management demo app
I started a new conversation and prompted:
Build a task management app with Starlette, it should have projects and tasks and comments and labels
And Claude did exactly that, producing a simple GitHub Issues clone using Starlette 1.0, a SQLite database (via aiosqlite) and a Jinja2 template.
Claude even tested the app manually like this:
cd /home/claude/taskflow && timeout 5 python -c "
import asyncio
from database import init_db
asyncio.run(init_db())
print('DB initialized successfully')
" 2>&1
pip install httpx --break-system-packages -q \
&& cd /home/claude/taskflow && \
python -c "
from starlette.testclient import TestClient
from main import app
client = TestClient(app)
r = client.get('/api/stats')
print('Stats:', r.json())
r = client.get('/api/projects')
print('Projects:', len(r.json()), 'found')
r = client.get('/api/tasks')
print('Tasks:', len(r.json()), 'found')
r = client.get('/api/labels')
print('Labels:', len(r.json()), 'found')
r = client.get('/api/tasks/1')
t = r.json()
print(f'Task 1: \"{t[\"title\"]}\" - {len(t[\"comments\"])} comments, {len(t[\"labels\"])} labels')
r = client.post('/api/tasks', json={'title':'Test task','project_id':1,'priority':'high','label_ids':[1,2]})
print('Created task:', r.status_code, r.json()['title'])
r = client.post('/api/comments', json={'task_id':1,'content':'Test comment'})
print('Created comment:', r.status_code)
r = client.get('/')
print('Homepage:', r.status_code, '- length:', len(r.text))
print('\nAll tests passed!')
"For all of the buzz about Claude Code, it's easy to overlook that Claude itself counts as a coding agent now, fully able to both write and then test the code that it is writing.
Here's what the resulting app looked like. The code is here in my research repository.

Tags: open-source, python, ai, asgi, kim-christie, generative-ai, llms, ai-assisted-programming, claude, coding-agents, skills, agentic-engineering, starlette
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み