Skip to content
33 changes: 33 additions & 0 deletions .agents/skills/polylith/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Polylith Skills

> **Note for contributors:** this README is a **human reference**. The agent loads each `*/SKILL.md` independently via the skill loader; this file is **not** auto-loaded with any skill. Anything an agent must know to act has to live in the relevant `SKILL.md` itself, not here.

## Available Skills

| Skill | Command | Purpose |
|---------------------------|--------------------|----------------------------------------------------------------------------------------------------------|
| [Workspace Setup](./workspace_setup/SKILL.md) | `poly create workspace` | Initialize a Polylith workspace (`workspace.toml`, top-level dirs). |
| [Component Creation](./component_creation/SKILL.md) | `poly create component` | Create a reusable brick (business logic, domain, capability). |
| [Base Creation](./base_creation/SKILL.md) | `poly create base` | Create an entry-point brick (HTTP API, CLI, Lambda handler). |
| [Project Management](./project_management/SKILL.md) | `poly create project` | Create a deployable project that references bricks. |
| [Sync](./sync/SKILL.md) | `poly sync` | Update each project's brick list to match actual imports. |
| [Workspace Inspection](./workspace_inspection/SKILL.md) | `poly info` | Show brick × project usage (which projects use which bricks). |
| [Dependency Visualization](./dependency_visualization/SKILL.md) | `poly deps` | Show brick × brick dependencies and interface compliance. |
| [Testing](./testing/SKILL.md) | `poly test diff` | List bricks/projects affected by **test-code** changes since a tag. |
| [Diff](./diff/SKILL.md) | `poly diff` | List bricks whose **implementation** changed since a tag. |
| [Check](./check/SKILL.md) | `poly check` | Validate the workspace (CI gate; exits 1 on failure). |
| [Libs](./libs/SKILL.md) | `poly libs` | Inspect third-party libraries per project. |
| [Concepts](./concepts/SKILL.md) | — | Provides foundational knowledge about Polylith architecture and terminology. |

---

## For humans — getting started

1. **Set up the workspace** — [Workspace Setup](./workspace_setup/SKILL.md).
2. **Understand the basics** — [Concepts](./concepts/SKILL.md).
3. **Create bricks** — [Component Creation](./component_creation/SKILL.md) and [Base Creation](./base_creation/SKILL.md).
4. **Create deployable projects** — [Project Management](./project_management/SKILL.md).
5. **Sync brick usage** — [Sync](./sync/SKILL.md).
6. **Inspect** — [Workspace Inspection](./workspace_inspection/SKILL.md) (brick × project) and [Dependency Visualization](./dependency_visualization/SKILL.md) (brick × brick).
7. **Validate** — [Check](./check/SKILL.md) (CI gate) and [Libs](./libs/SKILL.md) (library inspection).
8. **Diff between releases** — [Diff](./diff/SKILL.md) and [Testing](./testing/SKILL.md).
54 changes: 54 additions & 0 deletions .agents/skills/polylith/base_creation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
name: polylith-base-creation
description: Create a Polylith base with `poly create base` — the entry point of a deployable application (HTTP API, CLI, message-queue consumer, AWS Lambda handler, GCP Cloud Function, scheduled job). Use when the user wants to add a service, API, endpoint, handler, or any new entry point to a Polylith workspace.
---

# Base Creation Skill

## Quick command

```bash
uv run poly create base --name api
```

**Command prefix:** If you do not know the package manager, run `ls uv.lock poetry.lock pdm.lock pyproject.toml 2>/dev/null` to find out. Use `uv run poly` (uv), `poetry poly` (poetry), `pdm run poly` (pdm), `hatch run poly` (hatch), or `poly` (venv). Examples below use `uv run`.

> A **base** is the entry point of a deployable application. For non-entry-point reusable code (business logic, capabilities), use `polylith-component-creation` instead.

## Command reference

