xcorecli 2.0.0__tar.gz → 2.2.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.
- xcorecli-2.2.0/PKG-INFO +77 -0
- xcorecli-2.2.0/README.md +62 -0
- xcorecli-2.2.0/docs/commands/login.md +34 -0
- xcorecli-2.2.0/docs/getting-started/auth.md +110 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/migration/index.md +7 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/plugin/install.md +11 -0
- xcorecli-2.2.0/docs/plugin/marketplace.md +46 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/reference.md +26 -6
- xcorecli-2.2.0/docs/service/index.md +69 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/mkdocs.yml +2 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/pyproject.toml +7 -1
- {xcorecli-2.0.0 → xcorecli-2.2.0}/uv.lock +12 -1
- xcorecli-2.2.0/xcli/_login.py +80 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/config/runtime.py +62 -4
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/init/manager.py +3 -2
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/init/upgrade.py +8 -1
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/main.py +21 -1
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/migrations/cli.py +6 -5
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/migrations/runtime.py +121 -5
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/cli.py +2 -2
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/install_commands.py +144 -67
- xcorecli-2.2.0/xcli/plugin/marketplace_commands.py +158 -0
- xcorecli-2.2.0/xcli/plugin/shared.py +107 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/update_commands.py +34 -47
- xcorecli-2.2.0/xcli/service/cli.py +19 -0
- xcorecli-2.2.0/xcli/service/install_commands.py +275 -0
- xcorecli-2.2.0/xcli/service/marketplace_commands.py +101 -0
- xcorecli-2.2.0/xcli/service/shared.py +20 -0
- xcorecli-2.0.0/PKG-INFO +0 -12
- xcorecli-2.0.0/README.md +0 -0
- xcorecli-2.0.0/docs/getting-started/auth.md +0 -43
- xcorecli-2.0.0/docs/plugin/marketplace.md +0 -50
- xcorecli-2.0.0/xcli/marketplace/cli.py +0 -57
- xcorecli-2.0.0/xcli/plugin/marketplace_commands.py +0 -113
- xcorecli-2.0.0/xcli/plugin/shared.py +0 -49
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.github/workflows/publish.yml +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.gitignore +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.python-version +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.vscode/configurationCache.log +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.vscode/dryrun.log +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.vscode/settings.json +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/.vscode/targets.log +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/commands/health.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/commands/init.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/config/index.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/getting-started/configuration.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/getting-started/install.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/index.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/manager/index.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/manager/monitoring.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/manager/services.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/plugin/index.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/plugin/local.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/plugin/runtime.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/plugin/security.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/plugin/update.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/sandbox/index.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/worker/index.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/docs/worker/process.md +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/makefile +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/_credentials.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/_run.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/_xcore.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/config/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/config/cli.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/init/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/manager/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/manager/cli.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/migrations/__init__.py +0 -0
- {xcorecli-2.0.0/xcli/marketplace → xcorecli-2.2.0/xcli/plugin}/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/local_commands.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/runtime_commands.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/scaffold.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/plugin/security_commands.py +0 -0
- {xcorecli-2.0.0/xcli/plugin → xcorecli-2.2.0/xcli/sandbox}/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/sandbox/cli.py +0 -0
- {xcorecli-2.0.0/xcli/sandbox → xcorecli-2.2.0/xcli/service}/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/worker/__init__.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/worker/cli.py +0 -0
- {xcorecli-2.0.0 → xcorecli-2.2.0}/xcli/worker/worker.py +0 -0
xcorecli-2.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: xcorecli
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: CLI for xcore — configuration, plugins, monitoring
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: alembic>=1.18.0
|
|
7
|
+
Requires-Dist: httpx>=0.27
|
|
8
|
+
Requires-Dist: psutil>=5.9
|
|
9
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
10
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
11
|
+
Requires-Dist: rich>=14.3.4
|
|
12
|
+
Requires-Dist: sqlalchemy>=2.0.0
|
|
13
|
+
Requires-Dist: typer>=0.25.1
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# xcli — xcore project manager
|
|
17
|
+
|
|
18
|
+
Official CLI for the `xcore` framework: scaffold a project, manage
|
|
19
|
+
plugins (local dev, marketplace install, runtime control, signing), run
|
|
20
|
+
migrations, control the Celery worker, and monitor a running deployment.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install xcorecli
|
|
24
|
+
xcli --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Full docs: https://docs.xcorehub.dev (built from `docs/` with
|
|
28
|
+
`mkdocs-material` — `mkdocs serve` locally).
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
xcli init my-app # scaffold a new xcore project
|
|
34
|
+
cd my-app
|
|
35
|
+
pip install -r requirements.txt
|
|
36
|
+
xcli manager start --reload # run it
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Installing plugins from the marketplace
|
|
40
|
+
|
|
41
|
+
Browsing is public, no credentials needed:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
xcli plugin marketplace browse
|
|
45
|
+
xcli plugin marketplace search "auth"
|
|
46
|
+
xcli plugin marketplace info xlicense
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Installing needs two credentials — see
|
|
50
|
+
[docs/getting-started/auth.md](docs/getting-started/auth.md):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
xcli config set api-key xdk_...
|
|
54
|
+
xcli config set signing-key <your-signing-secret>
|
|
55
|
+
xcli plugin install xlicense
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Command groups
|
|
59
|
+
|
|
60
|
+
| Group | Purpose |
|
|
61
|
+
|-------|---------|
|
|
62
|
+
| `xcli init` / `xcli upgrade` | Scaffold a project / migrate `integration.yaml` to the latest schema |
|
|
63
|
+
| `xcli health` / `xcli services` | Health-check and status of all configured services |
|
|
64
|
+
| `xcli config` | Store local credentials (`api-key`, `signing-key`) |
|
|
65
|
+
| `xcli plugin` | Local dev, marketplace browse/install, runtime control, signing, updates — see `xcli plugin --help` |
|
|
66
|
+
| `xcli deploy` | Deploy plugins to remote servers |
|
|
67
|
+
| `xcli sandbox` | Inspect the plugin sandbox |
|
|
68
|
+
| `xcli worker` | Manage Celery workers |
|
|
69
|
+
| `xcli manager` | Runtime monitoring of a running instance |
|
|
70
|
+
| `xcli migration` | Alembic migrations for plugins |
|
|
71
|
+
|
|
72
|
+
Short hidden aliases exist for the busiest groups: `p` (plugin), `sb`
|
|
73
|
+
(sandbox), `w` (worker), `m` (manager), `mig` (migration).
|
|
74
|
+
|
|
75
|
+
`xcli` expects to run **inside** an xcore project directory (it reads that
|
|
76
|
+
project's `integration.yaml` and needs `xcore` importable in the current
|
|
77
|
+
environment) — it's a project-management tool, not a standalone service.
|
xcorecli-2.2.0/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# xcli — xcore project manager
|
|
2
|
+
|
|
3
|
+
Official CLI for the `xcore` framework: scaffold a project, manage
|
|
4
|
+
plugins (local dev, marketplace install, runtime control, signing), run
|
|
5
|
+
migrations, control the Celery worker, and monitor a running deployment.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install xcorecli
|
|
9
|
+
xcli --help
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Full docs: https://docs.xcorehub.dev (built from `docs/` with
|
|
13
|
+
`mkdocs-material` — `mkdocs serve` locally).
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
xcli init my-app # scaffold a new xcore project
|
|
19
|
+
cd my-app
|
|
20
|
+
pip install -r requirements.txt
|
|
21
|
+
xcli manager start --reload # run it
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Installing plugins from the marketplace
|
|
25
|
+
|
|
26
|
+
Browsing is public, no credentials needed:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
xcli plugin marketplace browse
|
|
30
|
+
xcli plugin marketplace search "auth"
|
|
31
|
+
xcli plugin marketplace info xlicense
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Installing needs two credentials — see
|
|
35
|
+
[docs/getting-started/auth.md](docs/getting-started/auth.md):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
xcli config set api-key xdk_...
|
|
39
|
+
xcli config set signing-key <your-signing-secret>
|
|
40
|
+
xcli plugin install xlicense
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Command groups
|
|
44
|
+
|
|
45
|
+
| Group | Purpose |
|
|
46
|
+
|-------|---------|
|
|
47
|
+
| `xcli init` / `xcli upgrade` | Scaffold a project / migrate `integration.yaml` to the latest schema |
|
|
48
|
+
| `xcli health` / `xcli services` | Health-check and status of all configured services |
|
|
49
|
+
| `xcli config` | Store local credentials (`api-key`, `signing-key`) |
|
|
50
|
+
| `xcli plugin` | Local dev, marketplace browse/install, runtime control, signing, updates — see `xcli plugin --help` |
|
|
51
|
+
| `xcli deploy` | Deploy plugins to remote servers |
|
|
52
|
+
| `xcli sandbox` | Inspect the plugin sandbox |
|
|
53
|
+
| `xcli worker` | Manage Celery workers |
|
|
54
|
+
| `xcli manager` | Runtime monitoring of a running instance |
|
|
55
|
+
| `xcli migration` | Alembic migrations for plugins |
|
|
56
|
+
|
|
57
|
+
Short hidden aliases exist for the busiest groups: `p` (plugin), `sb`
|
|
58
|
+
(sandbox), `w` (worker), `m` (manager), `mig` (migration).
|
|
59
|
+
|
|
60
|
+
`xcli` expects to run **inside** an xcore project directory (it reads that
|
|
61
|
+
project's `integration.yaml` and needs `xcore` importable in the current
|
|
62
|
+
environment) — it's a project-management tool, not a standalone service.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Login & Install Shortcut
|
|
2
|
+
|
|
3
|
+
Two small top-level commands, both really about the marketplace rather
|
|
4
|
+
than the local xcore runtime.
|
|
5
|
+
|
|
6
|
+
## `xcli login`
|
|
7
|
+
|
|
8
|
+
Authorizes this machine with the marketplace via a device-code flow —
|
|
9
|
+
opens a browser, you confirm a 6-digit code, `xcli` saves the resulting
|
|
10
|
+
credentials on its own. Full walkthrough:
|
|
11
|
+
[Authentication → Quick Start](../getting-started/auth.md#quick-start-xcli-login).
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
xcli login
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
!!! tip "For CI, not this"
|
|
18
|
+
`xcli login` mints a **personal** credential meant for a human running
|
|
19
|
+
it interactively. CI pipelines should use a project-scoped key and the
|
|
20
|
+
`XCLI_API_KEY`/`XCLI_SIGNING_KEY` environment variables instead — see
|
|
21
|
+
[Environment variables](../getting-started/auth.md#environment-variables).
|
|
22
|
+
|
|
23
|
+
## `xcli install`
|
|
24
|
+
|
|
25
|
+
A shortcut for [`xcli plugin install`](../plugin/install.md) — same
|
|
26
|
+
command, same options, one less word to type:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
xcli install name-of-plugin
|
|
30
|
+
xcli install name-of-plugin@1.2.3
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
There's no equivalent top-level shortcut for service extensions — use
|
|
34
|
+
[`xcli service install`](../service/index.md) directly.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Authentication
|
|
2
|
+
|
|
3
|
+
To interact with the **xcore marketplace** and install plugins, you need
|
|
4
|
+
two separate credentials — they protect different things and neither
|
|
5
|
+
substitutes for the other:
|
|
6
|
+
|
|
7
|
+
## Quick Start: `xcli login`
|
|
8
|
+
|
|
9
|
+
The fastest way to get both credentials — no copy-pasting required.
|
|
10
|
+
|
|
11
|
+
```bash title="Device-code login"
|
|
12
|
+
xcli login
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This opens the marketplace in your browser with a 6-digit code pre-filled,
|
|
16
|
+
and waits. Once you confirm it there (you must already be logged into the
|
|
17
|
+
marketplace website, and the confirmation is an explicit click — it never
|
|
18
|
+
happens automatically just by opening the link), `xcli` retrieves both
|
|
19
|
+
credentials on its own and saves them to `~/.xcli/config.json` — the exact
|
|
20
|
+
same file `xcli config set` writes to, just without the manual steps.
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
To authorize this device, visit: https://marketplace.xcorehub.dev/cli/confirm
|
|
24
|
+
And enter code: 042817
|
|
25
|
+
|
|
26
|
+
✓ Logged in — credentials saved to ~/.xcli/config.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If the browser can't be opened automatically (headless environment, remote
|
|
30
|
+
shell), the URL and code are printed regardless — open it manually.
|
|
31
|
+
|
|
32
|
+
!!! info "What kind of key does this create?"
|
|
33
|
+
`xcli login` mints a **personal** API key — unlike a key created
|
|
34
|
+
through the marketplace's project UI (which is scoped to exactly one
|
|
35
|
+
plugin or service), a personal key works for installing **any public**
|
|
36
|
+
plugin or service, and any private one you own or have team access to.
|
|
37
|
+
It's meant for day-to-day `xcli install`/`xcli service install` usage,
|
|
38
|
+
not for CI — see [Environment variables](#environment-variables) below
|
|
39
|
+
for the project-scoped alternative CI pipelines should use instead.
|
|
40
|
+
|
|
41
|
+
The device-code request expires after a few minutes if left unconfirmed;
|
|
42
|
+
just run `xcli login` again.
|
|
43
|
+
|
|
44
|
+
## Manual Setup
|
|
45
|
+
|
|
46
|
+
Prefer to configure credentials by hand, or need a **project-scoped** key
|
|
47
|
+
(tied to one specific plugin/service — the right choice for CI/CD, see
|
|
48
|
+
below) instead of a personal one? Both credentials can also be set directly:
|
|
49
|
+
|
|
50
|
+
| Credential | What it's for | Where to get it |
|
|
51
|
+
|------------|----------------|------------------|
|
|
52
|
+
| **API key** (`xdk_...`) | Authorizes the download itself (`X-API-Key` header on `GET /plugins/{slug}/install`) — tied to one project (`kind=plugin`, matching the target plugin's slug) | XCoreHub → Déploiements → Projets & clés |
|
|
53
|
+
| **Signing key** | An HMAC-SHA256 secret used to verify the `X-Signature` header on the downloaded ZIP — installation is refused if it doesn't match | XCoreHub → Déploiements → Clé de signature |
|
|
54
|
+
|
|
55
|
+
`browse`/`search`/`info` (read-only discovery) need **neither** — the
|
|
56
|
+
marketplace listing is public.
|
|
57
|
+
|
|
58
|
+
## Configuration Commands
|
|
59
|
+
|
|
60
|
+
`xcorecli` provides a `config` command group to manage your local settings.
|
|
61
|
+
|
|
62
|
+
### Store your credentials
|
|
63
|
+
|
|
64
|
+
```bash title="Configuration"
|
|
65
|
+
xcli config set api-key xdk_...
|
|
66
|
+
xcli config set signing-key <your-signing-secret>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Both are required before `xcli plugin install <name>` will succeed —
|
|
70
|
+
`install` checks for each explicitly and tells you exactly which one is
|
|
71
|
+
missing.
|
|
72
|
+
|
|
73
|
+
!!! warning "Security First"
|
|
74
|
+
Never share your API key or signing key, or commit them to version
|
|
75
|
+
control. They're stored in `~/.xcli/config.json` (mode `0600`), never in
|
|
76
|
+
your project's `integration.yaml`.
|
|
77
|
+
|
|
78
|
+
### View current configuration
|
|
79
|
+
|
|
80
|
+
To check your current configuration (with sensitive data masked):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
xcli config show
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Credential storage
|
|
87
|
+
|
|
88
|
+
Managed by `xcli/_credentials.py` — a flat `~/.xcli/config.json`, keyed
|
|
89
|
+
`api-key` / `signing-key`. Only these two keys are valid; anything else
|
|
90
|
+
passed to `xcli config set` is rejected.
|
|
91
|
+
|
|
92
|
+
!!! info "Marketplace URL"
|
|
93
|
+
By default, `xcorecli` connects to `https://marketplace.xcorehub.dev`.
|
|
94
|
+
Override it via `marketplace.url` in the project's `integration.yaml`
|
|
95
|
+
(the same value the project's own backend uses) — always include the
|
|
96
|
+
`https://` scheme, a bare domain will fail to resolve as a URL.
|
|
97
|
+
|
|
98
|
+
## Environment variables
|
|
99
|
+
|
|
100
|
+
For CI/CD environments, both credentials can be supplied via environment
|
|
101
|
+
variables instead of `xcli config set` — these take priority over
|
|
102
|
+
`~/.xcli/config.json` when present. Use a **project-scoped** key here (one
|
|
103
|
+
plugin/service, created from the marketplace's project page), not a
|
|
104
|
+
personal one from `xcli login` — a CI pipeline should only ever be able to
|
|
105
|
+
touch the one target it's meant to deploy:
|
|
106
|
+
|
|
107
|
+
```bash title=".env"
|
|
108
|
+
XCLI_API_KEY=xdk_...
|
|
109
|
+
XCLI_SIGNING_KEY=your-signing-secret
|
|
110
|
+
```
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
`xcorecli` provides a streamlined wrapper around **Alembic** to manage your database schema migrations, with added safety features like automated backups.
|
|
4
4
|
|
|
5
|
+
!!! info "Async database support"
|
|
6
|
+
`upgrade`/`downgrade`/`revision`/`current`/`stamp` all transparently
|
|
7
|
+
bridge to an async engine first when your `integration.yaml` database
|
|
8
|
+
URL uses an async driver (`sqlite+aiosqlite`, `postgresql+asyncpg`,
|
|
9
|
+
...) — the normal case for an xcore project. No configuration needed;
|
|
10
|
+
it's detected from the URL itself.
|
|
11
|
+
|
|
5
12
|
## Getting Started
|
|
6
13
|
|
|
7
14
|
Migrations are managed via the `migration` command group.
|
|
@@ -6,10 +6,21 @@ Plugins can be installed from the official **xcore Marketplace** or from externa
|
|
|
6
6
|
|
|
7
7
|
The easiest way to add features. `xcorecli` handles downloads and HMAC signature verification.
|
|
8
8
|
|
|
9
|
+
!!! warning "Two credentials required"
|
|
10
|
+
Marketplace installs need **both** an API key and a signing key
|
|
11
|
+
configured first — see [Authentication](../getting-started/auth.md).
|
|
12
|
+
Missing either one fails fast with a clear message telling you which
|
|
13
|
+
one and how to set it; nothing is extracted until the signature checks
|
|
14
|
+
out.
|
|
15
|
+
|
|
9
16
|
```bash title="Marketplace Install"
|
|
10
17
|
xcli plugin install name-of-plugin
|
|
11
18
|
```
|
|
12
19
|
|
|
20
|
+
!!! tip "Shortcut"
|
|
21
|
+
`xcli install name-of-plugin` works too — a top-level alias for
|
|
22
|
+
`xcli plugin install`, same command underneath.
|
|
23
|
+
|
|
13
24
|
### Installing a Specific Version
|
|
14
25
|
|
|
15
26
|
```bash
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Plugin Marketplace
|
|
2
|
+
|
|
3
|
+
Discover plugins available on the marketplace before installing them — all
|
|
4
|
+
three commands here are read-only and public, no credentials required.
|
|
5
|
+
|
|
6
|
+
## Browse All
|
|
7
|
+
|
|
8
|
+
List published plugins, sorted `newest` (default), `downloads`, or `rating`.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
xcli plugin marketplace browse
|
|
12
|
+
xcli plugin marketplace browse --sort downloads --limit 50
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Search
|
|
16
|
+
|
|
17
|
+
Find plugins by name or description.
|
|
18
|
+
|
|
19
|
+
```bash title="Search"
|
|
20
|
+
xcli plugin marketplace search "monitoring"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Plugin Details
|
|
24
|
+
|
|
25
|
+
Get in-depth information about a specific marketplace plugin before
|
|
26
|
+
installing it — description, rating, download count, repository, and
|
|
27
|
+
published versions.
|
|
28
|
+
|
|
29
|
+
```bash title="Plugin Info"
|
|
30
|
+
xcli plugin marketplace info name-of-plugin
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## What's not here
|
|
34
|
+
|
|
35
|
+
Rating a plugin (`POST /plugins/{slug}/ratings`) requires a full user
|
|
36
|
+
session (Bearer JWT), not the API key `xcli` stores — that's a web-app
|
|
37
|
+
action, not a CLI one; rate plugins from the XCoreHub dashboard instead.
|
|
38
|
+
There's also no dedicated "trending" endpoint server-side — use
|
|
39
|
+
`browse --sort downloads` or `--sort rating` for the same effect.
|
|
40
|
+
|
|
41
|
+
## Installing
|
|
42
|
+
|
|
43
|
+
Once you've found a plugin, see [Installing Plugins](install.md) — it
|
|
44
|
+
needs the API key and signing key described in
|
|
45
|
+
[Authentication](../getting-started/auth.md), which discovery commands on
|
|
46
|
+
this page don't.
|
|
@@ -6,8 +6,11 @@ A comprehensive list of all commands available in `xcorecli`.
|
|
|
6
6
|
|
|
7
7
|
- `xcli init`: Initialize a new xcore project.
|
|
8
8
|
- `xcli upgrade`: Migrate `integration.yaml` to the latest schema.
|
|
9
|
+
- `xcli login`: Authorize this machine with the marketplace (device-code flow).
|
|
10
|
+
- `xcli install`: Shortcut for `xcli plugin install`.
|
|
9
11
|
- `xcli health`: Global health check of all configured services.
|
|
10
|
-
- `xcli services`: Show status and details of all system services
|
|
12
|
+
- `xcli services`: Show status and details of all system services (local
|
|
13
|
+
runtime — not the marketplace catalog, see `xcli service` below).
|
|
11
14
|
|
|
12
15
|
## `manager` Administration
|
|
13
16
|
|
|
@@ -44,11 +47,12 @@ A comprehensive list of all commands available in `xcorecli`.
|
|
|
44
47
|
- `local list`: List all plugins with link type.
|
|
45
48
|
|
|
46
49
|
### `plugin marketplace` Discovery
|
|
47
|
-
- `marketplace browse`: List
|
|
48
|
-
- `marketplace search`: Search by
|
|
49
|
-
- `marketplace info`: Pre-install details.
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
- `marketplace browse`: List published plugins (`--sort newest|downloads|rating`).
|
|
51
|
+
- `marketplace search`: Search by name or description.
|
|
52
|
+
- `marketplace info`: Pre-install details, including published versions.
|
|
53
|
+
|
|
54
|
+
No `rate` command — rating requires a full user session (JWT), not an API
|
|
55
|
+
key; rate plugins from the XCoreHub dashboard.
|
|
52
56
|
|
|
53
57
|
### `plugin update` Maintenance
|
|
54
58
|
- `update check`: Check for new versions.
|
|
@@ -60,6 +64,22 @@ A comprehensive list of all commands available in `xcorecli`.
|
|
|
60
64
|
- `runtime reload`: Restart a plugin.
|
|
61
65
|
- `runtime status`: Show active plugins.
|
|
62
66
|
|
|
67
|
+
## `service` Marketplace Extensions
|
|
68
|
+
|
|
69
|
+
Mirror of `plugin` for the separate `xservices` catalog — not to be
|
|
70
|
+
confused with `xcli services`/`xcli manager services` (local runtime).
|
|
71
|
+
|
|
72
|
+
- `service info`: Detailed local extension report.
|
|
73
|
+
- `service health`: Health check of all installed extensions.
|
|
74
|
+
- `service remove`: Uninstall an extension.
|
|
75
|
+
- `service install`: Install from marketplace.
|
|
76
|
+
- `service versions`: List marketplace versions.
|
|
77
|
+
|
|
78
|
+
### `service marketplace` Discovery
|
|
79
|
+
- `marketplace browse`: List published extensions (`--sort newest|installs|rating`).
|
|
80
|
+
- `marketplace search`: Search by name or description.
|
|
81
|
+
- `marketplace info`: Pre-install details, including published versions.
|
|
82
|
+
|
|
63
83
|
## `worker` Background Tasks
|
|
64
84
|
|
|
65
85
|
- `worker start`: Start a Celery worker.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Service Extensions
|
|
2
|
+
|
|
3
|
+
The marketplace also hosts **service extensions** (`xservices`) — a
|
|
4
|
+
separate catalog from plugins, for reusable service-shaped dependencies a
|
|
5
|
+
plugin might need (databases, caches, message queues...). The `service`
|
|
6
|
+
command group mirrors `plugin` one-for-one, just pointed at that other
|
|
7
|
+
catalog.
|
|
8
|
+
|
|
9
|
+
!!! warning "Not `xcli services`"
|
|
10
|
+
`xcli service` (singular, this page) is the marketplace catalog.
|
|
11
|
+
`xcli services` and `xcli manager services` (plural) show your
|
|
12
|
+
**local** xcore runtime's own service status — an unrelated command
|
|
13
|
+
that happens to share a similar name. If a command errors with
|
|
14
|
+
something about your local `ServiceContainer`, you probably typed the
|
|
15
|
+
plural by mistake.
|
|
16
|
+
|
|
17
|
+
## Discovery
|
|
18
|
+
|
|
19
|
+
Read-only, public, no credentials required — same shape as
|
|
20
|
+
[Plugin Marketplace](../plugin/marketplace.md):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
xcli service marketplace browse
|
|
24
|
+
xcli service marketplace browse --sort installs --limit 50
|
|
25
|
+
xcli service marketplace search "cache"
|
|
26
|
+
xcli service marketplace info name-of-service
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`--sort` accepts `newest` (default), `installs`, or `rating` — note
|
|
30
|
+
`installs`, not `downloads`; the service catalog counts installs, not
|
|
31
|
+
downloads.
|
|
32
|
+
|
|
33
|
+
## Installing
|
|
34
|
+
|
|
35
|
+
Same two credentials as plugins — see [Authentication](../getting-started/auth.md)
|
|
36
|
+
(`xcli login` covers both catalogs at once; a project-scoped key is
|
|
37
|
+
per-catalog, so make sure the project you created it for has
|
|
38
|
+
`kind=service`).
|
|
39
|
+
|
|
40
|
+
```bash title="Install"
|
|
41
|
+
xcli service install name-of-service
|
|
42
|
+
xcli service install name-of-service@1.2.3
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Installed extensions land in the directory configured under
|
|
46
|
+
`marketplace_services.directory` in `integration.yaml` (defaults to
|
|
47
|
+
`./services`) — deliberately a separate key from `plugins.directory` and
|
|
48
|
+
from `services.databases.*` (xcore's own internal service container
|
|
49
|
+
config), which already both use `services`/`plugins` for something else.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
xcli service versions name-of-service
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Management Commands
|
|
56
|
+
|
|
57
|
+
Identical shape to `plugin`:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
xcli service info name-of-service # manifest, permissions, signature status
|
|
61
|
+
xcli service health # signature + AST + manifest check, all installed
|
|
62
|
+
xcli service remove name-of-service # uninstall
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
!!! info "Smaller surface than `plugin`"
|
|
66
|
+
There's no `service local`/`service runtime`/`service security`/
|
|
67
|
+
`service update` today — service extensions don't have the same
|
|
68
|
+
local-dev-scaffolding or hot-reload workflow plugins do. Everything
|
|
69
|
+
that exists lives directly under `xcli service`.
|
|
@@ -58,6 +58,7 @@ nav:
|
|
|
58
58
|
- Global Commands:
|
|
59
59
|
- init & upgrade: commands/init.md
|
|
60
60
|
- health & services: commands/health.md
|
|
61
|
+
- login & install: commands/login.md
|
|
61
62
|
- Config: config/index.md
|
|
62
63
|
- Plugin:
|
|
63
64
|
- Overview: plugin/index.md
|
|
@@ -67,6 +68,7 @@ nav:
|
|
|
67
68
|
- Marketplace: plugin/marketplace.md
|
|
68
69
|
- Security: plugin/security.md
|
|
69
70
|
- Updates: plugin/update.md
|
|
71
|
+
- Service: service/index.md
|
|
70
72
|
- Sandbox: sandbox/index.md
|
|
71
73
|
- Worker:
|
|
72
74
|
- Overview: worker/index.md
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "xcorecli"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "CLI for xcore — configuration, plugins, monitoring"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -16,6 +16,12 @@ dependencies = [
|
|
|
16
16
|
"pyyaml>=6.0.1",
|
|
17
17
|
"psutil>=5.9",
|
|
18
18
|
"httpx>=0.27",
|
|
19
|
+
# xcli migration needs to resolve ${VAR}-style placeholders in
|
|
20
|
+
# integration.yaml's services.databases.*.url the same way the app
|
|
21
|
+
# itself does at runtime (xcore.configurations.loader.ConfigLoader,
|
|
22
|
+
# same app.dotenv key, same library) — declared directly rather than
|
|
23
|
+
# relying on it being transitively present via an installed `xcore`.
|
|
24
|
+
"python-dotenv>=1.0.0",
|
|
19
25
|
]
|
|
20
26
|
|
|
21
27
|
[project.scripts]
|
|
@@ -569,6 +569,15 @@ wheels = [
|
|
|
569
569
|
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
|
570
570
|
]
|
|
571
571
|
|
|
572
|
+
[[package]]
|
|
573
|
+
name = "python-dotenv"
|
|
574
|
+
version = "1.2.3"
|
|
575
|
+
source = { registry = "https://pypi.org/simple" }
|
|
576
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6a/53/ed9d74092561d4b01a2ef1349d52cdbc135e526c245f366b089cfca6de49/python_dotenv-1.2.3.tar.gz", hash = "sha256:a20a594dabeaa385725aa239d5244871c143ecb356add8a20fcf23773a6c3a35", size = 58945, upload-time = "2026-08-16T16:54:54.067Z" }
|
|
577
|
+
wheels = [
|
|
578
|
+
{ url = "https://files.pythonhosted.org/packages/0d/17/c5c6b53ddc18f297992099b3d9ec16c855c0ccc83263a21fe4d1c625ec6c/python_dotenv-1.2.3-py3-none-any.whl", hash = "sha256:904552145e8bfed22162c09dab1c2b9b54fefa7b23ba780f4f26ca0316b0f0d9", size = 22780, upload-time = "2026-08-16T16:54:52.473Z" },
|
|
579
|
+
]
|
|
580
|
+
|
|
572
581
|
[[package]]
|
|
573
582
|
name = "pyyaml"
|
|
574
583
|
version = "6.0.3"
|
|
@@ -773,12 +782,13 @@ wheels = [
|
|
|
773
782
|
|
|
774
783
|
[[package]]
|
|
775
784
|
name = "xcorecli"
|
|
776
|
-
version = "2.
|
|
785
|
+
version = "2.2.0"
|
|
777
786
|
source = { editable = "." }
|
|
778
787
|
dependencies = [
|
|
779
788
|
{ name = "alembic" },
|
|
780
789
|
{ name = "httpx" },
|
|
781
790
|
{ name = "psutil" },
|
|
791
|
+
{ name = "python-dotenv" },
|
|
782
792
|
{ name = "pyyaml" },
|
|
783
793
|
{ name = "rich" },
|
|
784
794
|
{ name = "sqlalchemy" },
|
|
@@ -795,6 +805,7 @@ requires-dist = [
|
|
|
795
805
|
{ name = "alembic", specifier = ">=1.18.0" },
|
|
796
806
|
{ name = "httpx", specifier = ">=0.27" },
|
|
797
807
|
{ name = "psutil", specifier = ">=5.9" },
|
|
808
|
+
{ name = "python-dotenv", specifier = ">=1.0.0" },
|
|
798
809
|
{ name = "pyyaml", specifier = ">=6.0.1" },
|
|
799
810
|
{ name = "rich", specifier = ">=14.3.4" },
|
|
800
811
|
{ name = "sqlalchemy", specifier = ">=2.0.0" },
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
import webbrowser
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
import typer
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from xcli._credentials import save_credential
|
|
11
|
+
from xcli.plugin.shared import marketplace_api_base
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
_START_PATH = '/app/xdevkeys/device/start'
|
|
16
|
+
_POLL_PATH = '/app/xdevkeys/device/poll'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _try_open(url: str) -> bool:
|
|
20
|
+
try:
|
|
21
|
+
return webbrowser.open(url)
|
|
22
|
+
except Exception:
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def login() -> None:
|
|
27
|
+
"""`xcli login` — device-code flow (RFC 8628): opens the marketplace in a
|
|
28
|
+
browser for the user to confirm a 6-digit code, then polls until the
|
|
29
|
+
marketplace hands back a personal API key + signing key, saved straight
|
|
30
|
+
into ~/.xcli/config.json (same store `xcli config set` writes to — this
|
|
31
|
+
is just that, automated). The raw secrets are never printed."""
|
|
32
|
+
base = marketplace_api_base()
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
resp = httpx.post(f'{base}{_START_PATH}', timeout=15)
|
|
36
|
+
resp.raise_for_status()
|
|
37
|
+
except httpx.RequestError as e:
|
|
38
|
+
console.print(f'[red]Network error:[/red] {e}')
|
|
39
|
+
raise typer.Exit(1)
|
|
40
|
+
except httpx.HTTPStatusError as e:
|
|
41
|
+
console.print(f'[red]HTTP {e.response.status_code}:[/red] {e.response.text[:200]}')
|
|
42
|
+
raise typer.Exit(1)
|
|
43
|
+
|
|
44
|
+
data = resp.json()
|
|
45
|
+
device_code = data['device_code']
|
|
46
|
+
user_code = data['user_code']
|
|
47
|
+
verification_uri = data['verification_uri']
|
|
48
|
+
expires_in = data['expires_in']
|
|
49
|
+
interval = data['interval']
|
|
50
|
+
complete_url = f'{verification_uri}?code={user_code}'
|
|
51
|
+
|
|
52
|
+
console.print(f"\nTo authorize this device, visit: [cyan]{verification_uri}[/cyan]")
|
|
53
|
+
console.print(f"And enter code: [bold yellow]{user_code}[/bold yellow]\n")
|
|
54
|
+
if not _try_open(complete_url):
|
|
55
|
+
console.print("[dim]Couldn't open a browser automatically — open the URL above manually and enter the code.[/dim]\n")
|
|
56
|
+
|
|
57
|
+
deadline = time.monotonic() + expires_in
|
|
58
|
+
with console.status('Waiting for authorization...'):
|
|
59
|
+
while time.monotonic() < deadline:
|
|
60
|
+
time.sleep(interval)
|
|
61
|
+
try:
|
|
62
|
+
poll_resp = httpx.get(f'{base}{_POLL_PATH}', params={'device_code': device_code}, timeout=15)
|
|
63
|
+
except httpx.RequestError:
|
|
64
|
+
continue
|
|
65
|
+
|
|
66
|
+
if poll_resp.status_code == 404:
|
|
67
|
+
console.print('[red]Login request expired or was already used.[/red] Run [cyan]xcli login[/cyan] again.')
|
|
68
|
+
raise typer.Exit(1)
|
|
69
|
+
if poll_resp.status_code != 200:
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
payload = poll_resp.json()
|
|
73
|
+
if payload.get('status') == 'confirmed':
|
|
74
|
+
save_credential('api-key', payload['api_key'])
|
|
75
|
+
save_credential('signing-key', payload['signing_key'])
|
|
76
|
+
console.print('[green]✓[/green] Logged in — credentials saved to [dim]~/.xcli/config.json[/dim]')
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
console.print('[red]Login timed out.[/red] Run [cyan]xcli login[/cyan] again.')
|
|
80
|
+
raise typer.Exit(1)
|