simple-module-cli 0.0.10__tar.gz → 0.0.12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/PKG-INFO +11 -11
  2. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/README.md +9 -9
  3. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/pyproject.toml +3 -3
  4. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/app_project.py +1 -1
  5. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/cli.py +7 -7
  6. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/new.py +1 -1
  7. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/package_update.py +1 -1
  8. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/plugins.py +3 -3
  9. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/recipes.py +2 -2
  10. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/README.md +12 -12
  11. simple_module_cli-0.0.12/simple_module_cli/skills/simple-module-cli/SKILL.md +170 -0
  12. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-creating/SKILL.md +2 -2
  13. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-inertia-pages/SKILL.md +2 -2
  14. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-migrations/SKILL.md +1 -1
  15. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-testing/SKILL.md +1 -1
  16. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills_cmd.py +4 -4
  17. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/pages.ts +1 -1
  18. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/main.py +1 -1
  19. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/wizard.py +1 -1
  20. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_build_packaging.py +2 -2
  21. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_cli_new.py +1 -1
  22. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_cli_new_regressions.py +1 -1
  23. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_cli_package_update.py +1 -1
  24. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_cli_wizard.py +1 -1
  25. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_scaffolding_host.py +2 -2
  26. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_scaffolding_module.py +2 -2
  27. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_skills_cmd.py +1 -1
  28. simple_module_cli-0.0.10/simple_module_cli/skills/simple-module-cli/SKILL.md +0 -170
  29. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/.gitignore +0 -0
  30. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/LICENSE +0 -0
  31. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/__init__.py +0 -0
  32. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/_env.py +0 -0
  33. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/case.py +0 -0
  34. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/catalog.py +0 -0
  35. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/scaffolding.py +0 -0
  36. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-conventions/SKILL.md +0 -0
  37. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-database/SKILL.md +0 -0
  38. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-doctor/SKILL.md +0 -0
  39. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-locales/SKILL.md +0 -0
  40. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/skills/simple-module-registries/SKILL.md +0 -0
  41. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/.env.example +0 -0
  42. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/.gitignore +0 -0
  43. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/Makefile +0 -0
  44. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/README.md.tpl +0 -0
  45. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/_optional/background_tasks/Makefile.snippet +0 -0
  46. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/_optional/background_tasks/docker-compose.yml +0 -0
  47. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/_optional/background_tasks/host.Dockerfile +0 -0
  48. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/_optional/background_tasks/run_worker.py +0 -0
  49. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/_optional/background_tasks/worker.Dockerfile +0 -0
  50. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/alembic.ini +0 -0
  51. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/app.tsx +0 -0
  52. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/main.tsx +0 -0
  53. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/package.json.tpl +0 -0
  54. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/pages/Error.tsx +0 -0
  55. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/styles.css +0 -0
  56. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/tsconfig.json +0 -0
  57. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/client_app/vite.config.ts +0 -0
  58. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/migrations/env.py +0 -0
  59. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/migrations/script.py.mako +0 -0
  60. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/migrations/versions/.gitkeep +0 -0
  61. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/pyproject.toml.tpl +0 -0
  62. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/host/templates/index.html +0 -0
  63. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/.github/workflows/ci.yml +0 -0
  64. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/.github/workflows/publish.yml.tpl +0 -0
  65. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/.gitignore +0 -0
  66. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/README.md.tpl +0 -0
  67. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/__init__.py +0 -0
  68. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/endpoints/__init__.py +0 -0
  69. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/endpoints/api.py.tpl +0 -0
  70. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/module.py.tpl +0 -0
  71. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/pages/.gitkeep +0 -0
  72. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/services.py.tpl +0 -0
  73. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/__PACKAGE__/settings.py.tpl +0 -0
  74. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/package.json.tpl +0 -0
  75. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/pyproject.toml.tpl +0 -0
  76. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/tests/test_module.py.tpl +0 -0
  77. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/module/tsconfig.json.tpl +0 -0
  78. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/workspace/.env.example +0 -0
  79. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/workspace/.gitignore +0 -0
  80. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/workspace/Makefile +0 -0
  81. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/workspace/README.md.tpl +0 -0
  82. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/workspace/package.json.tpl +0 -0
  83. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/simple_module_cli/templates/workspace/pyproject.toml.tpl +0 -0
  84. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_cli_catalog.py +0 -0
  85. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_cli_recipes.py +0 -0
  86. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_no_framework_deps.py +0 -0
  87. {simple_module_cli-0.0.10 → simple_module_cli-0.0.12}/tests/test_plugin_discovery.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple_module_cli
3
- Version: 0.0.10
4
- Summary: Standalone scaffolder for the SimpleModule framework — `sm new`, `sm create-module`, plugin host.
3
+ Version: 0.0.12
4
+ Summary: Standalone scaffolder for the SimpleModule framework — `smpy new`, `smpy create-module`, plugin host.
5
5
  Project-URL: Homepage, https://github.com/antosubash/simple_module_python
6
6
  Project-URL: Repository, https://github.com/antosubash/simple_module_python
7
7
  Project-URL: Issues, https://github.com/antosubash/simple_module_python/issues
@@ -34,7 +34,7 @@ pip install simple_module_cli
34
34
  # or, to keep the CLI in its own venv:
35
35
  pipx install simple_module_cli
36
36
  # or, to run it without installing:
37
- uvx --from simple_module_cli sm new my-app
37
+ uvx --from simple_module_cli smpy new my-app
38
38
  ```
39
39
 
40
40
  The package depends only on `typer` and `tomlkit` — installing it does **not** pull in FastAPI, SQLModel, or any other framework runtime.
@@ -42,21 +42,21 @@ The package depends only on `typer` and `tomlkit` — installing it does **not**
42
42
  ## Usage
43
43
 
44
44
  ```bash