| Option | Required | Default | Description |
|-----------------|----------|---------|--------------------------------------------|
| `--name` | yes | — | Name of the base (also the package name). |
| `--description` | no | `""` | Optional human-readable description. |

## What gets created (loose theme)

```
bases/<namespace>/api/
├── __init__.py # Public interface — empty; add re-exports here
└── core.py # Implementation — empty; user fills it in
```

If `[tool.polylith.test].enabled = true` in `workspace.toml`, the CLI also creates `test/bases/<namespace>/api/test_core.py`.

For the `tdd` theme layout (`bases/api/{src,test}/<namespace>/api/...`), load `polylith-workspace-setup` via `eca__skill`.

## Examples

```bash
# Minimal
uv run poly create base --name api

# With description
uv run poly create base --name consumer --description "Kafka order consumer"
```

## Notes for the agent
- `core.py` is **empty boilerplate** — there is no FastAPI/Typer/Lambda scaffolding. Fill it in manually after creation if asked.
- `__init__.py` is also empty. By Polylith convention it should re-export the brick's public symbols, so consumers import `from <namespace>.api import …` rather than reaching into `core.py`.
- A new base is **not** wired into any project. To wire it: load `polylith-sync` and run `poly sync`, or run `poly create project` (the interactive prompt will offer to attach the base).
- The same command works for both `loose` and `tdd` themes — the CLI reads `[tool.polylith.structure].theme` from `workspace.toml`.

## Verification
After creation, verify the base exists using your file tools (e.g., check `bases/<namespace>/<name>/__init__.py`). Then, you will likely need to populate `core.py` and `__init__.py` using your file writing tools since they are created empty.
25 changes: 25 additions & 0 deletions .agents/skills/polylith/brick_removal/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: polylith-brick-removal
description: Safely remove a Polylith brick (component or base) from the workspace. Use when the user wants to delete, remove, or tear down a component or base.
---

# Brick Removal Skill

There is no `poly remove` CLI command. Removing a brick is a manual process.

## Steps to remove a brick

1. **Delete the source code:**
Delete the brick's directory under `components/<namespace>/<name>` or `bases/<namespace>/<name>`.
2. **Delete the tests:**
Delete the brick's test directory under `test/components/<namespace>/<name>` or `test/bases/<namespace>/<name>`.
3. **Remove from projects:**
Search across all `projects/*/pyproject.toml` files and remove the brick from the `[tool.polylith.bricks]` section.
4. **Remove from the development project:**
Remove the brick from the `[tool.polylith.bricks]` section in the root `pyproject.toml` (the development project).
5. **Sync and Check:**
Run `poly sync` (load `polylith-sync`) and `poly check` (load `polylith-check`) to ensure the workspace is valid and no other bricks were importing the deleted brick.

## Notes for the agent
- Always use your directory and file tools to verify the paths before deleting.
- If `poly check` fails after removal, it means another brick was depending on the removed brick. You must fix the importing brick.
54 changes: 54 additions & 0 deletions .agents/skills/polylith/check/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
name: polylith-check
description: Validate a Polylith workspace with `poly check` — the canonical CI gate. Verifies brick imports against project `pyproject.toml`s, third-party library declarations vs. the lock file, and (under `--strict`) cross-project version consistency. Exits 1 on failure. Use when the user wants to lint, validate, verify, or CI-gate a Polylith workspace.
---

# Check Skill

## Quick command

```bash
uv run poly check --strict
```

**Command prefix:** If you do not know the package manager, run `ls uv.lock poetry.lock pdm.lock pyproject.toml 2>/dev/null` to find out. Use `uv run poly` (uv), `poetry poly` (poetry), `pdm run poly` (pdm), `hatch run poly` (hatch), or `poly` (venv). Examples below use `uv run`.

> ⚠ **Run `poly sync` first** if bricks have been added/removed since the last commit, otherwise sync-related findings will dominate the report. Load `polylith-sync` if needed.
> ⚠ **Exit code 1 = failure** — this is the right command to wrap in CI.

