Workspace¶
Directory layout¶
A pascal workspace is a standard UV workspace with a pascal.toml manifest at the root.
my-workspace/
pascal.toml # pascal reads this
pyproject.toml # UV workspace root — auto-managed by pascal
uv.lock # lockfile — commit this to git
packages/
cart/
pyproject.toml
src/
cart/
__init__.py
tests/
test_cart.py
auth/
pyproject.toml
src/
auth/
__init__.py
tests/
test_auth.py
apps/
storefront/
pyproject.toml # dependencies = ["cart", "auth"]
src/
storefront/
__init__.py
main.py
tests/
test_storefront.py
pascal.toml reference¶
[workspace]
name = "my-workspace" # required
python = "3.12" # required — minimum Python version
description = "My monorepo" # optional
# Optional explicit member lists.
# If omitted, pascal auto-discovers from packages/*/pyproject.toml
# and apps/*/pyproject.toml.
packages = ["packages/cart", "packages/auth"]
apps = ["apps/storefront"]
Auto-discovery¶
When packages and apps are not listed in pascal.toml, pascal scans:
<root>/packages/*/pyproject.toml→ registered as packages<root>/apps/*/pyproject.toml→ registered as apps
This means adding a new directory under packages/ or apps/ is enough — no manifest update required.
Workspace root detection¶
Pascal walks up from the current working directory until it finds pascal.toml, the same way cargo and git find their roots. You can run pascal commands from any subdirectory inside the workspace.
Generated files¶
Root pyproject.toml¶
Auto-generated by pascal init and kept in sync by pascal sync:
[project]
name = "my-workspace"
version = "0.1.0"
requires-python = ">=3.12"
[tool.uv.workspace]
members = ["packages/*", "apps/*"]
Do not edit manually
This file is managed by pascal. Run pascal sync after changing pascal.toml to regenerate it.
Package pyproject.toml¶
Generated by pascal create package:
[project]
name = "cart"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
App pyproject.toml¶
Generated by pascal create app. Includes a [project.scripts] entry:
[project]
name = "storefront"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[project.scripts]
storefront = "storefront.main:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
After pascal add cart --to storefront:
[project]
name = "storefront"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["cart"]
[project.scripts]
storefront = "storefront.main:main"
[tool.uv.sources]
cart = { workspace = true }
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Source layout¶
Pascal uses the src layout for all generated packages and apps:
This keeps tests outside the importable package tree and avoids import confusion during development.
Name normalisation¶
Pascal normalises brick names the same way Python packaging does:
- Hyphens and underscores are treated as equivalent
pascal create package my-pkgcreatespackages/my-pkg/withsrc/my_pkg/- The
[project]name inpyproject.tomluses hyphens (my-pkg) - The source directory uses underscores (
my_pkg)