45
- sm new my-app # interactive wizard
46
- sm new my-app --yes --preset full # all built-in modules + background jobs
47
- sm create-module my_feature # scaffold a publishable module package
48
- sm create-host bare-host # scaffold a bare host (no opinionated wiring)
45
+ smpy new my-app # interactive wizard
46
+ smpy new my-app --yes --preset full # all built-in modules + background jobs
47
+ smpy create-module my_feature # scaffold a publishable module package
48
+ smpy create-host bare-host # scaffold a bare host (no opinionated wiring)
49
49
  ```
50
50
 
51
- Built-in commands: `sm new`, `sm create-host`, `sm create-module`.
51
+ Built-in commands: `smpy new`, `smpy create-host`, `smpy create-module`.
52
52
 
53
53
  When other framework packages are installed, they contribute additional subcommands via the `simple_module_cli.cli_plugins` entry-point group:
54
54
 
55
55
  | Package | Commands |
56
56
  |---|---|
57
- | `simple_module_hosting` | `sm host gen-pages`, `sm host sync-js-deps` |
58
- | `simple_module_users` | `sm users create-admin` |
59
- | `simple_module_settings` | `sm settings import-from-env` |
57
+ | `simple_module_hosting` | `smpy host gen-pages`, `smpy host sync-js-deps` |
58
+ | `simple_module_users` | `smpy users create-admin` |
59
+ | `simple_module_settings` | `smpy settings import-from-env` |
60
60
 
61
61
  ## License
62
62
 
@@ -9,7 +9,7 @@ pip install simple_module_cli
9
9
  # or, to keep the CLI in its own venv:
10
10
  pipx install simple_module_cli
11
11
  # or, to run it without installing:
12
- uvx --from simple_module_cli sm new my-app
12
+ uvx --from simple_module_cli smpy new my-app
13
13
  ```
14
14
 
15
15
  The package depends only on `typer` and `tomlkit` — installing it does **not** pull in FastAPI, SQLModel, or any other framework runtime.
@@ -17,21 +17,21 @@ The package depends only on `typer` and `tomlkit` — installing it does **not**
17
17
  ## Usage
18
18
 
19
19
  ```bash
20
- sm new my-app # interactive wizard
21
- sm new my-app --yes --preset full # all built-in modules + background jobs
22
- sm create-module my_feature # scaffold a publishable module package
23
- sm create-host bare-host # scaffold a bare host (no opinionated wiring)
20
+ smpy new my-app # interactive wizard
21
+ smpy new my-app --yes --preset full # all built-in modules + background jobs
22
+ smpy create-module my_feature # scaffold a publishable module package
23
+ smpy create-host bare-host # scaffold a bare host (no opinionated wiring)
24
24
  ```
25
25
 
26
- Built-in commands: `sm new`, `sm create-host`, `sm create-module`.
26
+ Built-in commands: `smpy new`, `smpy create-host`, `smpy create-module`.
27
27
 
28
28
  When other framework packages are installed, they contribute additional subcommands via the `simple_module_cli.cli_plugins` entry-point group:
29
29
 
30
30
  | Package | Commands |
31
31
  |---|---|
32
- | `simple_module_hosting` | `sm host gen-pages`, `sm host sync-js-deps` |
33
- | `simple_module_users` | `sm users create-admin` |
34
- | `simple_module_settings` | `sm settings import-from-env` |
32
+ | `simple_module_hosting` | `smpy host gen-pages`, `smpy host sync-js-deps` |
33
+ | `simple_module_users` | `smpy users create-admin` |
34
+ | `simple_module_settings` | `smpy settings import-from-env` |
35
35
 
36
36
  ## License
37
37
 
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "simple_module_cli"
3
- version = "0.0.10"
4
- description = "Standalone scaffolder for the SimpleModule framework — `sm new`, `sm create-module`, plugin host."
3
+ version = "0.0.12"
4
+ description = "Standalone scaffolder for the SimpleModule framework — `smpy new`, `smpy create-module`, plugin host."
5
5
  readme = "README.md"
6
6
  license = "MIT"
7
7
  license-files = ["LICENSE"]
@@ -25,7 +25,7 @@ dependencies = [
25
25
  ]
26
26
 
27
27
  [project.scripts]
28
- sm = "simple_module_cli.cli:main"
28
+ smpy = "simple_module_cli.cli:main"
29
29
  simple-module = "simple_module_cli.cli:main"
30
30
 
31
31
  [project.urls]
@@ -195,7 +195,7 @@ def _seed_static_dist_placeholder(static_dist: Path) -> None:
195
195
  def _pin_sample_module_deps(sample_dest: Path) -> None:
196
196
  """Replace the module template's future-API range pins with exact pins.
197
197
 
198
- The shared ``sm create-module`` template ships ``>=1.0,<2.0`` against the
198
+ The shared ``smpy create-module`` template ships ``>=1.0,<2.0`` against the
199
199
  framework's eventual stable line, but the workspace-bundled sample has to
200
200
  resolve against whatever the framework version actually is today (``==X``
201
201
  in pre-1.0). Without rewriting, ``uv sync`` can't satisfy the workspace.
@@ -1,13 +1,13 @@
1
- """Root `sm` Typer app — scaffolders + plugin mount.
1
+ """Root `smpy` Typer app — scaffolders + plugin mount.
2
2
 
3
3
  Built-in commands:
4
- sm new
5
- sm create-host
6
- sm create-module
7
- sm skills add / list / update
4
+ smpy new
5
+ smpy create-host
6
+ smpy create-module
7
+ smpy skills add / list / update
8
8
 
9
9
  Plugins discovered via the ``simple_module_cli.cli_plugins`` entry-point
10
- group are mounted as named subgroups (e.g. ``sm host gen-pages``).
10
+ group are mounted as named subgroups (e.g. ``smpy host gen-pages``).
11
11
  """
12
12
 
13
13
  from __future__ import annotations
@@ -101,7 +101,7 @@ discover_and_mount(app)
101
101
 
102
102
 
103
103
  def main() -> None:
104
- """Entry point for the `sm` console script."""
104
+ """Entry point for the `smpy` console script."""
105
105
  app()