## Typical CI usage

```bash
uv run poly sync # Make sure brick lists are current
uv run poly check # Validate; build fails if non-zero
uv run poly test diff --bricks # (Optional) scope test runs
```

## What it verifies
- Every brick imported by another brick is listed in the consuming project's `[tool.polylith.bricks]`.
- Every third-party library imported by a project's bricks is declared in that project's `dependencies` and present in the lock file.

## Command reference

| Option | Default | Description |
|----------------|---------|---------------------------------------------------------------------------------------------------------|
| `--strict` | `false` | Stricter name/version matching across projects (catches version drift). |
| `--verbose` | `false` | Print extra context, including lock-file lookups. |
| `--quiet` | `false` | Suppress output. Exit code unchanged. |
| `--alias` | — | Comma-separated `import_name=package_name` aliases. |
| `--directory` | cwd | Limit the check to projects whose path matches this directory. |

## Examples

```bash
# Standard CI gate
uv run poly check

# One project only
uv run poly check --directory projects/user_api
```

## Common failure modes & Auto-Fixes
1. **Missing Brick Error:** If the error says a brick imports another brick that isn't in `[tool.polylith.bricks]` → run `poly sync` (load `polylith-sync`).
2. **Missing Dependency Error:** If the error says a brick imports a third-party library not listed in the project's `dependencies` → load `polylith-dependency-management` and add the library to the project's `pyproject.toml`.
3. **Version Drift Error:** Under `--strict`, if versions of the same library diverge between projects → inspect `pyproject.toml` or load `polylith-libs` to find the drift, then align versions (or rely on a single root lock file).
57 changes: 57 additions & 0 deletions .agents/skills/polylith/component_creation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
name: polylith-component-creation
description: Create a Polylith component with `poly create component` — a reusable, isolated brick implementing business logic, a feature, a domain module, or a capability. Use when adding non-entry-point code that bases or other components will import.
---

# Component Creation Skill

## Quick command

```bash
uv run poly create component --name user_service
```

**Command prefix:** If you do not know the package manager, run `ls uv.lock poetry.lock pdm.lock pyproject.toml 2>/dev/null` to find out. Use `uv run poly` (uv), `poetry poly` (poetry), `pdm run poly` (pdm), `hatch run poly` (hatch), or `poly` (venv). Examples below use `uv run`.

> A **component** is reusable, non-entry-point code (business logic, domain features, capabilities). For entry points (HTTP API, CLI, Lambda handler), use `polylith-base-creation` instead.

## Command reference

| Option | Required | Default | Description |
|-----------------|----------|---------|---------------------------------------------------|
| `--name` | yes | — | Name of the component (also the package name). |
| `--description` | no | `""` | Optional human-readable description. |

## What gets created (loose theme)

```
components/<namespace>/user_service/
├── __init__.py # Public interface — empty; add re-exports here
└── core.py # Implementation — empty; user fills it in
```

If `[tool.polylith.test].enabled = true` in `workspace.toml`, the CLI also creates `test/components/<namespace>/user_service/test_core.py`.

For the `tdd` theme layout (`components/user_service/{src,test}/<namespace>/user_service/...`), load `polylith-workspace-setup`.

## Examples

```bash
# Minimal
uv run poly create component --name user_service

# With description
uv run poly create component --name greeting --description "Greeting domain"
```

## Notes for the agent
- Both `core.py` and `__init__.py` are **empty boilerplate**. The component is not "ready" — the user fills in `core.py`, then re-exports its public API from `__init__.py`:
```python
# components/<namespace>/user_service/__init__.py
from <namespace>.user_service.core import create_user, get_user
```
- Consumers import via the public interface (`from <namespace>.user_service import create_user`), never via `core.py` directly. `poly deps --interface` (load `polylith-dependency-visualization`) flags violations.
- A new component is **not** automatically used by any project. It is registered in a project once a base (or another component already in the project) imports it — then run `poly sync` (load `polylith-sync`).

