結論:[project.scripts]を書くだけでは、自作CLIは実行できません。コマンドは、現在のプロジェクト本体がuvのプロジェクト環境へインストールされたときに生成されます。依存は入るのに自作コマンドだけ見つからない場合は、[build-system]、tool.uv.package、実行オプション、利用中の環境を順に確認します。

1. 対象プロジェクトとPythonを確認する
pyproject.tomlがあるディレクトリで確認します。WindowsでもuvのコマンドはPowerShellで利用できます。
uv --versionmacOS/LinuxのBash等では次を確認します。
pwdWindowsのPowerShellでは、次の2つで作業場所と設定ファイルを確認します。
Get-LocationGet-Item .\pyproject.tomluv run python -c "import sys; print(sys.executable)"sys.executableが、通常は対象プロジェクトの.venv、環境パスを変更している場合はその指定先を指すか確認します。uvのプロジェクト操作は、別のVIRTUAL_ENVを既定では採用しません。有効化中の環境を意図的に使う場合だけ--activeを指定します。詳しくはuv公式のEnvironment説明を参照してください。
uv run --active brief-hello別環境へ入れたため見つからない問題と、現在のプロジェクト本体が未インストールの問題は分けて調べます。
2. project.scriptsと抑止設定を確認する
[project.scripts]の左辺はコマンド名、右辺はimport可能なmodule:functionです。配布名がbrief-cli-demoでも、import名はbrief_cliのように異なる場合があります。形式はPyPAの実行可能スクリプト解説でも確認できます。
次は、本体をインストールしない代表的な設定例です。
[project.scripts]
brief-hello = "brief_cli:main"
[tool.uv]
package = false[build-system]が定義されているかpackage = falseがないか--no-install-project、--no-install-workspace、--no-install-localを付けていないか--no-syncで古い環境を使っていないか
uvはbuild systemがない現在のプロジェクトをインストールせず、依存だけを入れます。package = falseはbuild systemがあっても本体インストールを抑止します。CLI名だけを変えても直りません。根拠はuv公式のBuild systemsに示されています。
3. build systemを定義する
既存プロジェクトにHatchling、Flit、PDM、setuptoolsなどの方針があるなら、そのbackendを尊重してください。下記は新規の最小検証用で、既存設定へそのまま上書きする例ではありません。
.
├── pyproject.toml
└── src
└── brief_cli
└── __init__.py[build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"
[project]
name = "brief-cli-demo"
version = "0.1.0"
requires-python = ">=3.9"
[project.scripts]
brief-hello = "brief_cli:main"def main():
print("brief-cli OK")tool.uv.package = trueでも本体インストールを強制できます。ただしbuild system未定義時はsetuptoolsのlegacy backendが使われます。明示backendがある既存プロジェクトでは、その設定を優先します。
2026年10月5日時点のuv公式のCreating projectsでは、現在のuv initは既定でuv build backendとsrc構成を持つpackaged projectを作ります。v0.12より前はアプリにbuild systemを既定設定しなかったため、古い解説ではuvの版と生成された設定を確認してください。
4. 同期して再確認する
uv syncuv run brief-hello設定と環境が正しければ、期待する出力はbrief-cli OKです。uv runは通常、実行前にプロジェクトをロック・同期します。同期動作はuv公式のLocking and syncingで確認できます。
コマンドは見つかるのにModuleNotFoundErrorになるなら、entry pointは生成されたものの、右辺のモジュールをimportできていません。src/brief_cli/__init__.pyが配布物に含まれるか、brief_cli:mainの綴り、関数の存在、backendのパッケージ検出設定を確認します。
uv run python -c "import brief_cli; print(brief_cli.__file__)"5. 実行方法の違い
| 対象 | 意味 |
|---|---|
| 依存のコマンド | 依存パッケージが提供するCLI。依存が入っていればuv runで起動できます。 |
自作project.scripts | 現在のプロジェクト本体をインストールして生成するCLIです。 |
uv tool run / uvx | ツールを一時的な分離環境で実行します。自作プロジェクトの環境とは別です。詳細はUsing toolsにあります。 |
| 単一スクリプト | Pythonファイルを直接実行する方法で、console script登録とは別です。 |
単一スクリプトを実行する場合の例です(file.pyが存在する場所で実行)。
uv run file.pyPYTHONPATHやグローバルインストールは、設定ミスを隠すことがあります。恒久対策は、build system、src配置、entry point、uvが使う環境を一致させることです。
FAQ
依存は入るのに自作コマンドだけないのはなぜですか?
本体が未インストールの可能性があります。build system未定義、package = false、--no-install-projectを確認します。
package = trueを追加すれば十分ですか?
本体インストールは強制できますが、build systemがなければlegacy backendになります。既存backendがあるなら明示設定を保ちます。
コマンドはあるのにModuleNotFoundErrorになります
右辺のimport名とsrc配置、同梱対象が一致しているか確認してください。配布名ではなくPythonからimportできる名前を使います。
uv tool runで自作CLIを試せますか?
通常は使いません。プロジェクト本体を同期し、uv runによるプロジェクト環境内のCLI実行で確認します。
検証範囲と公式資料
最小例はPython 3.12とsetuptoolsでオフラインwheelを作り、console_scriptsとsrcモジュールの同梱を確認済みです。この検証ではuv自体(uv sync・uv run)は実行していません。コマンド例は公式仕様に基づきます。

コメント