106
106
 
107
107
 
@@ -1,4 +1,4 @@
1
- """``sm new`` Typer command — flag-driven or interactive scaffolder."""
1
+ """``smpy new`` Typer command — flag-driven or interactive scaffolder."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -1,4 +1,4 @@
1
- """``sm package-update`` — bump simple_module_* deps to latest PyPI versions.
1
+ """``smpy package-update`` — bump simple_module_* deps to latest PyPI versions.
2
2
 
3
3
  Walks the project's ``pyproject.toml`` (and any ``[tool.uv.workspace]`` members),
4
4
  finds every dependency whose distribution name starts with ``simple_module_`` /
@@ -1,11 +1,11 @@
1
- """Plugin discovery for ``sm`` via the ``simple_module_cli.cli_plugins`` group.
1
+ """Plugin discovery for ``smpy`` via the ``simple_module_cli.cli_plugins`` group.
2
2
 
3
3
  Each entry-point's value (``module:attr``) must resolve to a
4
4
  :class:`typer.Typer` instance. The entry-point name becomes the
5
- subcommand namespace under ``sm`` (e.g. ``sm host gen-pages``).
5
+ subcommand namespace under ``smpy`` (e.g. ``smpy host gen-pages``).
6
6
 
7
7
  Failed loads (broken import, wrong type) print one line to stderr and
8
- are skipped — ``sm`` keeps working with whatever else loads.
8
+ are skipped — ``smpy`` keeps working with whatever else loads.
9
9
  """
10
10
 
11
11
  from __future__ import annotations