## Verification
After creation, verify the component exists using your file tools (e.g., check `components/<namespace>/<name>/__init__.py`). Then, you will likely need to populate `core.py` and `__init__.py` using your file writing tools since they are created empty.
58 changes: 58 additions & 0 deletions .agents/skills/polylith/concepts/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: polylith-concepts
description: Provides foundational knowledge about Polylith architecture, including the glossary (bases, components, projects, workspaces), theme layouts, and package manager mapping. Use this when you need to understand Polylith terminology or how the repository is structured conceptually before taking action.
---

# Polylith Concepts & Glossary

## Glossary

### Bricks
The fundamental units of code in Polylith — **components** and **bases**. Bricks are reusable, isolated, and organized under a single **namespace**.

### Components
Reusable, isolated bricks that implement business logic or capabilities. Components are consumed by bases and by other components, never the other way around.

### Bases
Bricks that serve as the **entry point** of a deployable application — for example HTTP APIs, CLIs, message-queue consumers, AWS Lambda handlers, GCP Cloud Functions, or scheduled jobs. A base wires together components and exposes the application to its runtime.

### Namespace
The top-level Python package name under which all bricks live (e.g. `mycompany`). Defined once in `[tool.polylith].namespace` in `workspace.toml`; shared by every brick.

### Workspace
The root directory of a Polylith repository. Contains `workspace.toml`, the root `pyproject.toml` (which **is** the development project), the `bases/`, `components/`, `projects/`, and `development/` directories, and a single shared lock file.

### Projects
Lightweight `pyproject.toml` configurations under `projects/<name>/` that **reference bricks** to produce deployable artifacts (Docker images, wheels, Lambda packages). Projects contain no Python source code of their own.

### Development Project
The root `pyproject.toml` itself — a single, unified Python environment that includes **every** brick and **every** dependency (production and dev). Used for local development, REPL sessions, and notebooks under `development/`.

### Dependencies
- The **development project** (root `pyproject.toml`) holds **all** dependencies, including dev-only ones.
- Each **project** under `projects/` holds only its **production** dependencies.
- With **uv workspaces** (or Poetry workspaces), individual projects don't need to pin third-party versions — the root `pyproject.toml` and the shared lock file pin versions centrally.

## Package & Dependency Management mapping

The `poly` CLI is package-manager-agnostic — only the **command prefix** changes. Each SKILL.md repeats the prefix detection rule inline so the agent doesn't need this README to act. The full table:

| Tool | Detection signal | Command prefix |
|-------------------------------|------------------------------------------------------------------------|-------------------|
| **uv** (recommended) | `uv.lock` present, or `[tool.uv]` in `pyproject.toml` | `uv run poly …` |
| **Poetry** | `[tool.poetry]` in `pyproject.toml`, `poetry.lock` | `poetry poly …` (via `poetry-polylith-plugin`) |
| **PDM** | `[tool.pdm]` in `pyproject.toml`, `pdm.lock` | `pdm run poly …` |
| **Hatch** | `[tool.hatch]` in `pyproject.toml` | `hatch run poly …`|
| **Rye** | `requirements.lock` + `[tool.rye]` | `rye run poly …` |
| **Activated virtualenv** | `$VIRTUAL_ENV` set, or none of the above | `poly …` |

If multiple signals are present, prefer the lock file that exists, then `[tool.<x>]` markers, then plain `poly`.

## Themes

`[tool.polylith.structure].theme` controls the on-disk brick layout:

- **`loose`** (recommended) — flat `<bricks_dir>/<namespace>/<brick>/` directories with tests in a top-level `test/` folder. Used by `python-polylith` itself and by most public examples.
- **`tdd`** — each brick is its own directory with `src/` and `test/` siblings.

> The CLI default for `poly create workspace --theme` is **`tdd`**. Always pass `--theme loose` explicitly when loose is wanted.
Loading