karni-cli 0.3.1__tar.gz → 0.5.0__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.
- {karni_cli-0.3.1 → karni_cli-0.5.0}/.gitignore +8 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/PKG-INFO +110 -56
- karni_cli-0.5.0/README.md +206 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/hatch_build.py +38 -1
- karni_cli-0.5.0/karni_cli/__init__.py +8 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_agent/__init__.py +4 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_agent/check.py +71 -25
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_agent/history.py +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_agent/history_chronicle.py +2 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_agent/overrides.py +2 -2
- karni_cli-0.5.0/karni_cli/_agent/rules.py +1308 -0
- karni_cli-0.5.0/karni_cli/_catalog/__init__.py +576 -0
- karni_cli-0.5.0/karni_cli/_catalog/__main__.py +30 -0
- karni_cli-0.5.0/karni_cli/_catalog/features/api_cache.toml +19 -0
- karni_cli-0.5.0/karni_cli/_catalog/features/email_code_login.toml +25 -0
- karni_cli-0.5.0/karni_cli/_catalog/features/social_login.toml +27 -0
- karni_cli-0.5.0/karni_cli/_catalog/features/terms.toml +28 -0
- karni_cli-0.5.0/karni_cli/_catalog/features/two_factor.toml +20 -0
- karni_cli-0.5.0/karni_cli/_catalog/features/user_grants.toml +21 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-ai.toml +61 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-approvals.toml +50 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-charts.toml +34 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-impersonation.toml +59 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-payments.toml +56 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-reports.toml +53 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-site.toml +84 -0
- karni_cli-0.5.0/karni_cli/_catalog/modules/karni-storage.toml +67 -0
- karni_cli-0.5.0/karni_cli/_changelog/0.4.0.toml +101 -0
- karni_cli-0.5.0/karni_cli/_changelog/0.5.0.toml +819 -0
- karni_cli-0.5.0/karni_cli/_errorcodes/__init__.py +3202 -0
- karni_cli-0.5.0/karni_cli/_errorcodes/failures.py +1282 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_errorcodes/links.py +4 -2
- karni_cli-0.5.0/karni_cli/_settings/base.py +796 -0
- karni_cli-0.5.0/karni_cli/_settings/reference.py +491 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/cookiecutter.json +4 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/.dockerignore +4 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/.env.example +146 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/.gitignore +19 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/Dockerfile +112 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/Makefile +1 -1
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/README.md +220 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/settings.py +69 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/urls.py +45 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/docker-compose.yml +14 -5
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/.npmrc +15 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/Dockerfile.dev +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/eslint.config.js +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/index.html +1 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/package.json +12 -9
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/App.tsx +21 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/index.css +15 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/layout.tsx +88 -0
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/pages/home.tsx +31 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/routes.tsx +7 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/tailwind.config.ts +1 -1
- karni_cli-0.5.0/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/vite.config.ts +28 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/pyproject.toml +15 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/tests/test_api_schema.py +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/tests/test_smoke.py +5 -0
- karni_cli-0.5.0/karni_cli/_ui/styles.css +264 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/adapters.py +169 -26
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/agent_adapters.toml +24 -7
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/agent_data.py +11 -1
- karni_cli-0.5.0/karni_cli/agent_tools.py +505 -0
- karni_cli-0.5.0/karni_cli/builder/__init__.py +21 -0
- karni_cli-0.5.0/karni_cli/builder/layout.py +83 -0
- karni_cli-0.5.0/karni_cli/builder/output.py +134 -0
- karni_cli-0.5.0/karni_cli/builder/record.py +215 -0
- karni_cli-0.5.0/karni_cli/builder/render.py +1155 -0
- karni_cli-0.5.0/karni_cli/builder/run.py +1111 -0
- karni_cli-0.5.0/karni_cli/catalog.py +274 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/clidoc.py +27 -12
- karni_cli-0.5.0/karni_cli/commands/add.py +463 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/beat.py +2 -1
- karni_cli-0.5.0/karni_cli/commands/build.py +131 -0
- karni_cli-0.5.0/karni_cli/commands/check.py +430 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/config.py +4 -4
- karni_cli-0.5.0/karni_cli/commands/context.py +445 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/createsuperuser.py +2 -1
- karni_cli-0.5.0/karni_cli/commands/design.py +246 -0
- karni_cli-0.5.0/karni_cli/commands/doctor.py +286 -0
- karni_cli-0.5.0/karni_cli/commands/explain.py +220 -0
- karni_cli-0.5.0/karni_cli/commands/import_design.py +608 -0
- karni_cli-0.5.0/karni_cli/commands/load.py +45 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/make.py +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/manage_passthrough.py +10 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/migrate.py +8 -3
- karni_cli-0.5.0/karni_cli/commands/modules.py +182 -0
- karni_cli-0.5.0/karni_cli/commands/new.py +697 -0
- karni_cli-0.5.0/karni_cli/commands/plan.py +155 -0
- karni_cli-0.5.0/karni_cli/commands/queries.py +106 -0
- karni_cli-0.5.0/karni_cli/commands/recipes.py +196 -0
- karni_cli-0.5.0/karni_cli/commands/remove.py +402 -0
- karni_cli-0.5.0/karni_cli/commands/replay.py +53 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/routes.py +4 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/rules.py +56 -10
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/run_tests.py +2 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/schedule.py +9 -3
- karni_cli-0.5.0/karni_cli/commands/schema.py +61 -0
- karni_cli-0.5.0/karni_cli/commands/seed.py +51 -0
- karni_cli-0.5.0/karni_cli/commands/serve.py +164 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/shell.py +1 -1
- karni_cli-0.5.0/karni_cli/commands/spec.py +191 -0
- karni_cli-0.5.0/karni_cli/commands/suggest.py +60 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/sync_roles.py +9 -2
- karni_cli-0.5.0/karni_cli/commands/trace.py +31 -0
- karni_cli-0.5.0/karni_cli/commands/types.py +142 -0
- karni_cli-0.5.0/karni_cli/commands/ui.py +597 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/upgrade.py +3 -3
- karni_cli-0.5.0/karni_cli/commands/why.py +203 -0
- karni_cli-0.5.0/karni_cli/commands/worker.py +113 -0
- karni_cli-0.5.0/karni_cli/database.py +176 -0
- karni_cli-0.5.0/karni_cli/db_probe.py +89 -0
- karni_cli-0.5.0/karni_cli/debugging.py +113 -0
- karni_cli-0.5.0/karni_cli/design/__init__.py +30 -0
- karni_cli-0.5.0/karni_cli/design/analyze.py +361 -0
- karni_cli-0.5.0/karni_cli/design/builder.py +2058 -0
- karni_cli-0.5.0/karni_cli/design/compare.py +603 -0
- karni_cli-0.5.0/karni_cli/design/editable.py +1717 -0
- karni_cli-0.5.0/karni_cli/design/extract.py +813 -0
- karni_cli-0.5.0/karni_cli/design/forms.py +602 -0
- karni_cli-0.5.0/karni_cli/design/hours.py +281 -0
- karni_cli-0.5.0/karni_cli/design/images.py +388 -0
- karni_cli-0.5.0/karni_cli/design/mapref.py +369 -0
- karni_cli-0.5.0/karni_cli/design/parse.py +411 -0
- karni_cli-0.5.0/karni_cli/design/proposal.py +708 -0
- karni_cli-0.5.0/karni_cli/design/regions.py +156 -0
- karni_cli-0.5.0/karni_cli/design/rewrite.py +534 -0
- karni_cli-0.5.0/karni_cli/design/scan.py +442 -0
- karni_cli-0.5.0/karni_cli/design/select.py +471 -0
- karni_cli-0.5.0/karni_cli/design/seo.py +70 -0
- karni_cli-0.5.0/karni_cli/design/site.py +1013 -0
- karni_cli-0.5.0/karni_cli/design/sources.py +712 -0
- karni_cli-0.5.0/karni_cli/design/values.py +475 -0
- karni_cli-0.5.0/karni_cli/envfile.py +69 -0
- karni_cli-0.5.0/karni_cli/errorcodes.py +1614 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/errordoc.py +78 -17
- karni_cli-0.5.0/karni_cli/explain_text.py +62 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/__init__.py +8 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/apitest.py +152 -35
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/app.py +8 -7
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/command.py +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/component.py +2 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/core.py +30 -13
- karni_cli-0.5.0/karni_cli/generators/deploy.py +880 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/event.py +1 -1
- karni_cli-0.5.0/karni_cli/generators/external.py +234 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/factory.py +1 -1
- karni_cli-0.5.0/karni_cli/generators/fields.py +807 -0
- karni_cli-0.5.0/karni_cli/generators/form.py +1089 -0
- karni_cli-0.5.0/karni_cli/generators/introspect.py +493 -0
- karni_cli-0.5.0/karni_cli/generators/lifecycle_fields.py +207 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/listener.py +9 -8
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/middleware.py +2 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/migration.py +5 -5
- karni_cli-0.5.0/karni_cli/generators/model.py +444 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/module.py +40 -10
- karni_cli-0.5.0/karni_cli/generators/naming.py +225 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/page.py +264 -25
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/pysource.py +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/schedule.py +9 -9
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/seeder.py +3 -3
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/serializer.py +7 -6
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/service.py +3 -3
- karni_cli-0.5.0/karni_cli/generators/site.py +677 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/task.py +2 -2
- karni_cli-0.5.0/karni_cli/generators/view.py +219 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/generators/viewset.py +81 -14
- karni_cli-0.5.0/karni_cli/kinds.py +253 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/local_state.py +14 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/main.py +61 -6
- karni_cli-0.5.0/karni_cli/mcp_server.py +339 -0
- karni_cli-0.5.0/karni_cli/module_codes.json +762 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/project.py +136 -31
- karni_cli-0.5.0/karni_cli/pyproject_edit.py +121 -0
- karni_cli-0.5.0/karni_cli/recipes/__init__.py +506 -0
- karni_cli-0.5.0/karni_cli/recipes/__main__.py +9 -0
- karni_cli-0.5.0/karni_cli/recipes/apply.py +114 -0
- karni_cli-0.5.0/karni_cli/recipes/booking/files/bookings/models.py +63 -0
- karni_cli-0.5.0/karni_cli/recipes/booking/files/bookings/tests/test_capacity.py +45 -0
- karni_cli-0.5.0/karni_cli/recipes/booking/files/bookings/viewsets.py +45 -0
- karni_cli-0.5.0/karni_cli/recipes/booking/karni.yaml +52 -0
- karni_cli-0.5.0/karni_cli/recipes/booking/recipe.toml +17 -0
- karni_cli-0.5.0/karni_cli/recipes/crm/files/crm/tests/test_pipeline.py +57 -0
- karni_cli-0.5.0/karni_cli/recipes/crm/files/crm/viewsets.py +39 -0
- karni_cli-0.5.0/karni_cli/recipes/crm/karni.yaml +80 -0
- karni_cli-0.5.0/karni_cli/recipes/crm/recipe.toml +18 -0
- karni_cli-0.5.0/karni_cli/recipes/data-portal/files/portal/seeds.py +157 -0
- karni_cli-0.5.0/karni_cli/recipes/data-portal/files/portal/tests/conftest.py +10 -0
- karni_cli-0.5.0/karni_cli/recipes/data-portal/files/portal/tests/test_portal.py +240 -0
- karni_cli-0.5.0/karni_cli/recipes/data-portal/karni.yaml +120 -0
- karni_cli-0.5.0/karni_cli/recipes/data-portal/recipe.toml +19 -0
- karni_cli-0.5.0/karni_cli/recipes/lms/files/courses/models.py +41 -0
- karni_cli-0.5.0/karni_cli/recipes/lms/files/courses/seeds.py +42 -0
- karni_cli-0.5.0/karni_cli/recipes/lms/files/courses/tests/test_completion.py +45 -0
- karni_cli-0.5.0/karni_cli/recipes/lms/files/courses/viewsets.py +30 -0
- karni_cli-0.5.0/karni_cli/recipes/lms/karni.yaml +73 -0
- karni_cli-0.5.0/karni_cli/recipes/lms/recipe.toml +16 -0
- karni_cli-0.5.0/karni_cli/recipes/marketplace/files/market/models.py +70 -0
- karni_cli-0.5.0/karni_cli/recipes/marketplace/files/market/tests/test_payouts.py +47 -0
- karni_cli-0.5.0/karni_cli/recipes/marketplace/files/market/viewsets.py +42 -0
- karni_cli-0.5.0/karni_cli/recipes/marketplace/karni.yaml +89 -0
- karni_cli-0.5.0/karni_cli/recipes/marketplace/recipe.toml +17 -0
- karni_cli-0.5.0/karni_cli/recipes/output.py +193 -0
- karni_cli-0.5.0/karni_cli/recipes/shop/files/shop/models.py +83 -0
- karni_cli-0.5.0/karni_cli/recipes/shop/files/shop/seeds.py +42 -0
- karni_cli-0.5.0/karni_cli/recipes/shop/files/shop/tests/test_checkout.py +55 -0
- karni_cli-0.5.0/karni_cli/recipes/shop/files/shop/viewsets.py +51 -0
- karni_cli-0.5.0/karni_cli/recipes/shop/karni.yaml +72 -0
- karni_cli-0.5.0/karni_cli/recipes/shop/recipe.toml +18 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/rules_render.py +19 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/scaffold.py +48 -5
- karni_cli-0.5.0/karni_cli/services.py +157 -0
- karni_cli-0.5.0/karni_cli/settingref.py +150 -0
- karni_cli-0.5.0/karni_cli/settings_edit.py +248 -0
- karni_cli-0.5.0/karni_cli/spec/__init__.py +17 -0
- karni_cli-0.5.0/karni_cli/spec/catalog.py +159 -0
- karni_cli-0.5.0/karni_cli/spec/edit.py +215 -0
- karni_cli-0.5.0/karni_cli/spec/emit.py +121 -0
- karni_cli-0.5.0/karni_cli/spec/export.py +1096 -0
- karni_cli-0.5.0/karni_cli/spec/navigation.py +283 -0
- karni_cli-0.5.0/karni_cli/spec/normal.py +277 -0
- karni_cli-0.5.0/karni_cli/spec/plan.py +1480 -0
- karni_cli-0.5.0/karni_cli/spec/questions.py +733 -0
- karni_cli-0.5.0/karni_cli/spec/schema.py +722 -0
- karni_cli-0.5.0/karni_cli/spec/source.py +102 -0
- karni_cli-0.5.0/karni_cli/spec/validate.py +2184 -0
- karni_cli-0.5.0/karni_cli/suggest.py +433 -0
- karni_cli-0.5.0/karni_cli/templateref.py +113 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/tips.py +5 -3
- karni_cli-0.5.0/karni_cli/toolchain.py +87 -0
- karni_cli-0.5.0/karni_cli/typegen.py +201 -0
- karni_cli-0.5.0/karni_cli/uitheme/__init__.py +32 -0
- karni_cli-0.5.0/karni_cli/uitheme/colour.py +221 -0
- karni_cli-0.5.0/karni_cli/uitheme/css.py +222 -0
- karni_cli-0.5.0/karni_cli/uitheme/defaults.py +111 -0
- karni_cli-0.5.0/karni_cli/uitheme/designsystems.py +699 -0
- karni_cli-0.5.0/karni_cli/uitheme/frontend.py +236 -0
- karni_cli-0.5.0/karni_cli/uitheme/jsobject.py +317 -0
- karni_cli-0.5.0/karni_cli/uitheme/model.py +173 -0
- karni_cli-0.5.0/karni_cli/uitheme/plaincss.py +1192 -0
- karni_cli-0.5.0/karni_cli/uitheme/primitives.py +192 -0
- karni_cli-0.5.0/karni_cli/uitheme/render.py +211 -0
- karni_cli-0.5.0/karni_cli/uitheme/shadcn.py +259 -0
- karni_cli-0.5.0/karni_cli/uitheme/tailwind.py +707 -0
- karni_cli-0.5.0/karni_cli/uitheme/wiring.py +143 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/engine.py +2 -2
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/python.py +5 -5
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/typescript.py +1 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v0_2/agent_guidance.py +9 -4
- karni_cli-0.5.0/karni_cli/upgrades/v0_5/urls_marker.py +61 -0
- karni_cli-0.5.0/karni_cli/urls_edit.py +120 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/pyproject.toml +14 -6
- karni_cli-0.5.0/tests/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/conftest.py +83 -0
- karni_cli-0.5.0/tests/fixtures/designs/academy/admissions.html +60 -0
- karni_cli-0.5.0/tests/fixtures/designs/academy/css/bootstrap.css +12 -0
- karni_cli-0.5.0/tests/fixtures/designs/academy/css/school.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/academy/img/garden.svg +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/academy/index.html +33 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/about.html +37 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/contact.html +40 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/css/site.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/img/hero.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/img/logo.svg +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/img/oven.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/img/pattern.png +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/img/unused.png +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/index.html +42 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/js/app.js +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/menu.html +40 -0
- karni_cli-0.5.0/tests/fixtures/designs/bakery/specials.html +9 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/404.html +36 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/css/bootstrap.min.css +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/css/clinic.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/css/fonts.css +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/fonts/clinic.woff2 +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/img/clinic.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/img/old-logo.png +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/index.html +37 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/js/bootstrap.bundle.min.js +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/services/dental.html +36 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/services/eyes.html +36 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/services/index.html +36 -0
- karni_cli-0.5.0/tests/fixtures/designs/clinic/team.html +29 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/courses.html +27 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/css/school.css +5 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/badge.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/campus.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/campus.webp +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/course-art.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/course-music.png +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/hero.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/logo.svg +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/share.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/img/teacher.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/college/index.html +32 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/contact.html +37 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/css/bootstrap.min.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/css/shop.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/baguette.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/carrot-cake.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/eclair.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/flat-white.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/lemon-tart.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/lemonade.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/rye.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/shop.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/img/sourdough.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/index.html +82 -0
- karni_cli-0.5.0/tests/fixtures/designs/patisserie/menu.html +157 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/img/bg.png +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/img/hero.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/img/hero.webp +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/img/shot-1x.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/img/shot-2x.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/index.html +40 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/scripts/reveal.js +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/portfolio/styles/main.css +1 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/about.html +29 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/css/practice.css +3 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/doctors/ada-okoro.html +54 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/doctors/ben-lim.html +55 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/doctors/cara-diaz.html +54 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/img/ada.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/img/ben.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/img/cara.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/img/logo.png +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/img/waiting-room.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/index.html +61 -0
- karni_cli-0.5.0/tests/fixtures/designs/practice/treatments.html +54 -0
- karni_cli-0.5.0/tests/fixtures/designs/salon/css/salon.css +12 -0
- karni_cli-0.5.0/tests/fixtures/designs/salon/index.html +41 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/courses/drawing.html +55 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/courses/pottery.html +56 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/courses/printing.html +53 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/courses/weaving.html +54 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/courses.html +65 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/css/school.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/drawing-1.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/drawing-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/drawing.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/lena.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/mia.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/omar.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/pottery-1.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/pottery-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/pottery-3.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/pottery.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/printing-1.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/printing.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/studio.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/weaving-1.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/weaving-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/img/weaving.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/index.html +56 -0
- karni_cli-0.5.0/tests/fixtures/designs/school/teachers.html +45 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/about.html +63 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/css/studio.css +2 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/about-1.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/about-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/ines.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/kiosk-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/kiosk.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/lakehouse-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/lakehouse-3.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/lakehouse.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/library-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/library-3.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/library.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/loft-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/loft.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/ola.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/slide-1.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/slide-2.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/slide-3.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/theo.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/img/yara.jpg +0 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/index.html +119 -0
- karni_cli-0.5.0/tests/fixtures/designs/studio/js/studio.js +1 -0
- karni_cli-0.5.0/tests/fixtures/spec/harbour-yoga.build.json +448 -0
- karni_cli-0.5.0/tests/fixtures/spec/harbour-yoga.plan.json +287 -0
- karni_cli-0.5.0/tests/fixtures/spec/harbour-yoga.yaml +60 -0
- karni_cli-0.5.0/tests/fixtures/ui/chakra/package.json +9 -0
- karni_cli-0.5.0/tests/fixtures/ui/chakra/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/chakra/src/theme.ts +35 -0
- karni_cli-0.5.0/tests/fixtures/ui/chakra3/package.json +9 -0
- karni_cli-0.5.0/tests/fixtures/ui/chakra3/src/components/ui/theme.ts +29 -0
- karni_cli-0.5.0/tests/fixtures/ui/chakra3/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/bakery/menu.css +36 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/bootstrap/theme.css +39 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/clinic/style.css +57 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/night/theme.css +20 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/about.html +9 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/css/about.css +2 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/css/site.css +17 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/css/tokens.css +8 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/css/unused.css +2 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/index.html +14 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/portfolio/vendor/normalize.css +4 -0
- karni_cli-0.5.0/tests/fixtures/ui/css/switching/app.css +27 -0
- karni_cli-0.5.0/tests/fixtures/ui/mantine/package.json +9 -0
- karni_cli-0.5.0/tests/fixtures/ui/mantine/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/mantine/src/theme.ts +41 -0
- karni_cli-0.5.0/tests/fixtures/ui/mui/package.json +11 -0
- karni_cli-0.5.0/tests/fixtures/ui/mui/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/mui/src/theme/index.ts +29 -0
- karni_cli-0.5.0/tests/fixtures/ui/plain/package.json +5 -0
- karni_cli-0.5.0/tests/fixtures/ui/plain/src/index.css +4 -0
- karni_cli-0.5.0/tests/fixtures/ui/plain/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/components.json +18 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/package.json +16 -0
- {karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend → karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3}/src/App.tsx +0 -2
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/components/ui/button.tsx +29 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/components/ui/checkbox.tsx +14 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/components/ui/input.tsx +12 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/components/ui/label.tsx +16 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/components/ui/select.tsx +69 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/index.css +49 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/src/main.tsx +11 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/tailwind.config.js +18 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw3/tsconfig.json +10 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/components.json +21 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/package.json +11 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/App.tsx +5 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/components/ui/button.tsx +23 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/components/ui/select.tsx +42 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/components/ui/switch.tsx +10 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/components/ui/textarea.tsx +9 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/index.css +60 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/src/main.tsx +10 -0
- karni_cli-0.5.0/tests/fixtures/ui/shadcn-tw4/tsconfig.json +9 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind3/package.json +6 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind3/src/index.css +3 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind3/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind3/tailwind.config.ts +32 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind4/package.json +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind4/src/index.css +8 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind4/src/main.tsx +7 -0
- karni_cli-0.5.0/tests/fixtures/ui/tailwind4/src/theme.css +27 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_adapters.py +142 -25
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_add.py +49 -11
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_agent_upgrade.py +6 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_audit_fixes.py +59 -2
- karni_cli-0.5.0/tests/test_bench_tokens.py +668 -0
- karni_cli-0.5.0/tests/test_benchmark.py +98 -0
- karni_cli-0.5.0/tests/test_build.py +1289 -0
- karni_cli-0.5.0/tests/test_catalog.py +567 -0
- karni_cli-0.5.0/tests/test_check.py +366 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_clidoc.py +1 -1
- karni_cli-0.5.0/tests/test_command_states.py +268 -0
- karni_cli-0.5.0/tests/test_context.py +366 -0
- karni_cli-0.5.0/tests/test_database.py +309 -0
- karni_cli-0.5.0/tests/test_debugging.py +176 -0
- karni_cli-0.5.0/tests/test_design_address.py +121 -0
- karni_cli-0.5.0/tests/test_design_analyze.py +658 -0
- karni_cli-0.5.0/tests/test_design_content.py +174 -0
- karni_cli-0.5.0/tests/test_design_extract.py +431 -0
- karni_cli-0.5.0/tests/test_design_hours.py +69 -0
- karni_cli-0.5.0/tests/test_design_terms.py +106 -0
- karni_cli-0.5.0/tests/test_docs_links.py +181 -0
- karni_cli-0.5.0/tests/test_docs_roadmap.py +60 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_doctor.py +99 -10
- karni_cli-0.5.0/tests/test_envfile.py +51 -0
- karni_cli-0.5.0/tests/test_errorcodes_cli.py +297 -0
- karni_cli-0.5.0/tests/test_explain_tags_and_map.py +123 -0
- karni_cli-0.5.0/tests/test_explain_text.py +233 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_history.py +7 -4
- karni_cli-0.5.0/tests/test_import_design.py +1004 -0
- karni_cli-0.5.0/tests/test_import_design_menu_rows.py +127 -0
- karni_cli-0.5.0/tests/test_import_design_seo.py +240 -0
- karni_cli-0.5.0/tests/test_kinds.py +518 -0
- karni_cli-0.5.0/tests/test_make.py +1317 -0
- karni_cli-0.5.0/tests/test_make_deploy.py +564 -0
- karni_cli-0.5.0/tests/test_make_external.py +216 -0
- karni_cli-0.5.0/tests/test_make_form.py +833 -0
- karni_cli-0.5.0/tests/test_make_gate.py +792 -0
- karni_cli-0.5.0/tests/test_make_lifecycle.py +114 -0
- karni_cli-0.5.0/tests/test_make_model_order_key.py +49 -0
- karni_cli-0.5.0/tests/test_make_model_pk.py +65 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_make_units.py +111 -1
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_mcp.py +42 -4
- karni_cli-0.5.0/tests/test_model_plural.py +85 -0
- karni_cli-0.5.0/tests/test_module_migrations.py +55 -0
- karni_cli-0.5.0/tests/test_new.py +587 -0
- karni_cli-0.5.0/tests/test_new_app.py +320 -0
- karni_cli-0.5.0/tests/test_new_recipe.py +376 -0
- karni_cli-0.5.0/tests/test_plan.py +1232 -0
- karni_cli-0.5.0/tests/test_questions.py +612 -0
- karni_cli-0.5.0/tests/test_recipe_builds.py +74 -0
- karni_cli-0.5.0/tests/test_recipes.py +405 -0
- karni_cli-0.5.0/tests/test_release.py +537 -0
- karni_cli-0.5.0/tests/test_rules.py +278 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_runners.py +183 -7
- karni_cli-0.5.0/tests/test_schema_cli.py +83 -0
- karni_cli-0.5.0/tests/test_services.py +254 -0
- karni_cli-0.5.0/tests/test_spec.py +1281 -0
- karni_cli-0.5.0/tests/test_spec_navigation.py +194 -0
- karni_cli-0.5.0/tests/test_speed.py +83 -0
- karni_cli-0.5.0/tests/test_suggest.py +474 -0
- karni_cli-0.5.0/tests/test_tool_names.py +101 -0
- karni_cli-0.5.0/tests/test_types.py +210 -0
- karni_cli-0.5.0/tests/test_ui_detect.py +721 -0
- karni_cli-0.5.0/tests/test_ui_detect_css.py +458 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_upgrade.py +149 -6
- karni_cli-0.5.0/tests/test_why.py +191 -0
- karni_cli-0.3.1/README.md +0 -153
- karni_cli-0.3.1/karni_cli/__init__.py +0 -3
- karni_cli-0.3.1/karni_cli/_agent/rules.py +0 -673
- karni_cli-0.3.1/karni_cli/_errorcodes/__init__.py +0 -1171
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/.env.example +0 -85
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/.gitignore +0 -10
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/Caddyfile +0 -22
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/Dockerfile +0 -53
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/README.md +0 -169
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/settings.py +0 -28
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/urls.py +0 -31
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/.npmrc +0 -7
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/postcss.config.js +0 -6
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/api/health.ts +0 -21
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/index.css +0 -11
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/layout.tsx +0 -51
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/pages/home.tsx +0 -28
- karni_cli-0.3.1/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/vite.config.ts +0 -18
- karni_cli-0.3.1/karni_cli/commands/add.py +0 -144
- karni_cli-0.3.1/karni_cli/commands/check.py +0 -101
- karni_cli-0.3.1/karni_cli/commands/context.py +0 -171
- karni_cli-0.3.1/karni_cli/commands/doctor.py +0 -136
- karni_cli-0.3.1/karni_cli/commands/explain.py +0 -60
- karni_cli-0.3.1/karni_cli/commands/new.py +0 -106
- karni_cli-0.3.1/karni_cli/commands/seed.py +0 -34
- karni_cli-0.3.1/karni_cli/commands/serve.py +0 -50
- karni_cli-0.3.1/karni_cli/commands/types.py +0 -72
- karni_cli-0.3.1/karni_cli/commands/worker.py +0 -63
- karni_cli-0.3.1/karni_cli/errorcodes.py +0 -377
- karni_cli-0.3.1/karni_cli/generators/fields.py +0 -343
- karni_cli-0.3.1/karni_cli/generators/introspect.py +0 -263
- karni_cli-0.3.1/karni_cli/generators/model.py +0 -235
- karni_cli-0.3.1/karni_cli/generators/naming.py +0 -100
- karni_cli-0.3.1/karni_cli/mcp_server.py +0 -103
- karni_cli-0.3.1/karni_cli/settings_edit.py +0 -128
- karni_cli-0.3.1/karni_cli/typegen.py +0 -101
- karni_cli-0.3.1/tests/test_check.py +0 -78
- karni_cli-0.3.1/tests/test_context.py +0 -134
- karni_cli-0.3.1/tests/test_errorcodes_cli.py +0 -130
- karni_cli-0.3.1/tests/test_make.py +0 -541
- karni_cli-0.3.1/tests/test_make_gate.py +0 -404
- karni_cli-0.3.1/tests/test_new.py +0 -216
- karni_cli-0.3.1/tests/test_rules.py +0 -156
- karni_cli-0.3.1/tests/test_types.py +0 -48
- {karni_cli-0.3.1 → karni_cli-0.5.0}/LICENSE +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_agent/__main__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_changelog/0.2.0.toml +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_changelog/0.3.0.toml +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_changelog/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_errorcodes/__main__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/asgi.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/celery.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/config/wsgi.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/.dockerignore +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/.jscpd.json +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/public/favicon.svg +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/main.tsx +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/src/vite-env.d.ts +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/frontend/tsconfig.json +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/manage.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/_templates/project/{{cookiecutter.project_slug}}/tests/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/brand.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/commands/mcp.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/config.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/environment.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/history.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/changelog.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/codemod.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/legacy_agent_files.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/transforms/rename-export.cjs +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v0_2/__init__.py +0 -0
- {karni_cli-0.3.1/tests → karni_cli-0.5.0/karni_cli/upgrades/v0_5}/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/__init__.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/all_objects_to_without.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/all_with_deleted_to_without.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/deleted_only_to_without_dead.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/object_permission_classes_to_access.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/related_lookups_to_optimize.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/scoped_related_lookups_to_optimize.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/karni_cli/upgrades/v1_0/soft_delete_manager_mixin_to_scoped.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/fixtures/schema.fixture.json +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/fixtures/upgrade_changelog/0.9.0.toml +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_brand.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_docs_tutorial.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_project.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_upgrade_codemods.py +0 -0
- {karni_cli-0.3.1 → karni_cli-0.5.0}/tests/test_upgrade_typescript.py +0 -0
|
@@ -19,6 +19,9 @@ packages/karni-cli/karni_cli/_templates/
|
|
|
19
19
|
packages/karni-cli/karni_cli/_agent/
|
|
20
20
|
packages/karni-cli/karni_cli/_changelog/
|
|
21
21
|
packages/karni-cli/karni_cli/_errorcodes/
|
|
22
|
+
packages/karni-cli/karni_cli/_settings/
|
|
23
|
+
packages/karni-cli/karni_cli/_catalog/
|
|
24
|
+
packages/karni-cli/karni_cli/_ui/
|
|
22
25
|
|
|
23
26
|
# Node
|
|
24
27
|
node_modules/
|
|
@@ -31,8 +34,11 @@ storybook-static/
|
|
|
31
34
|
!.env.example
|
|
32
35
|
.DS_Store
|
|
33
36
|
.idea/
|
|
34
|
-
.claude/scheduled_tasks.lock
|
|
35
|
-
.claude/settings.local.json
|
|
36
37
|
|
|
37
38
|
# MkDocs build output
|
|
38
39
|
site/
|
|
40
|
+
.github/ci/prod_e2e/test-results/
|
|
41
|
+
|
|
42
|
+
# Contributors' own agent working files stay on their machines
|
|
43
|
+
/CLAUDE.md
|
|
44
|
+
/.claude/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: karni-cli
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: The karni command
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: The karni command: scaffold, generate, run and upgrade Karni projects. Karni is an open-source Django + React framework for building with AI coding agents. Your agent writes only your domain. The API, admin, permissions and React screens come from a package you upgrade, not code it rewrites in each project. One rule set covers every coding agent. The build fails when an agent hand-writes what Karni ships.
|
|
5
5
|
Project-URL: Homepage, https://github.com/cbsshekhawat18-lab/karni
|
|
6
6
|
Project-URL: Documentation, https://cbsshekhawat18-lab.github.io/karni/
|
|
7
7
|
Project-URL: Repository, https://github.com/cbsshekhawat18-lab/karni
|
|
@@ -10,7 +10,7 @@ Project-URL: Changelog, https://github.com/cbsshekhawat18-lab/karni/tree/main/do
|
|
|
10
10
|
Author-email: Chandrabhan Shekhawat <cbsshekhawat18@gmail.com>
|
|
11
11
|
License-Expression: Apache-2.0
|
|
12
12
|
License-File: LICENSE
|
|
13
|
-
Keywords: ai-agents,
|
|
13
|
+
Keywords: ai-agents,cli,code-generation,cookiecutter,django,mcp,project-template,react,scaffolding
|
|
14
14
|
Classifier: Development Status :: 3 - Alpha
|
|
15
15
|
Classifier: Environment :: Console
|
|
16
16
|
Classifier: Framework :: Django
|
|
@@ -29,6 +29,7 @@ Requires-Python: >=3.12
|
|
|
29
29
|
Requires-Dist: cookiecutter>=2.5
|
|
30
30
|
Requires-Dist: libcst>=1.4
|
|
31
31
|
Requires-Dist: packaging>=24.0
|
|
32
|
+
Requires-Dist: pydantic>=2
|
|
32
33
|
Requires-Dist: pyyaml>=6.0
|
|
33
34
|
Requires-Dist: tomlkit>=0.12
|
|
34
35
|
Requires-Dist: typer>=0.12
|
|
@@ -38,66 +39,109 @@ Description-Content-Type: text/markdown
|
|
|
38
39
|
|
|
39
40
|
# karni-cli
|
|
40
41
|
|
|
41
|
-
The
|
|
42
|
-
|
|
42
|
+
The karni command: scaffold, generate, run and upgrade Karni projects.
|
|
43
|
+
|
|
44
|
+
[](https://pypi.org/project/karni-cli/) [](https://pypi.org/project/karni-cli/) [](https://github.com/cbsshekhawat18-lab/karni/blob/main/LICENSE) [](https://cbsshekhawat18-lab.github.io/karni/cli/)
|
|
45
|
+
|
|
46
|
+
It runs a project's own `manage.py` as a subprocess, so the CLI itself never imports Django. Karni's Python core is [`karni`](https://pypi.org/project/karni/) and its React side [`@karni/ui`](https://www.npmjs.com/package/@karni/ui).
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
pip install karni-cli
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## A minimal example
|
|
55
|
+
|
|
56
|
+
The shop recipe, built on SQLite with no Docker:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
60
|
+
pip install karni karni-cli karni-payments pytest pytest-django
|
|
61
|
+
karni new "Corner Shop" --recipe shop && cd corner_shop
|
|
62
|
+
printf 'DATABASE_URL=sqlite:///data/db.sqlite3\nKARNI_CACHE=locmem\n' > .env
|
|
63
|
+
karni build
|
|
64
|
+
karni serve --local
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`karni build` runs the migrations, seeds demo data, generates the TypeScript types, and runs the tests and `karni check`. The [quickstart](https://cbsshekhawat18-lab.github.io/karni/quickstart/) does the same on PostgreSQL.
|
|
68
|
+
|
|
69
|
+
## Main features
|
|
70
|
+
|
|
71
|
+
- **Start a project.** `karni new` scaffolds a site, an app or both, blank or from one of six [recipes](https://cbsshekhawat18-lab.github.io/karni/recipes/).
|
|
72
|
+
- **Build from a spec.** `karni spec validate`, `karni plan` and `karni build` turn `karni.yaml` into code ([the app spec](https://cbsshekhawat18-lab.github.io/karni/app-spec/)).
|
|
73
|
+
- **Generate.** `karni make app`, `model`, `page`, `schedule`, `task`, `site` and `form` write the files a project owns.
|
|
74
|
+
- **Modules.** `karni add` and `karni remove` wire a module in and out, and `karni modules` lists the catalog.
|
|
75
|
+
- **Run and check.** `karni serve`, `seed`, `migrate`, `test`, `types` and `check`, the last one failing the build when code rebuilds what Karni ships.
|
|
76
|
+
- **For coding agents.** `karni context`, `karni rules`, the procedures in AGENTS.md and `karni mcp`, the MCP server ([Karni for coding agents](https://cbsshekhawat18-lab.github.io/karni/agents/)).
|
|
77
|
+
- **Debugging.** `karni why`, `karni explain`, `karni trace`, `karni replay` and `karni queries` ([debugging](https://cbsshekhawat18-lab.github.io/karni/debugging/why/)).
|
|
78
|
+
- **Upgrades.** `karni upgrade` applies each release's codemods and lists what it could not change.
|
|
79
|
+
|
|
80
|
+
Every command and option is in [the karni command](https://cbsshekhawat18-lab.github.io/karni/cli/). A short list follows.
|
|
43
81
|
|
|
44
82
|
## Commands
|
|
45
|
-
- `karni new <name
|
|
46
|
-
template
|
|
47
|
-
`KARNI_TEMPLATES`
|
|
48
|
-
- `karni add <module
|
|
83
|
+
- `karni new <name>`: scaffold a project from the bundled cookiecutter
|
|
84
|
+
template. Monorepo checkouts use the live `templates/project`, and
|
|
85
|
+
`KARNI_TEMPLATES` overrides it.
|
|
86
|
+
- `karni add <module>`: add `karni-<module>` to `[project].dependencies` and
|
|
49
87
|
wire `karni_<module>` into the `# karni:apps` block in config/settings.py.
|
|
50
|
-
Only that marker block is managed
|
|
88
|
+
Only that marker block is managed. Any other layout gets a clear error, and
|
|
51
89
|
you edit settings manually.
|
|
52
90
|
Once the module is installed it also records the module's
|
|
53
91
|
`AGENTS.fragment.md` as `.karni/modules/<module>.md` and refreshes the agent
|
|
54
92
|
adapters.
|
|
55
|
-
- `karni types
|
|
93
|
+
- `karni types`: dump the OpenAPI schema (`manage.py spectacular`), generate
|
|
56
94
|
`types.ts` (openapi-typescript, project-pinned binary preferred, else
|
|
57
95
|
`npx openapi-typescript@^7`) and typed hooks (`hooks.ts`) over @karni/ui.
|
|
58
|
-
- `karni
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
96
|
+
- `karni ui detect`: map the frontend's design system (shadcn/ui, a Tailwind
|
|
97
|
+
theme, Material UI, Chakra UI or Mantine) onto @karni/ui's `--karni-*`
|
|
98
|
+
tokens in `karni-theme.css`, plus `karni-primitives.tsx` for shadcn/ui.
|
|
99
|
+
`--dry-run` previews, `--json` reports for agents, and edited files are kept
|
|
100
|
+
unless `--force`.
|
|
101
|
+
- `karni context`: a compact machine-readable inventory (< 200 tokens for a
|
|
102
|
+
typical project). APPS (from the `# karni:apps` block) and PAGES (from
|
|
103
|
+
`frontend/src/pages/`) are read statically, MODELS/VIEWSETS come from `manage.py karni_context`,
|
|
104
|
+
and COMPONENTS/HOOKS from @karni/ui's build-generated `dist/manifest.json`.
|
|
105
|
+
Those two are omitted when the manifest is absent. Run `npm i @karni/ui` in
|
|
106
|
+
`frontend/` on the host to enable them, or override with `--manifest PATH`.
|
|
107
|
+
Nothing is hand-maintained.
|
|
108
|
+
- `karni context --with-history [PATH]`: the same inventory plus a
|
|
65
109
|
`HISTORY:` brief of what was already asked and decided about PATH (without
|
|
66
110
|
PATH: the project's recorded decisions) from any history provider that
|
|
67
111
|
detects a store, e.g. Gigai Chronicle's `.chronicle/`. Capped at ~300
|
|
68
112
|
tokens (characters ÷ 4), cut at line boundaries with a last line naming the
|
|
69
113
|
full-brief command. With no store the output is exactly `karni context`'s.
|
|
70
114
|
See `docs/concepts/history-providers.md`.
|
|
71
|
-
- `karni check [-q]
|
|
115
|
+
- `karni check [-q]`: Django system checks plus `karni.checks` entry-point hooks
|
|
72
116
|
(the architecture-test extension surface). A clean run outside CI may end
|
|
73
|
-
with one tip on stderr, at most once per project
|
|
74
|
-
- `karni doctor [-q]
|
|
75
|
-
interpreter (`.venv` / compose service), Node/npm, the @karni/ui
|
|
76
|
-
adapter freshness
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
|
|
117
|
+
with one tip on stderr, at most once per project. `-q` suppresses it.
|
|
118
|
+
- `karni doctor [-q]`: a human-readable environment report covering the
|
|
119
|
+
project, interpreter (`.venv` / compose service), Node/npm, the @karni/ui
|
|
120
|
+
manifest, adapter freshness and history providers. It may end with the same
|
|
121
|
+
one-time tip.
|
|
122
|
+
- `karni config get|set|list [--global] KEY [VALUE]`: settings
|
|
123
|
+
(`suggest_tools`), kept in `.karni/config.toml` in the project (committed) or
|
|
124
|
+
in `$XDG_CONFIG_HOME/karni/config.toml` with `--global`. The project wins.
|
|
80
125
|
Machine-local state (e.g. "tip shown") lives in the self-ignoring
|
|
81
126
|
`.karni/local/`.
|
|
82
|
-
- `karni rules [--explain CODE | --procedure NAME | --check FILE... | --json]
|
|
83
|
-
|
|
127
|
+
- `karni rules [--explain CODE | --procedure NAME | --check FILE... | --json]`:
|
|
128
|
+
Karni's conventions from `karni.agent.rules` (no Django needed), and
|
|
84
129
|
static single-file checks (exit 1 on violations).
|
|
85
|
-
- `karni rules sync [--check] [--force]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
- `karni mcp` — context, rules and check as MCP tools
|
|
130
|
+
- `karni rules sync [--check] [--force]`: regenerate AGENTS.md, the agent
|
|
131
|
+
instructions with the procedures for routine tasks, from
|
|
132
|
+
`karni_cli/agent_adapters.toml`. `--check` is the CI staleness gate.
|
|
133
|
+
- `karni mcp`: context, rules and check as MCP tools
|
|
90
134
|
(`pip install 'karni-cli[mcp]'`).
|
|
91
135
|
- `karni upgrade [--to VERSION] [--from VERSION] [--dry-run] [--allow-dirty] [--list]`
|
|
92
136
|
moves the project across Karni versions. It reads the karni installed in
|
|
93
137
|
the project (`--from` overrides), takes every breaking change between that
|
|
94
138
|
and `--to` from Karni's machine-readable changelog
|
|
95
139
|
(`packages/karni/karni/changelog/*.toml`, bundled into karni-cli), and runs
|
|
96
|
-
their codemods in release order. Python codemods use libcst
|
|
97
|
-
codemods use a pinned jscodeshift through `npx
|
|
98
|
-
|
|
140
|
+
their codemods in release order. Python codemods use libcst. TypeScript
|
|
141
|
+
codemods use a pinned jscodeshift through `npx`, and without Node.js they
|
|
142
|
+
are skipped with the reason. The codemods run on a scratch copy, and the result
|
|
99
143
|
is written back all at once, or not at all if one fails. `--dry-run` prints
|
|
100
|
-
a unified diff and writes nothing. Writing needs a clean git tree
|
|
144
|
+
a unified diff and writes nothing. Writing needs a clean git tree.
|
|
101
145
|
`--allow-dirty` overrides that, and is also required outside git. The
|
|
102
146
|
report lists what was applied (each file and its rewrite count), what could
|
|
103
147
|
not be fixed automatically (the sites found, with each migration-note link)
|
|
@@ -110,7 +154,7 @@ See `docs/agents.md` for the agent surface in full.
|
|
|
110
154
|
Artisan-style shortcuts. Each runner runs one project command through the
|
|
111
155
|
project interpreter (see *Execution environment* below), streams its output
|
|
112
156
|
and exits with its exit code. `--help` on each names the command it wraps.
|
|
113
|
-
Extra arguments pass straight through
|
|
157
|
+
Extra arguments pass straight through. Put `--` before any that clash with
|
|
114
158
|
karni's own options (`--docker`, `--service`, `--help`).
|
|
115
159
|
|
|
116
160
|
| Command | Runs |
|
|
@@ -138,25 +182,25 @@ With the compose stack up, `worker` and `beat` already run as services, so
|
|
|
138
182
|
## Generators
|
|
139
183
|
`karni make <type>` writes the project code a task needs, so neither a person
|
|
140
184
|
nor an AI agent hand-creates a file a generator makes. `karni make --list`
|
|
141
|
-
prints them all
|
|
185
|
+
prints them all. Each one is also available as a hidden Laravel-style alias,
|
|
142
186
|
`karni make:<type>`. The full reference (every option, the field DSL) is
|
|
143
187
|
[docs/cli.md](https://cbsshekhawat18-lab.github.io/karni/cli/), generated from this CLI.
|
|
144
188
|
|
|
145
189
|
| Command | Writes |
|
|
146
190
|
|---|---|
|
|
147
|
-
| `karni make app NAME` | `NAME/{__init__,apps,models,viewsets}.py`, `migrations/`, `tests
|
|
148
|
-
| `karni make model NAME [FIELD...]` | `class NAME(BaseModel)` in `<app>/models.py
|
|
191
|
+
| `karni make app NAME` | `NAME/{__init__,apps,models,viewsets}.py`, `migrations/`, `tests/`, and wires `# karni:apps` |
|
|
192
|
+
| `karni make model NAME [FIELD...]` | `class NAME(BaseModel)` in `<app>/models.py`, with `--with viewset,page` / `-a` chains and `--migrate` |
|
|
149
193
|
| `karni make viewset MODEL` | `<Model>ViewSet` with its `access` (`--access authenticated\|public-read\|owned:<field>\|staff\|role:<name>`), `--search` |
|
|
150
194
|
| `karni make serializer MODEL --reason ...` | `<app>/serializers.py` + `serializer_class` on the viewset |
|
|
151
195
|
| `karni make migration [NAME]` | runs `manage.py makemigrations [--app] [--name] [--empty]` through the project interpreter |
|
|
152
196
|
| `karni make task NAME` | `@shared_task` in `<app>/tasks.py` (`--retry N`) |
|
|
153
197
|
| `karni make schedule NAME` | `every(...)`/`cron(...)` in `<app>/schedules.py` (`--every 15m` / `--cron "0 3 * * *"`, `--task`) |
|
|
154
198
|
| `karni make event NAME` | a `Signal` in `<app>/events.py` |
|
|
155
|
-
| `karni make listener NAME --on ...` | `<app>/listeners.py`: `Model.created\|updated\|deleted` or a custom event
|
|
199
|
+
| `karni make listener NAME --on ...` | `<app>/listeners.py`: `Model.created\|updated\|deleted` or a custom event, with `--queued` |
|
|
156
200
|
| `karni make command NAME` | `<app>/management/commands/NAME.py` |
|
|
157
201
|
| `karni make service NAME` | `<app>/services/NAME.py` (where HTTP clients are allowed) |
|
|
158
202
|
| `karni make middleware NAME` | `<app>/middleware.py`, wired through `# karni:middleware` |
|
|
159
|
-
| `karni make page NAME` | `frontend/src/pages/NAME.tsx` (≤ 50 lines
|
|
203
|
+
| `karni make page NAME` | `frontend/src/pages/NAME.tsx` (≤ 50 lines, `--resource R --kind list\|detail\|form`), route in `frontend/src/routes.tsx` |
|
|
160
204
|
| `karni make component NAME` | `frontend/src/components/NAME.tsx` claiming a role (`--role`) |
|
|
161
205
|
| `karni make module NAME` | `modules/karni-NAME/` per docs/modules.md |
|
|
162
206
|
|
|
@@ -169,23 +213,33 @@ karni make listener notify_organizer --on Event.created --queued
|
|
|
169
213
|
karni make schedule nightly-report --cron "0 3 * * *"
|
|
170
214
|
```
|
|
171
215
|
|
|
172
|
-
Every generator
|
|
173
|
-
files and diff and writes nothing
|
|
174
|
-
notes (the chosen `access`, the route,
|
|
175
|
-
from `--app` or the project's only
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
pages parse and stay within
|
|
180
|
-
every type into a fresh scaffold
|
|
181
|
-
frontend's ESLint config when
|
|
182
|
-
installed `frontend/node_modules`)
|
|
183
|
-
(makemigrations, migrate, check,
|
|
216
|
+
Every generator follows the same rules. It never overwrites without
|
|
217
|
+
`--force`, and `--dry-run` prints the files and diff and writes nothing. It
|
|
218
|
+
prints each created/modified file plus notes (the chosen `access`, the route,
|
|
219
|
+
the next command). It resolves the app from `--app` or the project's only
|
|
220
|
+
local app. It edits existing files only through marker comments or
|
|
221
|
+
AST-located appends, and an unfamiliar layout is an error naming the manual
|
|
222
|
+
step. It never imports Django. Generated Python is clean under ruff (lint and
|
|
223
|
+
format) and `karni rules --check`, and generated pages parse and stay within
|
|
224
|
+
50 lines. `tests/test_make_gate.py` generates every type into a fresh scaffold
|
|
225
|
+
and asserts this (plus `tsc` and the frontend's ESLint config when
|
|
226
|
+
`KARNI_TEST_NODE_MODULES` points at an installed `frontend/node_modules`).
|
|
227
|
+
Then it runs the generated backend for real (makemigrations, migrate, check,
|
|
228
|
+
requests through the Django test client).
|
|
184
229
|
|
|
185
230
|
Quote fields that end in `?` in zsh (`'venue:fk:Venue?'`) and choice values
|
|
186
231
|
joined by `|`.
|
|
187
232
|
|
|
188
233
|
## Execution environment
|
|
189
234
|
Commands that run the project resolve, in order: `--docker/--no-docker` flag →
|
|
190
|
-
`<project>/.venv` → a running compose service (default `django
|
|
235
|
+
`<project>/.venv` → a running compose service (default `django`, changed with
|
|
191
236
|
`--service` or `KARNI_COMPOSE_SERVICE`) → an error naming both remedies.
|
|
237
|
+
|
|
238
|
+
## Links
|
|
239
|
+
|
|
240
|
+
- The karni command: <https://cbsshekhawat18-lab.github.io/karni/cli/>
|
|
241
|
+
- Quickstart: <https://cbsshekhawat18-lab.github.io/karni/quickstart/>
|
|
242
|
+
- Karni, the framework this package is part of: <https://github.com/cbsshekhawat18-lab/karni>
|
|
243
|
+
- Changelog: <https://github.com/cbsshekhawat18-lab/karni/blob/main/CHANGELOG.md>
|
|
244
|
+
- Issues: <https://github.com/cbsshekhawat18-lab/karni/issues>
|
|
245
|
+
- License: Apache-2.0. karni-cli is released with every other Karni package, at one version.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# karni-cli
|
|
2
|
+
|
|
3
|
+
The karni command: scaffold, generate, run and upgrade Karni projects.
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/karni-cli/) [](https://pypi.org/project/karni-cli/) [](https://github.com/cbsshekhawat18-lab/karni/blob/main/LICENSE) [](https://cbsshekhawat18-lab.github.io/karni/cli/)
|
|
6
|
+
|
|
7
|
+
It runs a project's own `manage.py` as a subprocess, so the CLI itself never imports Django. Karni's Python core is [`karni`](https://pypi.org/project/karni/) and its React side [`@karni/ui`](https://www.npmjs.com/package/@karni/ui).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pip install karni-cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## A minimal example
|
|
16
|
+
|
|
17
|
+
The shop recipe, built on SQLite with no Docker:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
21
|
+
pip install karni karni-cli karni-payments pytest pytest-django
|
|
22
|
+
karni new "Corner Shop" --recipe shop && cd corner_shop
|
|
23
|
+
printf 'DATABASE_URL=sqlite:///data/db.sqlite3\nKARNI_CACHE=locmem\n' > .env
|
|
24
|
+
karni build
|
|
25
|
+
karni serve --local
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`karni build` runs the migrations, seeds demo data, generates the TypeScript types, and runs the tests and `karni check`. The [quickstart](https://cbsshekhawat18-lab.github.io/karni/quickstart/) does the same on PostgreSQL.
|
|
29
|
+
|
|
30
|
+
## Main features
|
|
31
|
+
|
|
32
|
+
- **Start a project.** `karni new` scaffolds a site, an app or both, blank or from one of six [recipes](https://cbsshekhawat18-lab.github.io/karni/recipes/).
|
|
33
|
+
- **Build from a spec.** `karni spec validate`, `karni plan` and `karni build` turn `karni.yaml` into code ([the app spec](https://cbsshekhawat18-lab.github.io/karni/app-spec/)).
|
|
34
|
+
- **Generate.** `karni make app`, `model`, `page`, `schedule`, `task`, `site` and `form` write the files a project owns.
|
|
35
|
+
- **Modules.** `karni add` and `karni remove` wire a module in and out, and `karni modules` lists the catalog.
|
|
36
|
+
- **Run and check.** `karni serve`, `seed`, `migrate`, `test`, `types` and `check`, the last one failing the build when code rebuilds what Karni ships.
|
|
37
|
+
- **For coding agents.** `karni context`, `karni rules`, the procedures in AGENTS.md and `karni mcp`, the MCP server ([Karni for coding agents](https://cbsshekhawat18-lab.github.io/karni/agents/)).
|
|
38
|
+
- **Debugging.** `karni why`, `karni explain`, `karni trace`, `karni replay` and `karni queries` ([debugging](https://cbsshekhawat18-lab.github.io/karni/debugging/why/)).
|
|
39
|
+
- **Upgrades.** `karni upgrade` applies each release's codemods and lists what it could not change.
|
|
40
|
+
|
|
41
|
+
Every command and option is in [the karni command](https://cbsshekhawat18-lab.github.io/karni/cli/). A short list follows.
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
- `karni new <name>`: scaffold a project from the bundled cookiecutter
|
|
45
|
+
template. Monorepo checkouts use the live `templates/project`, and
|
|
46
|
+
`KARNI_TEMPLATES` overrides it.
|
|
47
|
+
- `karni add <module>`: add `karni-<module>` to `[project].dependencies` and
|
|
48
|
+
wire `karni_<module>` into the `# karni:apps` block in config/settings.py.
|
|
49
|
+
Only that marker block is managed. Any other layout gets a clear error, and
|
|
50
|
+
you edit settings manually.
|
|
51
|
+
Once the module is installed it also records the module's
|
|
52
|
+
`AGENTS.fragment.md` as `.karni/modules/<module>.md` and refreshes the agent
|
|
53
|
+
adapters.
|
|
54
|
+
- `karni types`: dump the OpenAPI schema (`manage.py spectacular`), generate
|
|
55
|
+
`types.ts` (openapi-typescript, project-pinned binary preferred, else
|
|
56
|
+
`npx openapi-typescript@^7`) and typed hooks (`hooks.ts`) over @karni/ui.
|
|
57
|
+
- `karni ui detect`: map the frontend's design system (shadcn/ui, a Tailwind
|
|
58
|
+
theme, Material UI, Chakra UI or Mantine) onto @karni/ui's `--karni-*`
|
|
59
|
+
tokens in `karni-theme.css`, plus `karni-primitives.tsx` for shadcn/ui.
|
|
60
|
+
`--dry-run` previews, `--json` reports for agents, and edited files are kept
|
|
61
|
+
unless `--force`.
|
|
62
|
+
- `karni context`: a compact machine-readable inventory (< 200 tokens for a
|
|
63
|
+
typical project). APPS (from the `# karni:apps` block) and PAGES (from
|
|
64
|
+
`frontend/src/pages/`) are read statically, MODELS/VIEWSETS come from `manage.py karni_context`,
|
|
65
|
+
and COMPONENTS/HOOKS from @karni/ui's build-generated `dist/manifest.json`.
|
|
66
|
+
Those two are omitted when the manifest is absent. Run `npm i @karni/ui` in
|
|
67
|
+
`frontend/` on the host to enable them, or override with `--manifest PATH`.
|
|
68
|
+
Nothing is hand-maintained.
|
|
69
|
+
- `karni context --with-history [PATH]`: the same inventory plus a
|
|
70
|
+
`HISTORY:` brief of what was already asked and decided about PATH (without
|
|
71
|
+
PATH: the project's recorded decisions) from any history provider that
|
|
72
|
+
detects a store, e.g. Gigai Chronicle's `.chronicle/`. Capped at ~300
|
|
73
|
+
tokens (characters ÷ 4), cut at line boundaries with a last line naming the
|
|
74
|
+
full-brief command. With no store the output is exactly `karni context`'s.
|
|
75
|
+
See `docs/concepts/history-providers.md`.
|
|
76
|
+
- `karni check [-q]`: Django system checks plus `karni.checks` entry-point hooks
|
|
77
|
+
(the architecture-test extension surface). A clean run outside CI may end
|
|
78
|
+
with one tip on stderr, at most once per project. `-q` suppresses it.
|
|
79
|
+
- `karni doctor [-q]`: a human-readable environment report covering the
|
|
80
|
+
project, interpreter (`.venv` / compose service), Node/npm, the @karni/ui
|
|
81
|
+
manifest, adapter freshness and history providers. It may end with the same
|
|
82
|
+
one-time tip.
|
|
83
|
+
- `karni config get|set|list [--global] KEY [VALUE]`: settings
|
|
84
|
+
(`suggest_tools`), kept in `.karni/config.toml` in the project (committed) or
|
|
85
|
+
in `$XDG_CONFIG_HOME/karni/config.toml` with `--global`. The project wins.
|
|
86
|
+
Machine-local state (e.g. "tip shown") lives in the self-ignoring
|
|
87
|
+
`.karni/local/`.
|
|
88
|
+
- `karni rules [--explain CODE | --procedure NAME | --check FILE... | --json]`:
|
|
89
|
+
Karni's conventions from `karni.agent.rules` (no Django needed), and
|
|
90
|
+
static single-file checks (exit 1 on violations).
|
|
91
|
+
- `karni rules sync [--check] [--force]`: regenerate AGENTS.md, the agent
|
|
92
|
+
instructions with the procedures for routine tasks, from
|
|
93
|
+
`karni_cli/agent_adapters.toml`. `--check` is the CI staleness gate.
|
|
94
|
+
- `karni mcp`: context, rules and check as MCP tools
|
|
95
|
+
(`pip install 'karni-cli[mcp]'`).
|
|
96
|
+
- `karni upgrade [--to VERSION] [--from VERSION] [--dry-run] [--allow-dirty] [--list]`
|
|
97
|
+
moves the project across Karni versions. It reads the karni installed in
|
|
98
|
+
the project (`--from` overrides), takes every breaking change between that
|
|
99
|
+
and `--to` from Karni's machine-readable changelog
|
|
100
|
+
(`packages/karni/karni/changelog/*.toml`, bundled into karni-cli), and runs
|
|
101
|
+
their codemods in release order. Python codemods use libcst. TypeScript
|
|
102
|
+
codemods use a pinned jscodeshift through `npx`, and without Node.js they
|
|
103
|
+
are skipped with the reason. The codemods run on a scratch copy, and the result
|
|
104
|
+
is written back all at once, or not at all if one fails. `--dry-run` prints
|
|
105
|
+
a unified diff and writes nothing. Writing needs a clean git tree.
|
|
106
|
+
`--allow-dirty` overrides that, and is also required outside git. The
|
|
107
|
+
report lists what was applied (each file and its rewrite count), what could
|
|
108
|
+
not be fixed automatically (the sites found, with each migration-note link)
|
|
109
|
+
and what was skipped. Run it before you raise the karni pin. See
|
|
110
|
+
`docs/migrations/`.
|
|
111
|
+
|
|
112
|
+
See `docs/agents.md` for the agent surface in full.
|
|
113
|
+
|
|
114
|
+
## Runners
|
|
115
|
+
Artisan-style shortcuts. Each runner runs one project command through the
|
|
116
|
+
project interpreter (see *Execution environment* below), streams its output
|
|
117
|
+
and exits with its exit code. `--help` on each names the command it wraps.
|
|
118
|
+
Extra arguments pass straight through. Put `--` before any that clash with
|
|
119
|
+
karni's own options (`--docker`, `--service`, `--help`).
|
|
120
|
+
|
|
121
|
+
| Command | Runs |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `karni serve` | `docker compose up` (`--build`, `-d`) |
|
|
124
|
+
| `karni serve --local [--host H] [--port P]` | `manage.py runserver 127.0.0.1:8000` via `.venv` |
|
|
125
|
+
| `karni migrate [ARGS]` | `manage.py migrate [ARGS]` |
|
|
126
|
+
| `karni test [ARGS]` | `python -m pytest [ARGS]` |
|
|
127
|
+
| `karni shell [ARGS]` | `manage.py shell [ARGS]` |
|
|
128
|
+
| `karni routes [--json]` | `manage.py karni_routes`: every URL with methods, name, view, model, access |
|
|
129
|
+
| `karni worker [-A APP] [-l LEVEL] [ARGS]` | `python -m celery -A config worker -l info [ARGS]` |
|
|
130
|
+
| `karni beat [-A APP] [-l LEVEL] [ARGS]` | `python -m celery -A config beat -l info [ARGS]` |
|
|
131
|
+
| `karni schedule list [--json]` | `manage.py karni_schedules`: every merged beat schedule |
|
|
132
|
+
| `karni schedule run NAME` | `manage.py karni_schedules --run NAME`: runs the task once, synchronously |
|
|
133
|
+
| `karni createsuperuser [ARGS]` | `manage.py createsuperuser [ARGS]` |
|
|
134
|
+
| `karni manage ARGS` | `manage.py ARGS`: the raw passthrough for everything else |
|
|
135
|
+
|
|
136
|
+
In docker mode, `shell`, `test`, `worker`, `beat`, `createsuperuser` and
|
|
137
|
+
`manage` get a TTY (`docker compose exec` without `-T`) when karni runs in a
|
|
138
|
+
terminal, so prompts and Ctrl-C work. Scripted and agent runs keep `-T`.
|
|
139
|
+
With the compose stack up, `worker` and `beat` already run as services, so
|
|
140
|
+
`karni worker` and `karni beat` are for `.venv` development. See
|
|
141
|
+
`docs/events.md` and `docs/scheduling.md`.
|
|
142
|
+
|
|
143
|
+
## Generators
|
|
144
|
+
`karni make <type>` writes the project code a task needs, so neither a person
|
|
145
|
+
nor an AI agent hand-creates a file a generator makes. `karni make --list`
|
|
146
|
+
prints them all. Each one is also available as a hidden Laravel-style alias,
|
|
147
|
+
`karni make:<type>`. The full reference (every option, the field DSL) is
|
|
148
|
+
[docs/cli.md](https://cbsshekhawat18-lab.github.io/karni/cli/), generated from this CLI.
|
|
149
|
+
|
|
150
|
+
| Command | Writes |
|
|
151
|
+
|---|---|
|
|
152
|
+
| `karni make app NAME` | `NAME/{__init__,apps,models,viewsets}.py`, `migrations/`, `tests/`, and wires `# karni:apps` |
|
|
153
|
+
| `karni make model NAME [FIELD...]` | `class NAME(BaseModel)` in `<app>/models.py`, with `--with viewset,page` / `-a` chains and `--migrate` |
|
|
154
|
+
| `karni make viewset MODEL` | `<Model>ViewSet` with its `access` (`--access authenticated\|public-read\|owned:<field>\|staff\|role:<name>`), `--search` |
|
|
155
|
+
| `karni make serializer MODEL --reason ...` | `<app>/serializers.py` + `serializer_class` on the viewset |
|
|
156
|
+
| `karni make migration [NAME]` | runs `manage.py makemigrations [--app] [--name] [--empty]` through the project interpreter |
|
|
157
|
+
| `karni make task NAME` | `@shared_task` in `<app>/tasks.py` (`--retry N`) |
|
|
158
|
+
| `karni make schedule NAME` | `every(...)`/`cron(...)` in `<app>/schedules.py` (`--every 15m` / `--cron "0 3 * * *"`, `--task`) |
|
|
159
|
+
| `karni make event NAME` | a `Signal` in `<app>/events.py` |
|
|
160
|
+
| `karni make listener NAME --on ...` | `<app>/listeners.py`: `Model.created\|updated\|deleted` or a custom event, with `--queued` |
|
|
161
|
+
| `karni make command NAME` | `<app>/management/commands/NAME.py` |
|
|
162
|
+
| `karni make service NAME` | `<app>/services/NAME.py` (where HTTP clients are allowed) |
|
|
163
|
+
| `karni make middleware NAME` | `<app>/middleware.py`, wired through `# karni:middleware` |
|
|
164
|
+
| `karni make page NAME` | `frontend/src/pages/NAME.tsx` (≤ 50 lines, `--resource R --kind list\|detail\|form`), route in `frontend/src/routes.tsx` |
|
|
165
|
+
| `karni make component NAME` | `frontend/src/components/NAME.tsx` claiming a role (`--role`) |
|
|
166
|
+
| `karni make module NAME` | `modules/karni-NAME/` per docs/modules.md |
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
karni make app events
|
|
170
|
+
karni make model Event title:str:200 starts_at:datetime "status:choice:draft|live" \
|
|
171
|
+
organizer:fk:User 'venue:fk:Venue?' -a --access owned:organizer --search title
|
|
172
|
+
karni make migration && karni migrate
|
|
173
|
+
karni make listener notify_organizer --on Event.created --queued
|
|
174
|
+
karni make schedule nightly-report --cron "0 3 * * *"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Every generator follows the same rules. It never overwrites without
|
|
178
|
+
`--force`, and `--dry-run` prints the files and diff and writes nothing. It
|
|
179
|
+
prints each created/modified file plus notes (the chosen `access`, the route,
|
|
180
|
+
the next command). It resolves the app from `--app` or the project's only
|
|
181
|
+
local app. It edits existing files only through marker comments or
|
|
182
|
+
AST-located appends, and an unfamiliar layout is an error naming the manual
|
|
183
|
+
step. It never imports Django. Generated Python is clean under ruff (lint and
|
|
184
|
+
format) and `karni rules --check`, and generated pages parse and stay within
|
|
185
|
+
50 lines. `tests/test_make_gate.py` generates every type into a fresh scaffold
|
|
186
|
+
and asserts this (plus `tsc` and the frontend's ESLint config when
|
|
187
|
+
`KARNI_TEST_NODE_MODULES` points at an installed `frontend/node_modules`).
|
|
188
|
+
Then it runs the generated backend for real (makemigrations, migrate, check,
|
|
189
|
+
requests through the Django test client).
|
|
190
|
+
|
|
191
|
+
Quote fields that end in `?` in zsh (`'venue:fk:Venue?'`) and choice values
|
|
192
|
+
joined by `|`.
|
|
193
|
+
|
|
194
|
+
## Execution environment
|
|
195
|
+
Commands that run the project resolve, in order: `--docker/--no-docker` flag →
|
|
196
|
+
`<project>/.venv` → a running compose service (default `django`, changed with
|
|
197
|
+
`--service` or `KARNI_COMPOSE_SERVICE`) → an error naming both remedies.
|
|
198
|
+
|
|
199
|
+
## Links
|
|
200
|
+
|
|
201
|
+
- The karni command: <https://cbsshekhawat18-lab.github.io/karni/cli/>
|
|
202
|
+
- Quickstart: <https://cbsshekhawat18-lab.github.io/karni/quickstart/>
|
|
203
|
+
- Karni, the framework this package is part of: <https://github.com/cbsshekhawat18-lab/karni>
|
|
204
|
+
- Changelog: <https://github.com/cbsshekhawat18-lab/karni/blob/main/CHANGELOG.md>
|
|
205
|
+
- Issues: <https://github.com/cbsshekhawat18-lab/karni/issues>
|
|
206
|
+
- License: Apache-2.0. karni-cli is released with every other Karni package, at one version.
|
|
@@ -11,7 +11,15 @@ to Karni's machine-readable changelog (packages/karni/karni/changelog ->
|
|
|
11
11
|
karni_cli/_changelog), which `karni upgrade` reads: the CLI must know every
|
|
12
12
|
change up to its own release, whatever karni the project has installed.
|
|
13
13
|
Likewise Karni's error code registry (packages/karni/karni/errorcodes ->
|
|
14
|
-
karni_cli/_errorcodes), which `karni explain` and error messages read
|
|
14
|
+
karni_cli/_errorcodes), which `karni explain` and error messages read, the
|
|
15
|
+
settings reference (packages/karni/karni/conf/reference.py and the base.py it
|
|
16
|
+
reads -> karni_cli/_settings), which `karni explain <SETTING>` reads, and
|
|
17
|
+
@karni/ui's token stylesheet (packages/karni-ui/src/styles.css ->
|
|
18
|
+
karni_cli/_ui/styles.css), whose defaults `karni ui detect` lists when a
|
|
19
|
+
project has neither @karni/ui installed nor a monorepo checkout. And the
|
|
20
|
+
module catalog (packages/karni/karni/catalog -> karni_cli/_catalog, with a
|
|
21
|
+
copy of each module's karni.module.toml under _catalog/modules/), so
|
|
22
|
+
`karni modules list` shows the modules a project has not installed.
|
|
15
23
|
"""
|
|
16
24
|
|
|
17
25
|
from __future__ import annotations
|
|
@@ -49,6 +57,15 @@ class TemplateBundleHook(BuildHookInterface):
|
|
|
49
57
|
self._bundle_karni(pkg_root, "agent", "_agent", "agent rules", build_data)
|
|
50
58
|
self._bundle_karni(pkg_root, "changelog", "_changelog", "changelog", build_data)
|
|
51
59
|
self._bundle_karni(pkg_root, "errorcodes", "_errorcodes", "error codes", build_data)
|
|
60
|
+
self._bundle_karni(pkg_root, "catalog", "_catalog", "module catalog", build_data)
|
|
61
|
+
manifests = sorted(pkg_root.parent.parent.glob("modules/*/karni_*/karni.module.toml"))
|
|
62
|
+
bundled_modules = pkg_root / "karni_cli" / "_catalog" / "modules"
|
|
63
|
+
if manifests:
|
|
64
|
+
bundled_modules.mkdir(parents=True, exist_ok=True)
|
|
65
|
+
for manifest in manifests:
|
|
66
|
+
shutil.copy2(manifest, bundled_modules / f"{manifest.parent.parent.name}.toml")
|
|
67
|
+
elif not bundled_modules.is_dir():
|
|
68
|
+
raise RuntimeError("No module manifests to bundle into karni_cli/_catalog/modules.")
|
|
52
69
|
# karni.links (every published URL, stdlib only) rides inside the
|
|
53
70
|
# errorcodes bundle: the registry loads it by path when karni is absent.
|
|
54
71
|
links = pkg_root.parent / "karni" / "karni" / "links.py"
|
|
@@ -58,6 +75,26 @@ class TemplateBundleHook(BuildHookInterface):
|
|
|
58
75
|
elif not bundled_links.is_file():
|
|
59
76
|
raise RuntimeError("No karni/links.py to bundle into karni_cli/_errorcodes.")
|
|
60
77
|
|
|
78
|
+
# The settings reference (stdlib only) and the file it reads: `karni explain <SETTING>`.
|
|
79
|
+
settings_bundle = pkg_root / "karni_cli" / "_settings"
|
|
80
|
+
conf = pkg_root.parent / "karni" / "karni" / "conf"
|
|
81
|
+
if (conf / "reference.py").is_file():
|
|
82
|
+
settings_bundle.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
for name in ("reference.py", "base.py"):
|
|
84
|
+
shutil.copy2(conf / name, settings_bundle / name)
|
|
85
|
+
elif not (settings_bundle / "reference.py").is_file():
|
|
86
|
+
raise RuntimeError("No karni/conf/reference.py to bundle into karni_cli/_settings.")
|
|
87
|
+
build_data["artifacts"].append("karni_cli/_settings/")
|
|
88
|
+
|
|
89
|
+
styles = pkg_root.parent / "karni-ui" / "src" / "styles.css"
|
|
90
|
+
bundled_styles = pkg_root / "karni_cli" / "_ui" / "styles.css"
|
|
91
|
+
if styles.is_file():
|
|
92
|
+
bundled_styles.parent.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
shutil.copy2(styles, bundled_styles)
|
|
94
|
+
elif not bundled_styles.is_file():
|
|
95
|
+
raise RuntimeError("No @karni/ui styles.css to bundle into karni_cli/_ui.")
|
|
96
|
+
build_data["artifacts"].append("karni_cli/_ui/")
|
|
97
|
+
|
|
61
98
|
@staticmethod
|
|
62
99
|
def _bundle_karni(
|
|
63
100
|
pkg_root: Path, package: str, bundle: str, what: str, build_data: dict[str, Any]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""karni-cli — the ``karni`` command."""
|
|
2
|
+
|
|
3
|
+
from importlib import metadata as _metadata
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = _metadata.version("karni-cli") # [project] version in pyproject.toml
|
|
7
|
+
except _metadata.PackageNotFoundError: # a source tree on sys.path, never installed
|
|
8
|
+
__version__ = "0+unknown"
|
|
@@ -16,7 +16,7 @@ from typing import Any
|
|
|
16
16
|
from .check import check_file, check_source, supported
|
|
17
17
|
from .history import active_conditions
|
|
18
18
|
from .overrides import OVERRIDE_FILE, OverrideError, read_overrides, resolve_rules
|
|
19
|
-
from .rules import CATEGORIES, PROCEDURES, RULES, Procedure, Rule
|
|
19
|
+
from .rules import CATEGORIES, PROCEDURES, RULES, TOPICS, Procedure, Rule, Topic
|
|
20
20
|
|
|
21
21
|
#: Bumped when the shape of :func:`dump` changes incompatibly.
|
|
22
22
|
SCHEMA_VERSION = 1
|
|
@@ -27,9 +27,11 @@ __all__ = [
|
|
|
27
27
|
"PROCEDURES",
|
|
28
28
|
"RULES",
|
|
29
29
|
"SCHEMA_VERSION",
|
|
30
|
+
"TOPICS",
|
|
30
31
|
"OverrideError",
|
|
31
32
|
"Procedure",
|
|
32
33
|
"Rule",
|
|
34
|
+
"Topic",
|
|
33
35
|
"check_file",
|
|
34
36
|
"check_paths",
|
|
35
37
|
"check_source",
|
|
@@ -64,6 +66,7 @@ def dump(root: str | Path | None = None) -> dict[str, Any]:
|
|
|
64
66
|
"categories": [c for c in categories if any(r.category == c for r in rules)],
|
|
65
67
|
"rules": [rule.to_dict() for rule in rules],
|
|
66
68
|
"procedures": [procedure.to_dict() for procedure in PROCEDURES],
|
|
69
|
+
"topics": [topic.to_dict() for topic in TOPICS],
|
|
67
70
|
"adapters": overrides.adapters,
|
|
68
71
|
"overrides_file": str(overrides.path) if overrides.path else None,
|
|
69
72
|
"conditions": sorted(conditions),
|