@@ -1,6 +1,6 @@
1
1
  """Per-module post-scaffold recipes.
2
2
 
3
- A recipe is invoked by ``sm new`` after the base host scaffold lands. It
3
+ A recipe is invoked by ``smpy new`` after the base host scaffold lands. It
4
4
  performs module-specific actions (write helper scripts, append Make
5
5
  targets, drop a docker-compose stack). The framework layer is kept free
6
6
  of devex concerns — recipes know about Makefiles and compose, framework
@@ -68,7 +68,7 @@ class BackgroundTasksRecipe:
68
68
  if path.exists():
69
69
  raise FileExistsError(
70
70
  f"{path} already exists — refusing to clobber. "
71
- "Remove the file or run `sm new` against an empty directory."
71
+ "Remove the file or run `smpy new` against an empty directory."
72
72
  )
73
73
 
74
74
  run_worker_dest.parent.mkdir(parents=True, exist_ok=True)
@@ -6,22 +6,22 @@ Agent skills for working in a [simple_module_python](https://github.com/antosuba
6
6
 
7
7
  There are two install paths — pick whichever fits your project.
8
8
 
9
- ### Option A — `sm skills` (recommended for `simple_module_cli` users)
9
+ ### Option A — `smpy skills` (recommended for `simple_module_cli` users)
10
10
 
11
- Every project produced by `sm new` already depends on `simple_module_cli`, which ships these skills inside its wheel. From the project root:
11
+ Every project produced by `smpy new` already depends on `simple_module_cli`, which ships these skills inside its wheel. From the project root:
12
12
 
13
13
  ```bash
14
- sm skills list # see what's available
15
- sm skills add # install ALL skills into ./.claude/skills/
16
- sm skills add simple-module-creating # install just one
17
- sm skills add -g # install into ~/.claude/skills (machine-wide)
18
- sm skills add --dest agents/skills # custom target dir
19
- sm skills add --symlink # symlink to the bundled source (good for skill devs)
20
- sm skills update # re-pull updates for skills already installed
21
- sm skills update simple-module-doctor # explicit re-pull (force-overwrites)
14
+ smpy skills list # see what's available
15
+ smpy skills add # install ALL skills into ./.claude/skills/
16
+ smpy skills add simple-module-creating # install just one
17
+ smpy skills add -g # install into ~/.claude/skills (machine-wide)
18
+ smpy skills add --dest agents/skills # custom target dir
19
+ smpy skills add --symlink # symlink to the bundled source (good for skill devs)
20
+ smpy skills update # re-pull updates for skills already installed
21
+ smpy skills update simple-module-doctor # explicit re-pull (force-overwrites)
22
22
  ```
23
23
 
24
- `sm skills` resolves the bundled set against whatever version of `simple_module_cli` is installed, so upgrading the CLI ships skill updates the next time you run `sm skills update`.
24
+ `smpy skills` resolves the bundled set against whatever version of `simple_module_cli` is installed, so upgrading the CLI ships skill updates the next time you run `smpy skills update`.
25
25
 
26
26
  ### Option B — `npx skills` (no Python install needed)
27
27
 
@@ -38,7 +38,7 @@ The CLI is [vercel-labs/skills](https://github.com/vercel-labs/skills); see its
38
38
 
39
39
  | Skill | Use when |
40
40
  |---|---|
41
- | [simple-module-cli](./simple-module-cli/SKILL.md) | Invoking the `sm` CLI — `sm new`, `sm create-host`, `sm create-module`, `sm host gen-pages`, `sm users create-admin`, etc. |
41
+ | [simple-module-cli](./simple-module-cli/SKILL.md) | Invoking the `smpy` CLI — `smpy new`, `smpy create-host`, `smpy create-module`, `smpy host gen-pages`, `smpy users create-admin`, etc. |
42
42
  | [simple-module-creating](./simple-module-creating/SKILL.md) | Adding a new feature package — scaffolding, entry-point, `ModuleMeta` |
43
43
  | [simple-module-conventions](./simple-module-conventions/SKILL.md) | Writing or reviewing module code — the invariant list (SQLModel everywhere, settings layout, framework→plugin direction, etc.) |
44
44
  | [simple-module-database](./simple-module-database/SKILL.md) | Adding SQLModel tables, picking a mixin, or debugging session/transaction behavior |
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: simple-module-cli
3
+ description: Use when invoking the `smpy` CLI for a simple_module_python project — starting a new app, scaffolding a host or a publishable module, regenerating the Inertia page manifest, importing settings overrides from env, creating an admin user, or installing the bundled agent skills. Triggers on "smpy new", "smpy create-host", "smpy create-module", "smpy host gen-pages", "smpy users create-admin", "smpy skills add", or any unfamiliar `smpy` subcommand.
4
+ ---
5
+
6
+ # simple_module_python: the `smpy` CLI
7
+
8
+ The `smpy` command is provided by `simple_module_cli` (installed as a dep of `simple_module_hosting`). It groups four kinds of operations: scaffolding new things, project-time helpers for the host, admin shortcuts for the bundled modules, and installing the bundled agent skills.
9
+
10
+ ## Top-level commands
11
+
12
+ | Command | When to use |
13
+ |---|---|
14
+ | `smpy new <name>` | Greenfield: scaffold a complete app (host + selected modules) in one shot, with an interactive wizard for DB / tenancy / module preset |
15
+ | `smpy create-host <name>` | You want just a bare host project; you'll add modules later by `pip install`-ing them |
16
+ | `smpy create-module <name>` | You're authoring a publishable module package (separate repo, distributed via PyPI) |
17
+ | `smpy skills …` | Install / update the bundled agent-skill packs into a project (`add`, `list`, `update`) |
18
+ | `smpy host …` | Project-time helpers run from inside a host directory (page manifest, JS dep sync) |
19
+ | `smpy settings …` | Settings-module admin — currently `import-from-env` |
20
+ | `smpy users …` | Users-module admin — currently `create-admin` |
21
+
22
+ ## `smpy new <name>` — the wizard
23
+
24
+ The fastest way from zero to a working app. It calls `create-host` under the hood, then installs and wires up the modules you pick.
25
+
26
+ ```bash
27
+ # Interactive (asks for DB, tenancy, preset, module list)
28
+ smpy new MyApp
29
+
30
+ # Non-interactive: take all defaults (sqlite, no tenancy, standard preset)
31
+ smpy new MyApp --yes
32
+
33
+ # Pick a preset and add extras
34
+ smpy new MyApp --preset full --tenancy --db postgres
35
+ smpy new MyApp --preset minimal --with background_tasks,file_storage --yes
36
+
37
+ # Scaffold only — skip uv sync / npm install / alembic upgrade head
38
+ smpy new MyApp --no-install
39
+ ```
40
+
41
+ **Module presets:**
42
+
43
+ | Preset | Modules included |
44
+ |---|---|
45
+ | `minimal` | `users` (and `auth` as a dep) |
46
+ | `standard` (default) | `users`, `dashboard`, `permissions` (+ deps) |
47
+ | `full` | every module in the catalog |
48
+ | `custom` | interactive — pick each module yes/no |
49
+
50
+ `--with` accepts a comma-separated list of catalog keys (`auth, users, permissions, products, dashboard, settings, feature_flags, file_storage, background_tasks, …`). Transitive `requires` are auto-added; the wizard prints `Added X (required by Y)` so you can see what got pulled in.
51
+
52
+ **Options summary:**
53
+
54
+ | Flag | Default | Meaning |
55
+ |---|---|---|
56
+ | `--dest <PATH>` | `./<name>` | Where to write the project |
57
+ | `--db sqlite\|postgres` | `sqlite` | Backend configured in `.env.example` |
58
+ | `--tenancy / --no-tenancy` | `--no-tenancy` | Enable the multi-tenant middleware |
59
+ | `--preset minimal\|standard\|full` | wizard asks | Module bundle |
60
+ | `--with <names>` | none | Extra catalog keys beyond the preset |
61
+ | `--yes / -y` | off | Skip prompts; accept defaults |
62
+ | `--no-install` | off | Skip `uv sync` / `npm install` / `alembic upgrade head` |
63
+
64
+ ## `smpy create-host <name>` — bare host
65
+
66
+ ```bash
67
+ smpy create-host MyApp # empty host, no modules declared
68
+ smpy create-host MyApp --with Auth,Products # declare module deps in pyproject.toml
69
+ smpy create-host MyApp --dest ./apps/myapp # custom destination
70
+ ```
71
+
72
+ `--with` takes **PascalCase module names** (matching `ModuleMeta.name`), not catalog keys. Use this when you want to drive the build yourself rather than via `smpy new`'s wizard.
73
+
74
+ ## `smpy create-module <name>` — module package
75
+
76
+ For module authors publishing to PyPI. Scaffolds a standalone repo containing one module.
77
+
78
+ ```bash
79
+ smpy create-module orders # writes ./simple_module_orders/
80
+ smpy create-module orders --dest ./packages/orders
81
+ ```
82
+
83
+ The result is a complete package: `pyproject.toml` with the entry point declared, `module.py` with `ModuleBase`/`ModuleMeta` skeleton, `models.py`, `contracts/`, `endpoints/{api,views}.py`, `pages/`, `locales/en.json`, plus a tests directory wired up with `simple_module_test` fixtures.
84
+
85
+ `<name>` accepts any case — `orders`, `Orders`, `ORDERS`, `blog_posts` all work. The CLI lowercases it for the directory and PascalCases it for `ModuleMeta.name`.
86
+
87
+ For the post-scaffold steps (entry point, Inertia namespace, etc.) see **simple-module-creating**.
88
+
89
+ ## `smpy skills` — install the bundled agent skills
90
+
91
+ `simple_module_cli` ships a set of [SKILL.md](https://agentskills.io/specification) packs (the ones in this directory). Drop them into any project so Claude Code / Cursor / Codex / etc. find them automatically.
92
+
93
+ ```bash
94
+ smpy skills list # see what's available
95
+ smpy skills add # install ALL skills into ./.claude/skills/
96
+ smpy skills add simple-module-creating simple-module-cli # specific ones only
97
+ smpy skills add -g # ~/.claude/skills (machine-wide)
98
+ smpy skills add --dest agents/skills # explicit target dir
99
+ smpy skills add --symlink # symlink to bundled source (good when iterating on the skills themselves)
100
+ smpy skills update # re-pull whatever is already installed at the dest
101
+ smpy skills update simple-module-doctor # explicitly re-pull one (always force-overwrites)
102
+ ```
103
+
104
+ **Without `--force`, `smpy skills add` skips skills that already exist at the destination** — so re-running it is safe. Use `--force` (or `smpy skills update`) to overwrite.
105
+
106
+ The bundle resolves against your installed `simple_module_cli`. To get newer skills, upgrade the CLI (`uv sync` or `pip install -U simple_module_cli`) and re-run `smpy skills update`.
107
+
108
+ ## `smpy host gen-pages` — regenerate the Inertia manifest
109
+
110
+ Run from a host project. Scans every installed module's `pages/*.tsx`, writes `client_app/modules.{manifest.json,generated.ts,generated.css}`, and extends Vite's `server.fs.allow`.
111
+
112
+ ```bash
113
+ smpy host gen-pages # uses ./client_app
114
+ smpy host gen-pages --host-dir=apps/web/client_app
115
+ ```
116
+
117
+ `smpy new` runs this at scaffold time; you only need to call it manually after adding/renaming `.tsx` files mid-session, or after `pip install`-ing a new module that ships pages.
118
+
119
+ ## `smpy host sync-js-deps` — install module JS deps
120
+
121
+ Wheel-installed modules ship `package.json` declarations that need to land in the host's `client_app/node_modules`. This command does that. **In-repo workspace modules don't need it** — npm workspaces resolve them automatically.
122
+
123
+ ```bash
124
+ smpy host sync-js-deps # uses ./client_app
125
+ smpy host sync-js-deps --host-client-app=apps/web/client_app
126
+ ```
127
+
128
+ Run after `pip install <module>` if the new module ships frontend code.
129
+
130
+ ## `smpy settings import-from-env`
131
+
132
+ Walks the live environment for every `SM_<PREFIX>_<FIELD>` variable matching a registered settings dataclass and writes a SYSTEM-tier override into the settings module's store. Useful when promoting from environment-driven config (typical in Docker) to in-DB overrides (manageable in the admin UI) without re-keying values by hand.
133
+
134
+ ```bash
135
+ smpy settings import-from-env
136
+ ```
137
+
138
+ ## `smpy users create-admin`
139
+
140
+ Bootstraps the first admin user, or rotates an existing admin's password.
141
+
142
+ ```bash
143
+ smpy users create-admin -e admin@example.com -p hunter2
144
+ smpy users create-admin -e admin@example.com -p new-password --force # rotate
145
+ smpy users create-admin -e admin@example.com -p hunter2 --full-name "Admin"
146
+ ```
147
+
148
+ | Flag | Meaning |
149
+ |---|---|
150
+ | `-e, --email` (required) | Admin email |
151
+ | `-p, --password` (required) | Initial password (or new password with `--force`) |
152
+ | `--full-name` | Display name |
153
+ | `--force` | Update the password if the admin already exists; without it, the command exits if the email is taken |
154
+
155
+ Don't bake `--password` literals into a script you commit; use a secrets store and pass via shell expansion.
156
+
157
+ ## Pitfalls
158
+
159
+ - **Wrong shell for `--with`.** `smpy new` `--with auth,users` (catalog keys, lowercase). `smpy create-host` `--with Auth,Users` (`ModuleMeta.name`, PascalCase). They're not interchangeable.
160
+ - **Ran `smpy new` inside an existing project.** The default `--dest ./<name>` creates a sibling directory. If the directory already exists and is non-empty, the command errors out — pass `--dest` explicitly to disambiguate.
161
+ - **Ran `smpy host gen-pages` from outside the host directory.** Defaults to `./client_app`; pass `--host-dir` from elsewhere.
162
+ - **Forgot `smpy host sync-js-deps` after `pip install`-ing a module with pages.** Vite resolves module imports against `client_app/node_modules`; the new module's JS deps won't land until you sync.
163
+ - **Used `smpy create-module` to add a module to an existing host.** That command is for **publishable** packages, intended to live in their own repo. To add a module to an existing host: install it (`pip install simple_module_<name>` or add to `pyproject.toml` and `uv sync`), then autogenerate a migration. See **simple-module-creating** + **simple-module-migrations**.
164
+ - **Calling `smpy create-admin` before migrations have run.** The users tables don't exist yet; the command will error. Run `alembic upgrade head` first (or use `smpy new` which does it for you when `--no-install` isn't set).
165
+
166
+ ## Related skills
167
+
168
+ - **simple-module-creating** — what `smpy create-module` produces and the post-scaffold contract
169
+ - **simple-module-inertia-pages** — what `smpy host gen-pages` regenerates and why
170
+ - **simple-module-migrations** — the `alembic upgrade head` step `smpy new` runs
@@ -12,13 +12,13 @@ description: Use when adding a new feature package to a simple_module_python app
12
12
  ```bash
13
13
  # scaffold a publishable module package in ./orders (run in a fresh repo or
14
14
  # inside a host's modules/ directory)
15
- sm create-module orders
15
+ smpy create-module orders
16
16
 
17
17
  # install the new package into the host environment
18
18
  uv sync # or: pip install -e ./orders
19
19
 
20
20
  # if you added a frontend page, regenerate the Inertia manifest
21
- sm host gen-pages --host-dir=client_app
21
+ smpy host gen-pages --host-dir=client_app
22
22
 
23
23
  # if you added SQLModel tables, autogenerate + apply a migration
24
24
  uv run alembic revision --autogenerate -m "add orders module"
@@ -15,12 +15,12 @@ description: Use when adding or debugging an Inertia.js page in a simple_module_
15
15
  | Module page (snake-case dir) | `inertia.render("BlogPosts/Index", ...)` | `<module_pkg>/blog_posts/pages/Index.tsx` |
16
16
  | Host page | `inertia.render("Landing", ...)` | `<host>/client_app/pages/Landing.tsx` |
17
17
 
18
- The namespace is **PascalCase of the module's directory name**, not the file system path. Directory `blog_posts` → `BlogPosts`. The framework's manifest generator (`sm host gen-pages`) wires up Vite's `import.meta.glob` to resolve these keys at runtime.
18
+ The namespace is **PascalCase of the module's directory name**, not the file system path. Directory `blog_posts` → `BlogPosts`. The framework's manifest generator (`smpy host gen-pages`) wires up Vite's `import.meta.glob` to resolve these keys at runtime.
19
19
 
20
20
  After adding or renaming a `.tsx`, regenerate the manifest:
21
21
 
22
22
  ```bash
23
- sm host gen-pages --host-dir=client_app
23
+ smpy host gen-pages --host-dir=client_app
24
24
  ```
25
25
 
26
26
  Boot regenerates it too; mid-session adds need the manual call before HMR sees them.
@@ -23,7 +23,7 @@ my_host/ # the host project
23
23
 
24
24
  ## How autogenerate sees every module
25
25
 
26
- The host's `migrations/env.py` (scaffolded by `sm create-host`) calls:
26
+ The host's `migrations/env.py` (scaffolded by `smpy create-host`) calls:
27
27
 
28
28
  ```python
29
29
  from simple_module_db import build_module_metadata, make_include_object
@@ -84,7 +84,7 @@ modules/orders/
84
84
  └── test_service.py # imports orders.service
85
85
  ```
86
86
 
87
- The directory must be listed in the root `pyproject.toml` under `[tool.pytest.ini_options].testpaths` for `make test` to pick it up. `sm create-module` adds this entry; if you scaffolded a module by hand, add it.
87
+ The directory must be listed in the root `pyproject.toml` under `[tool.pytest.ini_options].testpaths` for `make test` to pick it up. `smpy create-module` adds this entry; if you scaffolded a module by hand, add it.
88
88
 
89
89
  ## Pitfalls
90
90
 
@@ -1,4 +1,4 @@
1
- """``sm skills`` — install or update agent skill packs in a target project.
1
+ """``smpy skills`` — install or update agent skill packs in a target project.
2
2
 
3
3
  Bundles the SKILL.md packs shipped under ``simple_module_cli/skills/`` and
4
4
  materialises them into a project directory (default ``.claude/skills``) so any
@@ -7,9 +7,9 @@ can pick them up.
7
7
 
8
8
  Three subcommands:
9
9
 
10
- * ``sm skills list`` — show every bundled skill and its description.
11
- * ``sm skills add`` — copy (or symlink) skills into the destination.
12
- * ``sm skills update`` — re-copy skills that are already installed at the
10
+ * ``smpy skills list`` — show every bundled skill and its description.
11
+ * ``smpy skills add`` — copy (or symlink) skills into the destination.
12
+ * ``smpy skills update`` — re-copy skills that are already installed at the
13
13
  destination, overwriting them.
14
14
  """
