spectackl 0.0.1__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.
- spectackl-0.0.1/MANIFEST.in +27 -0
- spectackl-0.0.1/PKG-INFO +92 -0
- spectackl-0.0.1/README.md +59 -0
- spectackl-0.0.1/pyproject.toml +98 -0
- spectackl-0.0.1/setup.cfg +4 -0
- spectackl-0.0.1/src/spectackl/__init__.py +3 -0
- spectackl-0.0.1/src/spectackl/auth.py +74 -0
- spectackl-0.0.1/src/spectackl/cli.py +108 -0
- spectackl-0.0.1/src/spectackl/commands/__init__.py +1 -0
- spectackl-0.0.1/src/spectackl/commands/artifact.py +335 -0
- spectackl-0.0.1/src/spectackl/commands/assets.py +260 -0
- spectackl-0.0.1/src/spectackl/commands/context.py +283 -0
- spectackl-0.0.1/src/spectackl/commands/daemon.py +687 -0
- spectackl-0.0.1/src/spectackl/commands/init.py +251 -0
- spectackl-0.0.1/src/spectackl/commands/relation.py +146 -0
- spectackl-0.0.1/src/spectackl/commands/rsync.py +821 -0
- spectackl-0.0.1/src/spectackl/commands/search.py +69 -0
- spectackl-0.0.1/src/spectackl/commands/task.py +263 -0
- spectackl-0.0.1/src/spectackl/config.py +369 -0
- spectackl-0.0.1/src/spectackl/exit_codes.py +68 -0
- spectackl-0.0.1/src/spectackl/http_client.py +95 -0
- spectackl-0.0.1/src/spectackl/output.py +181 -0
- spectackl-0.0.1/src/spectackl.egg-info/PKG-INFO +92 -0
- spectackl-0.0.1/src/spectackl.egg-info/SOURCES.txt +32 -0
- spectackl-0.0.1/src/spectackl.egg-info/dependency_links.txt +1 -0
- spectackl-0.0.1/src/spectackl.egg-info/entry_points.txt +2 -0
- spectackl-0.0.1/src/spectackl.egg-info/requires.txt +12 -0
- spectackl-0.0.1/src/spectackl.egg-info/top_level.txt +1 -0
- spectackl-0.0.1/tests/test_auth.py +75 -0
- spectackl-0.0.1/tests/test_commands.py +977 -0
- spectackl-0.0.1/tests/test_config.py +318 -0
- spectackl-0.0.1/tests/test_exit_codes.py +37 -0
- spectackl-0.0.1/tests/test_output.py +105 -0
- spectackl-0.0.1/tests/test_rsync.py +350 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Source-distribution contents.
|
|
2
|
+
#
|
|
3
|
+
# The wheel is controlled by [tool.setuptools.packages.find] in pyproject.toml, but an
|
|
4
|
+
# sdist defaults to sweeping in far more than that — so anything that must not be
|
|
5
|
+
# published has to be excluded here as well.
|
|
6
|
+
|
|
7
|
+
# The generated OpenAPI client is repo-only: it exists for the CI drift check
|
|
8
|
+
# (scripts/regenerate-client.sh) and nothing in the CLI imports it. Keeping it out of
|
|
9
|
+
# the sdist matches the wheel, so both distributions carry the same code.
|
|
10
|
+
prune src/spectackl_client
|
|
11
|
+
|
|
12
|
+
# Credentials must never reach a published artifact. .env.local holds real PyPI tokens
|
|
13
|
+
# and is gitignored; the sdist defaults happen not to pick up dotfiles today, and this
|
|
14
|
+
# makes that a rule rather than a coincidence. A token published inside an sdist cannot
|
|
15
|
+
# be recalled — only revoked, after it is already public.
|
|
16
|
+
#
|
|
17
|
+
# These are three exact patterns, deliberately NOT a `.env*` glob: `.env.example` is
|
|
18
|
+
# committed and must keep working. Nothing here matches it — `.env.*.local` requires the
|
|
19
|
+
# `.local` suffix. Add new patterns one at a time for the same reason.
|
|
20
|
+
global-exclude .env .env.local .env.*.local
|
|
21
|
+
|
|
22
|
+
# Build and tooling noise.
|
|
23
|
+
global-exclude *.pyc
|
|
24
|
+
prune **/__pycache__
|
|
25
|
+
prune .mypy_cache
|
|
26
|
+
prune .pytest_cache
|
|
27
|
+
prune .ruff_cache
|
spectackl-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spectackl
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: CLI for the Spectackl Public REST API — for AI agents and operators
|
|
5
|
+
Author-email: Spectackl Engineering <engineering@spectackl.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://spectackl.ai
|
|
8
|
+
Project-URL: Documentation, https://docs.spectackl.ai
|
|
9
|
+
Keywords: spectackl,cli,ai,agents
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: typer>=0.12
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-httpx>=0.30; extra == "dev"
|
|
29
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
31
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
32
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
33
|
+
|
|
34
|
+
# spectackl
|
|
35
|
+
|
|
36
|
+
Command-line interface to the [Spectackl](https://spectackl.ai) Public REST API — built
|
|
37
|
+
for AI agents and operators who need programmatic access to artifacts, scenes and task
|
|
38
|
+
executions without going through the web UI.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install spectackl
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
spectackl init --api-key spc_… --backend-url https://api.spectackl.ai --project my-project
|
|
48
|
+
spectackl artifact list --json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
API keys are managed in the Spectackl Admin Console. `init` writes
|
|
52
|
+
`.spectackl/settings.yaml` in the current directory and a user-global
|
|
53
|
+
`~/.config/spectackl/settings.yaml`; both are created `0600` and neither should be
|
|
54
|
+
committed.
|
|
55
|
+
|
|
56
|
+
## What it does
|
|
57
|
+
|
|
58
|
+
| Command | Purpose |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `spectackl search <query>` | Hybrid full-text + semantic search across a project's content |
|
|
61
|
+
| `spectackl artifact` | Get, list, create and update artifacts |
|
|
62
|
+
| `spectackl relation` | Manage the artifact graph (`INCLUDES`, `DOCUMENTS`, `DEPENDS_ON`, …) |
|
|
63
|
+
| `spectackl context` | Inspect scenes (work contexts) and the artifacts they scope |
|
|
64
|
+
| `spectackl task` | Claim, progress and complete task executions |
|
|
65
|
+
| `spectackl assets sync` | Materialize the project's agents and skills into `./.claude/` |
|
|
66
|
+
| `spectackl rsync` | Reconcile artifact content with local files, in both directions |
|
|
67
|
+
| `spectackl daemon` | Run agent sessions on this machine |
|
|
68
|
+
|
|
69
|
+
Every command accepts `--json` for machine-readable output, and every command returns a
|
|
70
|
+
documented exit code — `0` success, `10` auth required, `20` validation, `30` not found,
|
|
71
|
+
`40` upstream unavailable, and so on — so scripts can branch on failures precisely
|
|
72
|
+
rather than parsing text.
|
|
73
|
+
|
|
74
|
+
## Designed for agents
|
|
75
|
+
|
|
76
|
+
Output is stable and parseable, errors are structured, and the exit-code scheme is part
|
|
77
|
+
of the public contract. `spectackl assets sync` writes agent and skill definitions in the
|
|
78
|
+
exact layout Claude Code reads, built from the same artifacts the platform provisions
|
|
79
|
+
into a sandbox — so an agent invoked on a workstation is the one that runs in production.
|
|
80
|
+
|
|
81
|
+
## Requirements
|
|
82
|
+
|
|
83
|
+
- Python 3.10+
|
|
84
|
+
- A Spectackl tenant and an API key (`spc_` prefix)
|
|
85
|
+
|
|
86
|
+
## Documentation
|
|
87
|
+
|
|
88
|
+
Full guide: **https://docs.spectackl.ai**
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# spectackl
|
|
2
|
+
|
|
3
|
+
Command-line interface to the [Spectackl](https://spectackl.ai) Public REST API — built
|
|
4
|
+
for AI agents and operators who need programmatic access to artifacts, scenes and task
|
|
5
|
+
executions without going through the web UI.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install spectackl
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
spectackl init --api-key spc_… --backend-url https://api.spectackl.ai --project my-project
|
|
15
|
+
spectackl artifact list --json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
API keys are managed in the Spectackl Admin Console. `init` writes
|
|
19
|
+
`.spectackl/settings.yaml` in the current directory and a user-global
|
|
20
|
+
`~/.config/spectackl/settings.yaml`; both are created `0600` and neither should be
|
|
21
|
+
committed.
|
|
22
|
+
|
|
23
|
+
## What it does
|
|
24
|
+
|
|
25
|
+
| Command | Purpose |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `spectackl search <query>` | Hybrid full-text + semantic search across a project's content |
|
|
28
|
+
| `spectackl artifact` | Get, list, create and update artifacts |
|
|
29
|
+
| `spectackl relation` | Manage the artifact graph (`INCLUDES`, `DOCUMENTS`, `DEPENDS_ON`, …) |
|
|
30
|
+
| `spectackl context` | Inspect scenes (work contexts) and the artifacts they scope |
|
|
31
|
+
| `spectackl task` | Claim, progress and complete task executions |
|
|
32
|
+
| `spectackl assets sync` | Materialize the project's agents and skills into `./.claude/` |
|
|
33
|
+
| `spectackl rsync` | Reconcile artifact content with local files, in both directions |
|
|
34
|
+
| `spectackl daemon` | Run agent sessions on this machine |
|
|
35
|
+
|
|
36
|
+
Every command accepts `--json` for machine-readable output, and every command returns a
|
|
37
|
+
documented exit code — `0` success, `10` auth required, `20` validation, `30` not found,
|
|
38
|
+
`40` upstream unavailable, and so on — so scripts can branch on failures precisely
|
|
39
|
+
rather than parsing text.
|
|
40
|
+
|
|
41
|
+
## Designed for agents
|
|
42
|
+
|
|
43
|
+
Output is stable and parseable, errors are structured, and the exit-code scheme is part
|
|
44
|
+
of the public contract. `spectackl assets sync` writes agent and skill definitions in the
|
|
45
|
+
exact layout Claude Code reads, built from the same artifacts the platform provisions
|
|
46
|
+
into a sandbox — so an agent invoked on a workstation is the one that runs in production.
|
|
47
|
+
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
- Python 3.10+
|
|
51
|
+
- A Spectackl tenant and an API key (`spc_` prefix)
|
|
52
|
+
|
|
53
|
+
## Documentation
|
|
54
|
+
|
|
55
|
+
Full guide: **https://docs.spectackl.ai**
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
MIT
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "spectackl"
|
|
7
|
+
# Single-sourced from spectackl.__version__ so the package metadata and the
|
|
8
|
+
# `spectackl --version` output can never disagree. Bump it in src/spectackl/__init__.py.
|
|
9
|
+
dynamic = ["version"]
|
|
10
|
+
description = "CLI for the Spectackl Public REST API — for AI agents and operators"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
license = {text = "MIT"}
|
|
14
|
+
authors = [
|
|
15
|
+
{name = "Spectackl Engineering", email = "engineering@spectackl.ai"},
|
|
16
|
+
]
|
|
17
|
+
keywords = ["spectackl", "cli", "ai", "agents"]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Environment :: Console",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
29
|
+
]
|
|
30
|
+
# Every entry here is imported by src/spectackl. pydantic used to be listed for the
|
|
31
|
+
# generated OpenAPI client, which is no longer distributed — the CLI itself never
|
|
32
|
+
# imported it, and it is a compiled dependency, so carrying it taxed every install.
|
|
33
|
+
dependencies = [
|
|
34
|
+
"typer>=0.12",
|
|
35
|
+
"httpx>=0.27",
|
|
36
|
+
"rich>=13.0",
|
|
37
|
+
"pyyaml>=6.0",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://spectackl.ai"
|
|
42
|
+
Documentation = "https://docs.spectackl.ai"
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
spectackl = "spectackl.cli:app"
|
|
46
|
+
|
|
47
|
+
[project.optional-dependencies]
|
|
48
|
+
dev = [
|
|
49
|
+
"pytest>=8.0",
|
|
50
|
+
"pytest-httpx>=0.30",
|
|
51
|
+
"mypy>=1.10",
|
|
52
|
+
"ruff>=0.5",
|
|
53
|
+
"build>=1.0",
|
|
54
|
+
"twine>=5.0",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.setuptools.dynamic]
|
|
58
|
+
version = {attr = "spectackl.__version__"}
|
|
59
|
+
|
|
60
|
+
# Ship ONLY the CLI package. `src/spectackl_client/` is a separate, generated
|
|
61
|
+
# OpenAPI client kept in the repo for the CI drift check (scripts/regenerate-client.sh)
|
|
62
|
+
# — nothing in the CLI imports it; every request goes through httpx directly. Shipping
|
|
63
|
+
# it put two unused top-level packages (`spectackl_client`, `spectackl_public_api_client`)
|
|
64
|
+
# into the site-packages of everyone who installs us, one of them twice.
|
|
65
|
+
#
|
|
66
|
+
# The explicit include is what keeps it out: a bare `where = ["src"]` would pick up
|
|
67
|
+
# `spectackl_client` again, and a glob like "spectackl*" would match it too.
|
|
68
|
+
[tool.setuptools.packages.find]
|
|
69
|
+
where = ["src"]
|
|
70
|
+
include = ["spectackl", "spectackl.*"]
|
|
71
|
+
|
|
72
|
+
[tool.setuptools.package-dir]
|
|
73
|
+
"" = "src"
|
|
74
|
+
|
|
75
|
+
[tool.ruff]
|
|
76
|
+
line-length = 100
|
|
77
|
+
target-version = "py310"
|
|
78
|
+
|
|
79
|
+
[tool.ruff.lint]
|
|
80
|
+
select = ["E", "F", "I", "UP", "B", "C4", "SIM"]
|
|
81
|
+
ignore = [
|
|
82
|
+
"E501",
|
|
83
|
+
# B904: typer.Exit is not a re-raise; it is a flow-control mechanism, not a chained exception
|
|
84
|
+
"B904",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[tool.mypy]
|
|
88
|
+
python_version = "3.10"
|
|
89
|
+
strict = false
|
|
90
|
+
warn_return_any = true
|
|
91
|
+
warn_unused_ignores = true
|
|
92
|
+
ignore_missing_imports = true
|
|
93
|
+
|
|
94
|
+
[tool.pytest.ini_options]
|
|
95
|
+
testpaths = ["tests"]
|
|
96
|
+
python_files = ["test_*.py"]
|
|
97
|
+
python_functions = ["test_*"]
|
|
98
|
+
addopts = ["-v"]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""API key resolution for the Spectackl CLI.
|
|
2
|
+
|
|
3
|
+
Resolution order (highest to lowest priority):
|
|
4
|
+
1. --api-key CLI flag
|
|
5
|
+
2. SPECTACKL_API_KEY environment variable
|
|
6
|
+
3. api_key field in .spectackl/settings.yaml (repo root, walked up from CWD)
|
|
7
|
+
4. api_key field in ~/.config/spectackl/settings.yaml
|
|
8
|
+
5. Error if none found (exit code 10)
|
|
9
|
+
|
|
10
|
+
Any of the file-based values may be a ${VAR} reference resolved from the named
|
|
11
|
+
scalars in ~/.config/spectackl/settings.yaml (see spectackl.config.load_config).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import typer
|
|
17
|
+
|
|
18
|
+
from spectackl import exit_codes
|
|
19
|
+
from spectackl.config import SpectacklConfig
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def resolve_api_key(config: SpectacklConfig) -> str:
|
|
23
|
+
"""Return the API key or exit with code 10.
|
|
24
|
+
|
|
25
|
+
Raises:
|
|
26
|
+
typer.Exit: with code 10 (AUTH_REQUIRED) if no API key is found.
|
|
27
|
+
"""
|
|
28
|
+
if config.api_key:
|
|
29
|
+
return config.api_key
|
|
30
|
+
|
|
31
|
+
typer.echo(
|
|
32
|
+
"Error: API key not found.\n"
|
|
33
|
+
" Run 'spectackl init' to create the config files, or\n"
|
|
34
|
+
" set --api-key, the SPECTACKL_API_KEY env var,\n"
|
|
35
|
+
" or api_key in .spectackl/settings.yaml (repo root) / ~/.config/spectackl/settings.yaml.\n"
|
|
36
|
+
" api_key may be a ${VAR} reference resolved from ~/.config/spectackl/settings.yaml.",
|
|
37
|
+
err=True,
|
|
38
|
+
)
|
|
39
|
+
raise typer.Exit(code=exit_codes.AUTH_REQUIRED)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def resolve_project_id(config: SpectacklConfig) -> str:
|
|
43
|
+
"""Return the project ID or exit with code 2 (usage error).
|
|
44
|
+
|
|
45
|
+
Resolution order is already applied by load_config:
|
|
46
|
+
--project flag > SPECTACKL_PROJECT_ID env > .spectackl/settings.yaml > global config.
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
typer.Exit: with code 2 (USAGE_ERROR) if no project_id is found.
|
|
50
|
+
"""
|
|
51
|
+
if config.project_id:
|
|
52
|
+
return config.project_id
|
|
53
|
+
|
|
54
|
+
typer.echo(
|
|
55
|
+
"Error: project_id not found.\n"
|
|
56
|
+
" Run 'spectackl init --project <key>', or\n"
|
|
57
|
+
" set --project, the SPECTACKL_PROJECT_ID env var,\n"
|
|
58
|
+
" or add project_id (or project_key) to .spectackl/settings.yaml in the repo root.",
|
|
59
|
+
err=True,
|
|
60
|
+
)
|
|
61
|
+
raise typer.Exit(code=exit_codes.USAGE_ERROR)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def validate_api_key_format(api_key: str) -> bool:
|
|
65
|
+
"""Return True if the key matches the spc_<64hex> format.
|
|
66
|
+
|
|
67
|
+
Does not contact the server. Used for local pre-flight validation only.
|
|
68
|
+
"""
|
|
69
|
+
if not api_key.startswith("spc_"):
|
|
70
|
+
return False
|
|
71
|
+
suffix = api_key[4:]
|
|
72
|
+
if len(suffix) != 64:
|
|
73
|
+
return False
|
|
74
|
+
return all(c in "0123456789abcdefABCDEF" for c in suffix)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Spectackl CLI entry point.
|
|
2
|
+
|
|
3
|
+
The Spectackl CLI provides commands for AI agents and operators to interact
|
|
4
|
+
with the Spectackl Public REST API.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
spectackl init # create the config files, first thing on a new machine
|
|
8
|
+
spectackl assets sync # pull the project's agents and skills into ./.claude/
|
|
9
|
+
spectackl --help
|
|
10
|
+
spectackl search "SSO login" # hybrid content search over the project
|
|
11
|
+
spectackl artifact --help
|
|
12
|
+
spectackl context --help
|
|
13
|
+
spectackl task --help
|
|
14
|
+
|
|
15
|
+
Global flags (available on all commands):
|
|
16
|
+
--api-key TEXT Spectackl API key (spc_<64hex>)
|
|
17
|
+
--base-url TEXT API base URL (default: http://localhost:8080/api/v1)
|
|
18
|
+
--json / --no-json Output raw JSON (recommended for scripts and agents)
|
|
19
|
+
--no-color Disable color output
|
|
20
|
+
-v / -vv Increase verbosity
|
|
21
|
+
|
|
22
|
+
Authentication priority:
|
|
23
|
+
1. --api-key flag
|
|
24
|
+
2. SPECTACKL_API_KEY environment variable
|
|
25
|
+
3. api_key in ~/.config/spectackl/settings.yaml
|
|
26
|
+
|
|
27
|
+
Exit codes:
|
|
28
|
+
0 Success
|
|
29
|
+
1 Generic error
|
|
30
|
+
2 Usage error (bad flag, missing argument)
|
|
31
|
+
10 Authentication required or invalid (HTTP 401)
|
|
32
|
+
11 Authorization denied (HTTP 403)
|
|
33
|
+
20 Validation error (HTTP 400)
|
|
34
|
+
30 Not found (HTTP 404)
|
|
35
|
+
31 Conflict (HTTP 409)
|
|
36
|
+
40 Upstream unavailable or timeout (HTTP 502/504)
|
|
37
|
+
50 Internal facade error (HTTP 5xx)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from __future__ import annotations
|
|
41
|
+
|
|
42
|
+
from typing import Annotated
|
|
43
|
+
|
|
44
|
+
import typer
|
|
45
|
+
|
|
46
|
+
from spectackl import __version__
|
|
47
|
+
from spectackl.commands import artifact, assets, context, daemon, init, relation
|
|
48
|
+
from spectackl.commands import rsync as rsync_cmd
|
|
49
|
+
from spectackl.commands import search as search_cmd
|
|
50
|
+
from spectackl.commands import task
|
|
51
|
+
|
|
52
|
+
# Root typer app
|
|
53
|
+
app = typer.Typer(
|
|
54
|
+
name="spectackl",
|
|
55
|
+
help=(
|
|
56
|
+
"Spectackl CLI — interact with the Spectackl Public REST API.\n\n"
|
|
57
|
+
"Designed for AI agents and operators. Use --json for machine-readable output."
|
|
58
|
+
),
|
|
59
|
+
no_args_is_help=True,
|
|
60
|
+
add_completion=True,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Register subcommand groups
|
|
64
|
+
app.add_typer(init.app, name="init")
|
|
65
|
+
app.add_typer(artifact.app, name="artifact")
|
|
66
|
+
app.add_typer(context.app, name="context")
|
|
67
|
+
app.add_typer(assets.app, name="assets")
|
|
68
|
+
app.add_typer(relation.app, name="relation")
|
|
69
|
+
app.add_typer(task.app, name="task")
|
|
70
|
+
app.add_typer(daemon.app, name="daemon")
|
|
71
|
+
|
|
72
|
+
# Top-level content search command (mirrors GET /api/v1/search)
|
|
73
|
+
app.command(name="search")(search_cmd.search)
|
|
74
|
+
|
|
75
|
+
# Bi-directional file synchronization. Distinct from `assets sync`, which pulls
|
|
76
|
+
# agent/skill definitions one way.
|
|
77
|
+
app.command(name="rsync")(rsync_cmd.rsync)
|
|
78
|
+
|
|
79
|
+
# Deprecated: `spectackl sync` was renamed to `spectackl assets sync`. The same
|
|
80
|
+
# function is registered twice so the two entry points cannot drift; it is hidden
|
|
81
|
+
# from --help and warns when invoked, and will be removed in a later release.
|
|
82
|
+
app.command(
|
|
83
|
+
name=assets.DEPRECATED_ALIAS,
|
|
84
|
+
hidden=True,
|
|
85
|
+
help="Deprecated alias for `spectackl assets sync`.",
|
|
86
|
+
)(assets.sync)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _version_callback(value: bool) -> None:
|
|
90
|
+
if value:
|
|
91
|
+
typer.echo(f"spectackl {__version__}")
|
|
92
|
+
raise typer.Exit()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@app.callback()
|
|
96
|
+
def main(
|
|
97
|
+
version: Annotated[
|
|
98
|
+
bool | None,
|
|
99
|
+
typer.Option(
|
|
100
|
+
"--version",
|
|
101
|
+
"-V",
|
|
102
|
+
help="Show version and exit.",
|
|
103
|
+
callback=_version_callback,
|
|
104
|
+
is_eager=True,
|
|
105
|
+
),
|
|
106
|
+
] = None,
|
|
107
|
+
) -> None:
|
|
108
|
+
"""Spectackl CLI — AI agent and operator interface to the Spectackl platform."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# spectackl.commands package
|