refactor(cli): resource-first command surface
Names collide across resource types (a program and a service can share a name),
so the CLI no longer resolves bare names. Operations live under the resource
they act on; platform lifecycle and the cross-resource overview stay top-level.
castle program list|info|create|add|clone|delete|run|install|uninstall|
build|test|lint|format|type-check|check
castle service list|info|create|delete|deploy|enable|disable|start|stop|restart|logs
castle job <same verbs> (create takes --schedule)
castle gateway start|stop|reload|status
castle list | status | deploy [name] # cross-cutting
castle start | stop | restart # whole platform (systemd verbs)
Key changes:
- info/delete/list/run are resource-scoped (no more cross-section name match).
- delete only removes the named resource's entry; program delete still blocks
when a deployment references it.
- per-resource start/stop/restart (systemctl on the unit/timer); top-level
start/stop/restart act on the whole platform.
- expose → 'service create' (more general: --program ref, --runner); gained
'job create' (the CLI never had one).
- dropped up/down — bringing things online is the honest 'deploy && start'.
Docs (CLAUDE.md, registry.md, stack guides) and user-facing messages updated.
core 94 / cli 24 / api 52 green; ruff clean. Verified live: program/service/job
list+info scope correctly, service create+scoped-delete round-trips.
This commit is contained in:
@@ -157,9 +157,9 @@ repo: https://github.com/me/widget.git
|
||||
ref: v2.1.0 # optional branch/tag/commit
|
||||
```
|
||||
|
||||
`repo` records a git URL so `castle clone` can provision the source on a fresh
|
||||
`repo` records a git URL so `castle program clone` can provision the source on a fresh
|
||||
machine. When `source:` points at an existing working copy, that takes
|
||||
precedence. Use `castle add <path|url>` to register an existing repo as a program.
|
||||
precedence. Use `castle program add <path|url>` to register an existing repo as a program.
|
||||
|
||||
### `system_dependencies` — Required system packages
|
||||
|
||||
@@ -240,7 +240,7 @@ manage:
|
||||
systemd: {}
|
||||
```
|
||||
|
||||
Enables `castle service enable/disable` and `castle logs`. An empty `{}`
|
||||
Enables `castle service enable/disable` and `castle service logs`. An empty `{}`
|
||||
uses defaults (enable=true, restart=on-failure, restart_sec=2).
|
||||
|
||||
Full options:
|
||||
@@ -292,7 +292,7 @@ semantics as services.
|
||||
Every program's source lives in one place — `~/.castle/code/<name>/`. It can
|
||||
arrive there a few ways:
|
||||
|
||||
1. **Scaffold a new one** with `castle create` — writes the project into
|
||||
1. **Scaffold a new one** with `castle program create` — writes the project into
|
||||
`~/.castle/code/<name>/` and registers it in `castle.yaml` with
|
||||
`source: code/<name>`.
|
||||
2. **Clone an existing project** — `git clone <url> ~/.castle/code/<name>`,
|
||||
@@ -310,14 +310,14 @@ inside the castle git repo and are referenced with `source: repo:<name>`.
|
||||
|
||||
## Registering a new program
|
||||
|
||||
### Via `castle create` (recommended)
|
||||
### Via `castle program create` (recommended)
|
||||
|
||||
```bash
|
||||
# Service — scaffolds into ~/.castle/code/, assigns port, registers in castle.yaml
|
||||
castle create my-service --stack python-fastapi --description "Does something"
|
||||
castle program create my-service --stack python-fastapi --description "Does something"
|
||||
|
||||
# Tool — scaffolds into ~/.castle/code/
|
||||
castle create my-tool --stack python-cli --description "Does something"
|
||||
castle program create my-tool --stack python-cli --description "Does something"
|
||||
```
|
||||
|
||||
### Manually
|
||||
@@ -363,10 +363,10 @@ services:
|
||||
### Service lifecycle
|
||||
|
||||
```bash
|
||||
castle create my-service --stack python-fastapi # 1. Scaffold + register
|
||||
castle program create my-service --stack python-fastapi # 1. Scaffold + register
|
||||
cd ~/.castle/code/my-service && uv sync # 2. Install deps
|
||||
# ... implement ...
|
||||
castle test my-service # 3. Run tests
|
||||
castle program test my-service # 3. Run tests
|
||||
castle service enable my-service # 4. Generate systemd unit, start
|
||||
castle gateway reload # 5. Update Caddy routes
|
||||
```
|
||||
@@ -376,17 +376,17 @@ on failure. Manage with:
|
||||
|
||||
```bash
|
||||
castle logs my-service -f # Tail logs
|
||||
castle run my-service # Run in foreground (for debugging)
|
||||
castle service run my-service # Run in foreground (for debugging)
|
||||
castle service disable my-service # Stop and remove systemd unit
|
||||
```
|
||||
|
||||
### Tool lifecycle
|
||||
|
||||
```bash
|
||||
castle create my-tool --stack python-cli # 1. Scaffold + register
|
||||
castle program create my-tool --stack python-cli # 1. Scaffold + register
|
||||
cd ~/.castle/code/my-tool && uv sync # 2. Install deps
|
||||
# ... implement ...
|
||||
castle test my-tool # 3. Run tests
|
||||
castle program test my-tool # 3. Run tests
|
||||
uv tool install --editable ~/.castle/code/my-tool/ # 4. Install to PATH
|
||||
```
|
||||
|
||||
@@ -406,7 +406,7 @@ jobs:
|
||||
systemd: {}
|
||||
```
|
||||
|
||||
`castle service enable my-job` generates both a `.service` (Type=oneshot)
|
||||
`castle job enable my-job` generates both a `.service` (Type=oneshot)
|
||||
and a `.timer` file.
|
||||
|
||||
## Infrastructure paths
|
||||
|
||||
Reference in New Issue
Block a user