15
15
 
@@ -2,7 +2,7 @@
2
2
  * Inertia page resolver.
3
3
  *
4
4
  * Module pages are discovered via a generated file (modules.generated.ts)
5
- * emitted by the Python host at boot, or manually via `sm gen-pages`. Each
5
+ * emitted by the Python host at boot, or manually via `smpy gen-pages`. Each
6
6
  * installed module contributes an import.meta.glob() call with an absolute
7
7
  * path, so pages shipped inside pip-installed module wheels resolve.
8
8
  *
@@ -1,6 +1,6 @@
1
1
  """Host application entry point.
2
2
 
3
- This file was generated by `sm create-host`. Modules are discovered at boot
3
+ This file was generated by `smpy create-host`. Modules are discovered at boot
4
4
  via entry_points; add them to this host's pyproject.toml to install them.
5
5
  """
6
6
 
@@ -1,4 +1,4 @@
1
- """Interactive prompt sequence for ``sm new``."""
1
+ """Interactive prompt sequence for ``smpy new``."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -40,7 +40,7 @@ def built_artifacts(tmp_path_factory) -> tuple[Path, Path]:
40
40
 
41
41
 
42
42
  def test_wheel_contains_bundled_skills(built_artifacts: tuple[Path, Path]) -> None:
43
- """The wheel must ship the agent skill packs that ``sm skills`` depends on.
43
+ """The wheel must ship the agent skill packs that ``smpy skills`` depends on.
44
44
 
45
45
  Regression: ``[tool.hatch.build.targets.wheel.force-include]`` with
46
46
  ``../../skills`` made the wheel re-build from sdist crash with
@@ -61,7 +61,7 @@ def test_wheel_contains_bundled_skills(built_artifacts: tuple[Path, Path]) -> No
61
61
 
62
62
 
63
63
  def test_wheel_contains_templates(built_artifacts: tuple[Path, Path]) -> None:
64
- """``sm new`` reads from ``simple_module_cli/templates`` — must ship in the wheel."""
64
+ """``smpy new`` reads from ``simple_module_cli/templates`` — must ship in the wheel."""
65
65
  _, wheel = built_artifacts
66
66
  with zipfile.ZipFile(wheel) as zf:
67
67
  names = zf.namelist()
@@ -1,4 +1,4 @@
1
- """Tests for the `sm new` / `simple-module new` CLI subcommand."""
1
+ """Tests for the `smpy new` / `simple-module new` CLI subcommand."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -1,4 +1,4 @@
1
- """Regression tests for ``sm new`` scaffold bugs filed against released wheels.
1
+ """Regression tests for ``smpy new`` scaffold bugs filed against released wheels.
2
2
 
3
3
  Each test pins a specific issue's repro so the bug can't sneak back in
4
4
  without a CI failure pointing at the fix.
@@ -1,4 +1,4 @@
1
- """Tests for `sm package-update`."""
1
+ """Tests for `smpy package-update`."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -1,4 +1,4 @@
1
- """Tests for the `sm new` interactive wizard."""
1
+ """Tests for the `smpy new` interactive wizard."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -1,4 +1,4 @@
1
- """Tests for the module-pages manifest and `sm create-host` scaffolding."""
1
+ """Tests for the module-pages manifest and `smpy create-host` scaffolding."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -154,7 +154,7 @@ class TestCreateHost:
154
154
  assert "for mod in modules:" not in env_py
155
155
 
156
156
  async def test_cli_create_host_runs_end_to_end(self, tmp_path):
157
- """The Click `sm create-host` command produces a working scaffold."""
157
+ """The Click `smpy create-host` command produces a working scaffold."""
158
158
  from simple_module_cli.cli import app
159
159
  from typer.testing import CliRunner
160
160
 
@@ -1,4 +1,4 @@
1
- """Tests for `sm create-module` scaffolding: module package, CI, static bundling."""
1
+ """Tests for `smpy create-module` scaffolding: module package, CI, static bundling."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -74,7 +74,7 @@ class TestCreateModule:
74
74
  create_module(dest, name="MyFeature")
75
75
 
76
76
  async def test_cli_create_module_runs_end_to_end(self, tmp_path):
77
- """The Click `sm create-module` command produces a working scaffold."""
77
+ """The Click `smpy create-module` command produces a working scaffold."""
78
78
  from simple_module_cli.cli import app
79
79
  from typer.testing import CliRunner
80
80
 
@@ -1,4 +1,4 @@
1
- """Tests for the ``sm skills`` subcommand group."""
1
+ """Tests for the ``smpy skills`` subcommand group."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -1,170 +0,0 @@
1
- ---
2
- name: simple-module-cli
3
- description: Use when invoking the `sm` CLI for a simple_module_python project — starting a new app, scaffolding a host or a publishable module, regenerating the Inertia page manifest, importing settings overrides from env, creating an admin user, or installing the bundled agent skills. Triggers on "sm new", "sm create-host", "sm create-module", "sm host gen-pages", "sm users create-admin", "sm skills add", or any unfamiliar `sm` subcommand.
4
- ---
5
-
6
- # simple_module_python: the `sm` CLI
7
-
8
- The `sm` command is provided by `simple_module_cli` (installed as a dep of `simple_module_hosting`). It groups four kinds of operations: scaffolding new things, project-time helpers for the host, admin shortcuts for the bundled modules, and installing the bundled agent skills.
9
-
10
- ## Top-level commands
11
-
12
- | Command | When to use |
13
- |---|---|
14
- | `sm new <name>` | Greenfield: scaffold a complete app (host + selected modules) in one shot, with an interactive wizard for DB / tenancy / module preset |
15
- | `sm create-host <name>` | You want just a bare host project; you'll add modules later by `pip install`-ing them |
16
- | `sm create-module <name>` | You're authoring a publishable module package (separate repo, distributed via PyPI) |
17
- | `sm skills …` | Install / update the bundled agent-skill packs into a project (`add`, `list`, `update`) |
18
- | `sm host …` | Project-time helpers run from inside a host directory (page manifest, JS dep sync) |
19
- | `sm settings …` | Settings-module admin — currently `import-from-env` |
20
- | `sm users …` | Users-module admin — currently `create-admin` |
21
-
22
- ## `sm new <name>` — the wizard
23
-
24
- The fastest way from zero to a working app. It calls `create-host` under the hood, then installs and wires up the modules you pick.
25
-
26
- ```bash
27
- # Interactive (asks for DB, tenancy, preset, module list)
28
- sm new MyApp
29
-
30
- # Non-interactive: take all defaults (sqlite, no tenancy, standard preset)
31
- sm new MyApp --yes
32
-
33
- # Pick a preset and add extras
34
- sm new MyApp --preset full --tenancy --db postgres
35
- sm new MyApp --preset minimal --with background_tasks,file_storage --yes
36
-
37
- # Scaffold only — skip uv sync / npm install / alembic upgrade head
38
- sm new MyApp --no-install
39
- ```
40
-
41
- **Module presets:**
42
-
43
- | Preset | Modules included |
44
- |---|---|
45
- | `minimal` | `users` (and `auth` as a dep) |
46
- | `standard` (default) | `users`, `dashboard`, `permissions` (+ deps) |
47
- | `full` | every module in the catalog |
48
- | `custom` | interactive — pick each module yes/no |
49
-
50
- `--with` accepts a comma-separated list of catalog keys (`auth, users, permissions, products, dashboard, settings, feature_flags, file_storage, background_tasks, …`). Transitive `requires` are auto-added; the wizard prints `Added X (required by Y)` so you can see what got pulled in.
51
-
52
- **Options summary:**
53
-
54
- | Flag | Default | Meaning |
55
- |---|---|---|
56
- | `--dest <PATH>` | `./<name>` | Where to write the project |
57
- | `--db sqlite\|postgres` | `sqlite` | Backend configured in `.env.example` |
58
- | `--tenancy / --no-tenancy` | `--no-tenancy` | Enable the multi-tenant middleware |
59
- | `--preset minimal\|standard\|full` | wizard asks | Module bundle |
60
- | `--with <names>` | none | Extra catalog keys beyond the preset |
61
- | `--yes / -y` | off | Skip prompts; accept defaults |
62
- | `--no-install` | off | Skip `uv sync` / `npm install` / `alembic upgrade head` |
63
-
64
- ## `sm create-host <name>` — bare host
65
-
66
- ```bash
67
- sm create-host MyApp # empty host, no modules declared
68
- sm create-host MyApp --with Auth,Products # declare module deps in pyproject.toml
69
- sm create-host MyApp --dest ./apps/myapp # custom destination
70
- ```
71
-
72
- `--with` takes **PascalCase module names** (matching `ModuleMeta.name`), not catalog keys. Use this when you want to drive the build yourself rather than via `sm new`'s wizard.
73
-
74
- ## `sm create-module <name>` — module package
75
-
76
- For module authors publishing to PyPI. Scaffolds a standalone repo containing one module.
77
-
78
- ```bash
79
- sm create-module orders # writes ./simple_module_orders/
80
- sm create-module orders --dest ./packages/orders
81
- ```
82
-
83
- The result is a complete package: `pyproject.toml` with the entry point declared, `module.py` with `ModuleBase`/`ModuleMeta` skeleton, `models.py`, `contracts/`, `endpoints/{api,views}.py`, `pages/`, `locales/en.json`, plus a tests directory wired up with `simple_module_test` fixtures.
84
-
85
- `<name>` accepts any case — `orders`, `Orders`, `ORDERS`, `blog_posts` all work. The CLI lowercases it for the directory and PascalCases it for `ModuleMeta.name`.
86
-
87
- For the post-scaffold steps (entry point, Inertia namespace, etc.) see **simple-module-creating**.
88
-
89
- ## `sm skills` — install the bundled agent skills
90
-
91
- `simple_module_cli` ships a set of [SKILL.md](https://agentskills.io/specification) packs (the ones in this directory). Drop them into any project so Claude Code / Cursor / Codex / etc. find them automatically.
92
-
93
- ```bash
94
- sm skills list # see what's available
95
- sm skills add # install ALL skills into ./.claude/skills/
96
- sm skills add simple-module-creating simple-module-cli # specific ones only
97
- sm skills add -g # ~/.claude/skills (machine-wide)
98
- sm skills add --dest agents/skills # explicit target dir
99
- sm skills add --symlink # symlink to bundled source (good when iterating on the skills themselves)
100
- sm skills update # re-pull whatever is already installed at the dest
101
- sm skills update simple-module-doctor # explicitly re-pull one (always force-overwrites)
102
- ```
103
-
104
- **Without `--force`, `sm skills add` skips skills that already exist at the destination** — so re-running it is safe. Use `--force` (or `sm skills update`) to overwrite.
105
-
106
- The bundle resolves against your installed `simple_module_cli`. To get newer skills, upgrade the CLI (`uv sync` or `pip install -U simple_module_cli`) and re-run `sm skills update`.
107
-
108
- ## `sm host gen-pages` — regenerate the Inertia manifest
109
-
110
- Run from a host project. Scans every installed module's `pages/*.tsx`, writes `client_app/modules.{manifest.json,generated.ts,generated.css}`, and extends Vite's `server.fs.allow`.
111
-
112
- ```bash
113
- sm host gen-pages # uses ./client_app
114
- sm host gen-pages --host-dir=apps/web/client_app
115
- ```
116
-
117
- `sm new` runs this at scaffold time; you only need to call it manually after adding/renaming `.tsx` files mid-session, or after `pip install`-ing a new module that ships pages.
118
-
119
- ## `sm host sync-js-deps` — install module JS deps
120
-
121
- Wheel-installed modules ship `package.json` declarations that need to land in the host's `client_app/node_modules`. This command does that. **In-repo workspace modules don't need it** — npm workspaces resolve them automatically.
122
-
123
- ```bash
124
- sm host sync-js-deps # uses ./client_app
125
- sm host sync-js-deps --host-client-app=apps/web/client_app
126
- ```
127
-
128
- Run after `pip install <module>` if the new module ships frontend code.
129
-
130
- ## `sm settings import-from-env`
131
-
132
- Walks the live environment for every `SM_<PREFIX>_<FIELD>` variable matching a registered settings dataclass and writes a SYSTEM-tier override into the settings module's store. Useful when promoting from environment-driven config (typical in Docker) to in-DB overrides (manageable in the admin UI) without re-keying values by hand.
133
-
134
- ```bash
135
- sm settings import-from-env
136
- ```
137
-
138
- ## `sm users create-admin`
139
-
140
- Bootstraps the first admin user, or rotates an existing admin's password.
141
-
142
- ```bash
143
- sm users create-admin -e admin@example.com -p hunter2
144
- sm users create-admin -e admin@example.com -p new-password --force # rotate
145
- sm users create-admin -e admin@example.com -p hunter2 --full-name "Admin"
146
- ```
147
-
148
- | Flag | Meaning |
149
- |---|---|
150
- | `-e, --email` (required) | Admin email |
151
- | `-p, --password` (required) | Initial password (or new password with `--force`) |
152
- | `--full-name` | Display name |
153
- | `--force` | Update the password if the admin already exists; without it, the command exits if the email is taken |
154
-
155
- Don't bake `--password` literals into a script you commit; use a secrets store and pass via shell expansion.
156
-
157
- ## Pitfalls
158
-
159
- - **Wrong shell for `--with`.** `sm new` `--with auth,users` (catalog keys, lowercase). `sm create-host` `--with Auth,Users` (`ModuleMeta.name`, PascalCase). They're not interchangeable.
160
- - **Ran `sm new` inside an existing project.** The default `--dest ./<name>` creates a sibling directory. If the directory already exists and is non-empty, the command errors out — pass `--dest` explicitly to disambiguate.
161
- - **Ran `sm host gen-pages` from outside the host directory.** Defaults to `./client_app`; pass `--host-dir` from elsewhere.
162
- - **Forgot `sm host sync-js-deps` after `pip install`-ing a module with pages.** Vite resolves module imports against `client_app/node_modules`; the new module's JS deps won't land until you sync.
163
- - **Used `sm create-module` to add a module to an existing host.** That command is for **publishable** packages, intended to live in their own repo. To add a module to an existing host: install it (`pip install simple_module_<name>` or add to `pyproject.toml` and `uv sync`), then autogenerate a migration. See **simple-module-creating** + **simple-module-migrations**.
164
- - **Calling `sm create-admin` before migrations have run.** The users tables don't exist yet; the command will error. Run `alembic upgrade head` first (or use `sm new` which does it for you when `--no-install` isn't set).
165
-
166
- ## Related skills
167
-
168
- - **simple-module-creating** — what `sm create-module` produces and the post-scaffold contract
169
- - **simple-module-inertia-pages** — what `sm host gen-pages` regenerates and why
170
- - **simple-module-migrations** — the `alembic upgrade head` step `sm new` runs