fluxloop-cli 0.3.10__tar.gz → 0.4.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.
- fluxloop_cli-0.4.0/.fluxloop/context.json +4 -0
- fluxloop_cli-0.4.0/.gitignore +178 -0
- fluxloop_cli-0.4.0/PKG-INFO +285 -0
- fluxloop_cli-0.4.0/README.md +253 -0
- fluxloop_cli-0.4.0/build.sh +21 -0
- fluxloop_cli-0.4.0/fluxloop_cli/__init__.py +3 -0
- fluxloop_cli-0.4.0/fluxloop_cli/api_utils.py +85 -0
- fluxloop_cli-0.4.0/fluxloop_cli/auth/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/auth/device_flow.py +154 -0
- fluxloop_cli-0.4.0/fluxloop_cli/auth/token_store.py +109 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/apikeys.py +135 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/auth.py +224 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/bundles.py +121 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/context.py +43 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/data.py +333 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/evaluate.py +308 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/init.py +99 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/inputs.py +313 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/intent.py +159 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/manifests.py +159 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/personas.py +120 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/projects.py +178 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/run.py +198 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/scenario_resolution.py +149 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/scenarios.py +214 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/skill.py +805 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/sync_cmd.py +257 -0
- fluxloop_cli-0.4.0/fluxloop_cli/commands/test_cmd.py +499 -0
- fluxloop_cli-0.4.0/fluxloop_cli/config/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/config/loader.py +205 -0
- fluxloop_cli-0.4.0/fluxloop_cli/config/schema.py +94 -0
- fluxloop_cli-0.4.0/fluxloop_cli/constants.py +42 -0
- fluxloop_cli-0.4.0/fluxloop_cli/contract/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/contract/behavior_matcher.py +275 -0
- fluxloop_cli-0.4.0/fluxloop_cli/contract/safe_regex.py +81 -0
- fluxloop_cli-0.4.0/fluxloop_cli/contract/static_linter.py +229 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/conversation_runner.py +170 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/executor.py +67 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/function_executor.py +226 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/process_executor.py +180 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/skill_executor.py +310 -0
- fluxloop_cli-0.4.0/fluxloop_cli/core/user_simulator.py +187 -0
- fluxloop_cli-0.4.0/fluxloop_cli/main.py +82 -0
- fluxloop_cli-0.4.0/fluxloop_cli/path_safety.py +26 -0
- fluxloop_cli-0.4.0/fluxloop_cli/result/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/result/error_writer.py +74 -0
- fluxloop_cli-0.4.0/fluxloop_cli/result/metadata.py +25 -0
- fluxloop_cli-0.4.0/fluxloop_cli/result/summary_writer.py +70 -0
- fluxloop_cli-0.4.0/fluxloop_cli/result/trace_writer.py +69 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/client.py +163 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/data_api.py +181 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/inputs_api.py +30 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/intent_api.py +31 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/meta.py +19 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/poller.py +53 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/puller.py +95 -0
- fluxloop_cli-0.4.0/fluxloop_cli/sync/uploader.py +228 -0
- fluxloop_cli-0.4.0/fluxloop_cli/workspace/__init__.py +0 -0
- fluxloop_cli-0.4.0/fluxloop_cli/workspace/context.py +286 -0
- fluxloop_cli-0.4.0/fluxloop_cli/workspace/sandbox.py +161 -0
- {fluxloop_cli-0.3.10 → fluxloop_cli-0.4.0}/pyproject.toml +29 -50
- fluxloop_cli-0.4.0/tests/__init__.py +0 -0
- fluxloop_cli-0.4.0/tests/conftest.py +53 -0
- fluxloop_cli-0.4.0/tests/test_api_utils.py +68 -0
- fluxloop_cli-0.4.0/tests/test_behavior_matcher.py +349 -0
- fluxloop_cli-0.4.0/tests/test_config_loader.py +180 -0
- fluxloop_cli-0.4.0/tests/test_config_schema.py +180 -0
- fluxloop_cli-0.4.0/tests/test_conversation_runner.py +134 -0
- fluxloop_cli-0.4.0/tests/test_executor.py +74 -0
- fluxloop_cli-0.4.0/tests/test_function_executor.py +179 -0
- fluxloop_cli-0.4.0/tests/test_path_safety.py +32 -0
- fluxloop_cli-0.4.0/tests/test_phase3_commands.py +347 -0
- fluxloop_cli-0.4.0/tests/test_phase6_backend_commands.py +223 -0
- fluxloop_cli-0.4.0/tests/test_process_executor.py +117 -0
- fluxloop_cli-0.4.0/tests/test_protocol_schemas.py +364 -0
- fluxloop_cli-0.4.0/tests/test_result_writers.py +471 -0
- fluxloop_cli-0.4.0/tests/test_safe_regex.py +25 -0
- fluxloop_cli-0.4.0/tests/test_sandbox.py +171 -0
- fluxloop_cli-0.4.0/tests/test_scenario_resolution.py +112 -0
- fluxloop_cli-0.4.0/tests/test_skill_commands.py +485 -0
- fluxloop_cli-0.4.0/tests/test_skill_executor.py +357 -0
- fluxloop_cli-0.4.0/tests/test_static_linter.py +280 -0
- fluxloop_cli-0.4.0/tests/test_sync_client.py +109 -0
- fluxloop_cli-0.4.0/tests/test_sync_poller.py +66 -0
- fluxloop_cli-0.4.0/tests/test_sync_puller.py +53 -0
- fluxloop_cli-0.4.0/tests/test_sync_uploader.py +137 -0
- fluxloop_cli-0.4.0/tests/test_test_results.py +137 -0
- fluxloop_cli-0.4.0/tests/test_token_store.py +140 -0
- fluxloop_cli-0.4.0/tests/test_user_simulator.py +75 -0
- fluxloop_cli-0.4.0/tests/test_workspace_context.py +215 -0
- fluxloop_cli-0.4.0/uv.lock +1204 -0
- fluxloop_cli-0.3.10/PKG-INFO +0 -170
- fluxloop_cli-0.3.10/README.md +0 -130
- fluxloop_cli-0.3.10/fluxloop_cli/__init__.py +0 -9
- fluxloop_cli-0.3.10/fluxloop_cli/api_utils.py +0 -231
- fluxloop_cli-0.3.10/fluxloop_cli/arg_binder.py +0 -353
- fluxloop_cli-0.3.10/fluxloop_cli/auth_manager.py +0 -410
- fluxloop_cli-0.3.10/fluxloop_cli/commands/__init__.py +0 -45
- fluxloop_cli-0.3.10/fluxloop_cli/commands/apikeys.py +0 -236
- fluxloop_cli-0.3.10/fluxloop_cli/commands/auth.py +0 -338
- fluxloop_cli-0.3.10/fluxloop_cli/commands/bundles.py +0 -443
- fluxloop_cli-0.3.10/fluxloop_cli/commands/config.py +0 -411
- fluxloop_cli-0.3.10/fluxloop_cli/commands/context.py +0 -122
- fluxloop_cli-0.3.10/fluxloop_cli/commands/criteria.py +0 -58
- fluxloop_cli-0.3.10/fluxloop_cli/commands/data.py +0 -692
- fluxloop_cli-0.3.10/fluxloop_cli/commands/evaluate.py +0 -188
- fluxloop_cli-0.3.10/fluxloop_cli/commands/generate.py +0 -224
- fluxloop_cli-0.3.10/fluxloop_cli/commands/init.py +0 -275
- fluxloop_cli-0.3.10/fluxloop_cli/commands/inputs.py +0 -713
- fluxloop_cli-0.3.10/fluxloop_cli/commands/local_context.py +0 -167
- fluxloop_cli-0.3.10/fluxloop_cli/commands/personas.py +0 -331
- fluxloop_cli-0.3.10/fluxloop_cli/commands/projects.py +0 -279
- fluxloop_cli-0.3.10/fluxloop_cli/commands/run.py +0 -501
- fluxloop_cli-0.3.10/fluxloop_cli/commands/scenarios.py +0 -603
- fluxloop_cli-0.3.10/fluxloop_cli/commands/status.py +0 -263
- fluxloop_cli-0.3.10/fluxloop_cli/commands/sync.py +0 -944
- fluxloop_cli-0.3.10/fluxloop_cli/commands/test.py +0 -521
- fluxloop_cli-0.3.10/fluxloop_cli/common_options.py +0 -73
- fluxloop_cli-0.3.10/fluxloop_cli/config_loader.py +0 -357
- fluxloop_cli-0.3.10/fluxloop_cli/config_schema.py +0 -78
- fluxloop_cli-0.3.10/fluxloop_cli/constants.py +0 -49
- fluxloop_cli-0.3.10/fluxloop_cli/context_manager.py +0 -583
- fluxloop_cli-0.3.10/fluxloop_cli/conversation_supervisor.py +0 -389
- fluxloop_cli-0.3.10/fluxloop_cli/environment.py +0 -71
- fluxloop_cli-0.3.10/fluxloop_cli/http_client.py +0 -157
- fluxloop_cli-0.3.10/fluxloop_cli/input_generator.py +0 -261
- fluxloop_cli-0.3.10/fluxloop_cli/language.py +0 -17
- fluxloop_cli-0.3.10/fluxloop_cli/llm_generator.py +0 -417
- fluxloop_cli-0.3.10/fluxloop_cli/main.py +0 -146
- fluxloop_cli-0.3.10/fluxloop_cli/progress.py +0 -138
- fluxloop_cli-0.3.10/fluxloop_cli/project_paths.py +0 -259
- fluxloop_cli-0.3.10/fluxloop_cli/runner.py +0 -1493
- fluxloop_cli-0.3.10/fluxloop_cli/target_loader.py +0 -157
- fluxloop_cli-0.3.10/fluxloop_cli/templates.py +0 -586
- fluxloop_cli-0.3.10/fluxloop_cli/testing/__init__.py +0 -24
- fluxloop_cli-0.3.10/fluxloop_cli/testing/pytest_plugin.py +0 -432
- fluxloop_cli-0.3.10/fluxloop_cli/testing/types.py +0 -188
- fluxloop_cli-0.3.10/fluxloop_cli/token_usage.py +0 -182
- fluxloop_cli-0.3.10/fluxloop_cli/turns.py +0 -282
- fluxloop_cli-0.3.10/fluxloop_cli/validators.py +0 -41
- fluxloop_cli-0.3.10/fluxloop_cli.egg-info/PKG-INFO +0 -170
- fluxloop_cli-0.3.10/fluxloop_cli.egg-info/SOURCES.txt +0 -74
- fluxloop_cli-0.3.10/fluxloop_cli.egg-info/dependency_links.txt +0 -1
- fluxloop_cli-0.3.10/fluxloop_cli.egg-info/entry_points.txt +0 -2
- fluxloop_cli-0.3.10/fluxloop_cli.egg-info/requires.txt +0 -24
- fluxloop_cli-0.3.10/fluxloop_cli.egg-info/top_level.txt +0 -1
- fluxloop_cli-0.3.10/setup.cfg +0 -4
- fluxloop_cli-0.3.10/tests/test_analysis_recommendations.py +0 -82
- fluxloop_cli-0.3.10/tests/test_arg_binder.py +0 -207
- fluxloop_cli-0.3.10/tests/test_config_command.py +0 -95
- fluxloop_cli-0.3.10/tests/test_conversation_supervisor.py +0 -37
- fluxloop_cli-0.3.10/tests/test_evaluate_command.py +0 -471
- fluxloop_cli-0.3.10/tests/test_evaluation_llm.py +0 -93
- fluxloop_cli-0.3.10/tests/test_init_pytest_template.py +0 -62
- fluxloop_cli-0.3.10/tests/test_input_generator.py +0 -158
- fluxloop_cli-0.3.10/tests/test_inputs_command.py +0 -124
- fluxloop_cli-0.3.10/tests/test_personas_command.py +0 -95
- fluxloop_cli-0.3.10/tests/test_projects_language.py +0 -81
- fluxloop_cli-0.3.10/tests/test_prompt_library.py +0 -29
- fluxloop_cli-0.3.10/tests/test_pytest_plugin.py +0 -103
- fluxloop_cli-0.3.10/tests/test_run_command.py +0 -131
- fluxloop_cli-0.3.10/tests/test_runner_multi_turn.py +0 -243
- fluxloop_cli-0.3.10/tests/test_scenarios_language.py +0 -252
- fluxloop_cli-0.3.10/tests/test_success_criteria.py +0 -54
- fluxloop_cli-0.3.10/tests/test_target_loader.py +0 -89
- fluxloop_cli-0.3.10/tests/test_testing_types.py +0 -66
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
bin/
|
|
11
|
+
build/
|
|
12
|
+
!apps/web/src/app/(app)/build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
/lib/
|
|
19
|
+
/lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py,cover
|
|
51
|
+
.hypothesistests/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
.python-version
|
|
87
|
+
|
|
88
|
+
# pipenv
|
|
89
|
+
# According to pypa/pipenv#1173, it is recommended not to include Pipfile.lock in version control.
|
|
90
|
+
# However, in cases where the package is not being distributed, it can be useful.
|
|
91
|
+
#Pipfile.lock
|
|
92
|
+
|
|
93
|
+
# poetry
|
|
94
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
95
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
96
|
+
#poetry.lock
|
|
97
|
+
|
|
98
|
+
# pdm
|
|
99
|
+
.pdm.toml
|
|
100
|
+
.pdm-python
|
|
101
|
+
.pdm-build/
|
|
102
|
+
|
|
103
|
+
# PEP 582; used by e.g. github.com/fannheyward/coc-pyright
|
|
104
|
+
__pypackages__/
|
|
105
|
+
|
|
106
|
+
# Celery stuff
|
|
107
|
+
celerybeat-schedule
|
|
108
|
+
celerybeat.pid
|
|
109
|
+
|
|
110
|
+
# SageMath parsed files
|
|
111
|
+
*.sage.py
|
|
112
|
+
|
|
113
|
+
# Environments
|
|
114
|
+
.env
|
|
115
|
+
.venv
|
|
116
|
+
env/
|
|
117
|
+
venv/
|
|
118
|
+
ENV/
|
|
119
|
+
env.bak/
|
|
120
|
+
venv.bak/
|
|
121
|
+
|
|
122
|
+
# Spyder project settings
|
|
123
|
+
.spyderproject
|
|
124
|
+
.spyproject
|
|
125
|
+
|
|
126
|
+
# Rope project settings
|
|
127
|
+
.ropeproject
|
|
128
|
+
|
|
129
|
+
# mkdocs documentation
|
|
130
|
+
/site
|
|
131
|
+
|
|
132
|
+
# mypy
|
|
133
|
+
.mypy_cache/
|
|
134
|
+
.dmypy.json
|
|
135
|
+
dmypy.json
|
|
136
|
+
|
|
137
|
+
# Pyre type checker
|
|
138
|
+
.pyre/
|
|
139
|
+
|
|
140
|
+
# pytype static type analyzer
|
|
141
|
+
.pytype/
|
|
142
|
+
|
|
143
|
+
# Cython debug symbols
|
|
144
|
+
cython_debug/
|
|
145
|
+
|
|
146
|
+
# Node.js
|
|
147
|
+
node_modules/
|
|
148
|
+
npm-debug.log*
|
|
149
|
+
yarn-debug.log*
|
|
150
|
+
yarn-error.log*
|
|
151
|
+
.pnpm-debug.log*
|
|
152
|
+
.env.local
|
|
153
|
+
.env.development.local
|
|
154
|
+
.env.test.local
|
|
155
|
+
.env.production.local
|
|
156
|
+
|
|
157
|
+
# OS
|
|
158
|
+
.DS_Store
|
|
159
|
+
.DS_Store?
|
|
160
|
+
._*
|
|
161
|
+
.Spotlight-V100
|
|
162
|
+
.Trashes
|
|
163
|
+
ehthumbs.db
|
|
164
|
+
Thumbs.db
|
|
165
|
+
|
|
166
|
+
# Project specific
|
|
167
|
+
ref/
|
|
168
|
+
@ref/
|
|
169
|
+
|
|
170
|
+
services/backend/env.sample
|
|
171
|
+
|
|
172
|
+
# Next.js
|
|
173
|
+
.next/
|
|
174
|
+
out/
|
|
175
|
+
.vercel
|
|
176
|
+
thoughts/
|
|
177
|
+
|
|
178
|
+
persona_images/
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fluxloop-cli
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: FluxLoop CLI — Agent evaluation framework
|
|
5
|
+
Project-URL: Homepage, https://github.com/chuckgu/fluxloop
|
|
6
|
+
Project-URL: Documentation, https://docs.fluxloop.dev
|
|
7
|
+
Project-URL: Repository, https://github.com/chuckgu/fluxloop
|
|
8
|
+
Project-URL: Issues, https://github.com/chuckgu/fluxloop/issues
|
|
9
|
+
Author-email: FluxLoop Team <team@fluxloop.dev>
|
|
10
|
+
License: Apache-2.0
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: claude-agent-sdk>=0.1.0
|
|
19
|
+
Requires-Dist: httpx>=0.27
|
|
20
|
+
Requires-Dist: pydantic>=2.0
|
|
21
|
+
Requires-Dist: python-dotenv>=1.0
|
|
22
|
+
Requires-Dist: rich>=13.0
|
|
23
|
+
Requires-Dist: ruamel-yaml>=0.18
|
|
24
|
+
Requires-Dist: typer>=0.9
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# FluxLoop CLI
|
|
34
|
+
|
|
35
|
+
Command-line interface for the FluxLoop agent evaluation framework.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install fluxloop-cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Authenticate
|
|
47
|
+
fluxloop auth login
|
|
48
|
+
|
|
49
|
+
# Create a project and scenario
|
|
50
|
+
fluxloop projects create --name my-project
|
|
51
|
+
fluxloop init scenario smoke-test
|
|
52
|
+
fluxloop scenarios create --name smoke-test --goal "Validate agent accuracy"
|
|
53
|
+
|
|
54
|
+
# Run a skill test
|
|
55
|
+
fluxloop skill validate ./SKILL.md
|
|
56
|
+
fluxloop skill test ./SKILL.md --input "Generate a summary" --copy-files src/
|
|
57
|
+
|
|
58
|
+
# Full test workflow (pull inputs → run → push results)
|
|
59
|
+
fluxloop test --scenario smoke-test
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Commands
|
|
63
|
+
|
|
64
|
+
### Core
|
|
65
|
+
|
|
66
|
+
| Command | Description |
|
|
67
|
+
|---------|-------------|
|
|
68
|
+
| `fluxloop run` | Run agent over configured inputs using the selected executor |
|
|
69
|
+
| `fluxloop skill validate` | Validate SKILL.md against static contracts |
|
|
70
|
+
| `fluxloop skill test` | Execute a skill in sandbox with behavior contract evaluation |
|
|
71
|
+
| `fluxloop skill benchmark` | Run N benchmark iterations and report stats |
|
|
72
|
+
| `fluxloop init scenario <name>` | Scaffold a new scenario directory |
|
|
73
|
+
| `fluxloop context show` | Display current project, scenario, and workspace state |
|
|
74
|
+
| `fluxloop test` | Full workflow: pull → run → push |
|
|
75
|
+
| `fluxloop test results` | View local or remote test results |
|
|
76
|
+
| `fluxloop evaluate` | Trigger server-side evaluation and wait for completion |
|
|
77
|
+
|
|
78
|
+
### Authentication & Projects
|
|
79
|
+
|
|
80
|
+
| Command | Description |
|
|
81
|
+
|---------|-------------|
|
|
82
|
+
| `fluxloop auth login` | Authenticate via device code flow |
|
|
83
|
+
| `fluxloop auth logout` | Remove stored credentials |
|
|
84
|
+
| `fluxloop auth status` | Show login state and token expiry |
|
|
85
|
+
| `fluxloop projects list` | List available projects |
|
|
86
|
+
| `fluxloop projects create` | Create a new project |
|
|
87
|
+
| `fluxloop projects select` | Set active project |
|
|
88
|
+
| `fluxloop apikeys create` | Generate an API key (saved to `.fluxloop/.env`) |
|
|
89
|
+
| `fluxloop apikeys list` | List existing API keys |
|
|
90
|
+
|
|
91
|
+
### Scenarios & Data Pipeline
|
|
92
|
+
|
|
93
|
+
| Command | Description |
|
|
94
|
+
|---------|-------------|
|
|
95
|
+
| `fluxloop scenarios create` | Create a scenario on the server |
|
|
96
|
+
| `fluxloop scenarios select` | Set active scenario locally |
|
|
97
|
+
| `fluxloop scenarios refine` | Refine scenario contracts |
|
|
98
|
+
| `fluxloop personas suggest` | Generate user personas via LLM |
|
|
99
|
+
| `fluxloop inputs synthesize` | Generate test inputs from personas |
|
|
100
|
+
| `fluxloop inputs list` | List available input sets |
|
|
101
|
+
| `fluxloop inputs qc` | Quality-check generated inputs |
|
|
102
|
+
| `fluxloop inputs refine` | Refine inputs iteratively |
|
|
103
|
+
| `fluxloop bundles publish` | Publish input sets as versioned bundles |
|
|
104
|
+
| `fluxloop bundles list` | List published bundles |
|
|
105
|
+
| `fluxloop manifests show` | Display current manifest |
|
|
106
|
+
| `fluxloop manifests publish` | Publish manifest to server |
|
|
107
|
+
| `fluxloop data push` | Upload knowledge or ground-truth data |
|
|
108
|
+
| `fluxloop data bind` | Bind uploaded data to a scenario |
|
|
109
|
+
| `fluxloop data gt status` | Check ground-truth materialization status |
|
|
110
|
+
| `fluxloop intent refine` | Refine agent profile and test intent |
|
|
111
|
+
|
|
112
|
+
### Sync
|
|
113
|
+
|
|
114
|
+
| Command | Description |
|
|
115
|
+
|---------|-------------|
|
|
116
|
+
| `fluxloop sync pull` | Pull bundle (inputs, personas, criteria) from server |
|
|
117
|
+
| `fluxloop sync push` | Upload test results to server |
|
|
118
|
+
|
|
119
|
+
## Configuration
|
|
120
|
+
|
|
121
|
+
Scenario configuration lives in YAML files under `scenarios/<name>/configs/`:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
scenarios/
|
|
125
|
+
smoke-test/
|
|
126
|
+
configs/
|
|
127
|
+
simulation.yaml # Runner, iterations, conversation settings
|
|
128
|
+
input.yaml # Input source and items
|
|
129
|
+
scenario.yaml # Scenario metadata
|
|
130
|
+
contracts/
|
|
131
|
+
static.yaml # SKILL.md structure rules
|
|
132
|
+
behavior.yaml # Execution assertions
|
|
133
|
+
pulled/ # Data from sync pull
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Runner Types
|
|
137
|
+
|
|
138
|
+
Configure the executor in `simulation.yaml`:
|
|
139
|
+
|
|
140
|
+
**Function** — call a Python handler directly:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
runner:
|
|
144
|
+
type: function
|
|
145
|
+
target: "my_agent:handler"
|
|
146
|
+
timeout_seconds: 30
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Skill** — run a SKILL.md in Claude Agent SDK sandbox:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
runner:
|
|
153
|
+
type: skill
|
|
154
|
+
skill_path: ./SKILL.md
|
|
155
|
+
harness: claude
|
|
156
|
+
allowed_tools: ["Read", "Write", "Shell"]
|
|
157
|
+
skill_max_turns: 10
|
|
158
|
+
budget: 0.50
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Process** — invoke a subprocess via NDJSON protocol:
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
runner:
|
|
165
|
+
type: process
|
|
166
|
+
command: ["python", "agent.py"]
|
|
167
|
+
protocol: ndjson
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Input Sources
|
|
171
|
+
|
|
172
|
+
```yaml
|
|
173
|
+
input:
|
|
174
|
+
source: inline # inline | generated | bundle | pulled
|
|
175
|
+
items:
|
|
176
|
+
- text: "Hello, summarize this document"
|
|
177
|
+
- text: "What are the key takeaways?"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
When `source: pulled`, inputs are loaded from `pulled/inputs.json` after `sync pull`.
|
|
181
|
+
|
|
182
|
+
### Environment Variable Substitution
|
|
183
|
+
|
|
184
|
+
YAML config values support `${VAR}` syntax, resolved from environment variables.
|
|
185
|
+
|
|
186
|
+
## Contracts
|
|
187
|
+
|
|
188
|
+
### Static Contract
|
|
189
|
+
|
|
190
|
+
Validates SKILL.md structure before execution:
|
|
191
|
+
|
|
192
|
+
- Required sections (e.g., `# Purpose`, `# Instructions`)
|
|
193
|
+
- File size limits
|
|
194
|
+
- Encoding checks
|
|
195
|
+
- Forbidden pattern detection
|
|
196
|
+
|
|
197
|
+
### Behavior Contract
|
|
198
|
+
|
|
199
|
+
Asserts conditions on execution results:
|
|
200
|
+
|
|
201
|
+
- `tool_called` / `tool_not_called`
|
|
202
|
+
- `turn_count` (min/max)
|
|
203
|
+
- `output_contains` / `output_matches`
|
|
204
|
+
- `file_exists`
|
|
205
|
+
- `cost_below` / `duration_below`
|
|
206
|
+
|
|
207
|
+
## Authentication
|
|
208
|
+
|
|
209
|
+
FluxLoop uses OAuth device code flow for interactive login:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
fluxloop auth login # Opens browser for approval
|
|
213
|
+
fluxloop auth login --no-browser # Manual code entry
|
|
214
|
+
fluxloop auth login --no-wait # Save pending, resume later
|
|
215
|
+
fluxloop auth login --resume # Resume pending login
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Tokens are stored in `~/.fluxloop/auth.json`. For CI environments, use `FLUXLOOP_API_KEY` instead.
|
|
219
|
+
|
|
220
|
+
## Environment Variables
|
|
221
|
+
|
|
222
|
+
| Variable | Purpose |
|
|
223
|
+
|----------|---------|
|
|
224
|
+
| `FLUXLOOP_API_URL` | Backend API base URL |
|
|
225
|
+
| `FLUXLOOP_API_KEY` | API key for authenticated requests |
|
|
226
|
+
| `FLUXLOOP_SYNC_API_KEY` | API key specifically for sync operations |
|
|
227
|
+
| `ANTHROPIC_API_KEY` | Required for multi-turn UserSimulator |
|
|
228
|
+
| `OPENAI_API_KEY` | Alternative provider for UserSimulator |
|
|
229
|
+
|
|
230
|
+
Workspace-level variables can also be set in `.fluxloop/.env`.
|
|
231
|
+
|
|
232
|
+
## Output
|
|
233
|
+
|
|
234
|
+
Test runs produce standardized output in `.fluxloop/results/<experiment>-<timestamp>/`:
|
|
235
|
+
|
|
236
|
+
| File | Content |
|
|
237
|
+
|------|---------|
|
|
238
|
+
| `trace_summary.jsonl` | Per-run execution traces (tool calls, tokens, cost) |
|
|
239
|
+
| `summary.json` | Aggregated statistics (success rate, duration, cost) |
|
|
240
|
+
| `errors.json` | Failure inventory with diagnostics |
|
|
241
|
+
|
|
242
|
+
## Developing
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
cd cli/python
|
|
246
|
+
|
|
247
|
+
# Install dependencies
|
|
248
|
+
uv sync --group dev
|
|
249
|
+
|
|
250
|
+
# Run in development mode
|
|
251
|
+
uv run fluxloop --help
|
|
252
|
+
|
|
253
|
+
# Run tests
|
|
254
|
+
uv run pytest
|
|
255
|
+
|
|
256
|
+
# Lint
|
|
257
|
+
uv run ruff check .
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Building & Publishing
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# Build
|
|
264
|
+
uv build
|
|
265
|
+
|
|
266
|
+
# Publish to PyPI
|
|
267
|
+
uv publish
|
|
268
|
+
# or
|
|
269
|
+
twine upload dist/*
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Tech Stack
|
|
273
|
+
|
|
274
|
+
| Library | Purpose |
|
|
275
|
+
|---------|---------|
|
|
276
|
+
| [Typer](https://typer.tiangolo.com) | CLI framework |
|
|
277
|
+
| [Pydantic](https://docs.pydantic.dev) | Data validation |
|
|
278
|
+
| [ruamel.yaml](https://yaml.readthedocs.io) | YAML parsing |
|
|
279
|
+
| [httpx](https://www.python-httpx.org) | HTTP client |
|
|
280
|
+
| [Rich](https://rich.readthedocs.io) | Terminal output formatting |
|
|
281
|
+
| [claude-agent-sdk](https://pypi.org/project/claude-agent-sdk/) | Skill execution in Claude sandbox |
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
Apache-2.0
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# FluxLoop CLI
|
|
2
|
+
|
|
3
|
+
Command-line interface for the FluxLoop agent evaluation framework.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install fluxloop-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Authenticate
|
|
15
|
+
fluxloop auth login
|
|
16
|
+
|
|
17
|
+
# Create a project and scenario
|
|
18
|
+
fluxloop projects create --name my-project
|
|
19
|
+
fluxloop init scenario smoke-test
|
|
20
|
+
fluxloop scenarios create --name smoke-test --goal "Validate agent accuracy"
|
|
21
|
+
|
|
22
|
+
# Run a skill test
|
|
23
|
+
fluxloop skill validate ./SKILL.md
|
|
24
|
+
fluxloop skill test ./SKILL.md --input "Generate a summary" --copy-files src/
|
|
25
|
+
|
|
26
|
+
# Full test workflow (pull inputs → run → push results)
|
|
27
|
+
fluxloop test --scenario smoke-test
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
### Core
|
|
33
|
+
|
|
34
|
+
| Command | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| `fluxloop run` | Run agent over configured inputs using the selected executor |
|
|
37
|
+
| `fluxloop skill validate` | Validate SKILL.md against static contracts |
|
|
38
|
+
| `fluxloop skill test` | Execute a skill in sandbox with behavior contract evaluation |
|
|
39
|
+
| `fluxloop skill benchmark` | Run N benchmark iterations and report stats |
|
|
40
|
+
| `fluxloop init scenario <name>` | Scaffold a new scenario directory |
|
|
41
|
+
| `fluxloop context show` | Display current project, scenario, and workspace state |
|
|
42
|
+
| `fluxloop test` | Full workflow: pull → run → push |
|
|
43
|
+
| `fluxloop test results` | View local or remote test results |
|
|
44
|
+
| `fluxloop evaluate` | Trigger server-side evaluation and wait for completion |
|
|
45
|
+
|
|
46
|
+
### Authentication & Projects
|
|
47
|
+
|
|
48
|
+
| Command | Description |
|
|
49
|
+
|---------|-------------|
|
|
50
|
+
| `fluxloop auth login` | Authenticate via device code flow |
|
|
51
|
+
| `fluxloop auth logout` | Remove stored credentials |
|
|
52
|
+
| `fluxloop auth status` | Show login state and token expiry |
|
|
53
|
+
| `fluxloop projects list` | List available projects |
|
|
54
|
+
| `fluxloop projects create` | Create a new project |
|
|
55
|
+
| `fluxloop projects select` | Set active project |
|
|
56
|
+
| `fluxloop apikeys create` | Generate an API key (saved to `.fluxloop/.env`) |
|
|
57
|
+
| `fluxloop apikeys list` | List existing API keys |
|
|
58
|
+
|
|
59
|
+
### Scenarios & Data Pipeline
|
|
60
|
+
|
|
61
|
+
| Command | Description |
|
|
62
|
+
|---------|-------------|
|
|
63
|
+
| `fluxloop scenarios create` | Create a scenario on the server |
|
|
64
|
+
| `fluxloop scenarios select` | Set active scenario locally |
|
|
65
|
+
| `fluxloop scenarios refine` | Refine scenario contracts |
|
|
66
|
+
| `fluxloop personas suggest` | Generate user personas via LLM |
|
|
67
|
+
| `fluxloop inputs synthesize` | Generate test inputs from personas |
|
|
68
|
+
| `fluxloop inputs list` | List available input sets |
|
|
69
|
+
| `fluxloop inputs qc` | Quality-check generated inputs |
|
|
70
|
+
| `fluxloop inputs refine` | Refine inputs iteratively |
|
|
71
|
+
| `fluxloop bundles publish` | Publish input sets as versioned bundles |
|
|
72
|
+
| `fluxloop bundles list` | List published bundles |
|
|
73
|
+
| `fluxloop manifests show` | Display current manifest |
|
|
74
|
+
| `fluxloop manifests publish` | Publish manifest to server |
|
|
75
|
+
| `fluxloop data push` | Upload knowledge or ground-truth data |
|
|
76
|
+
| `fluxloop data bind` | Bind uploaded data to a scenario |
|
|
77
|
+
| `fluxloop data gt status` | Check ground-truth materialization status |
|
|
78
|
+
| `fluxloop intent refine` | Refine agent profile and test intent |
|
|
79
|
+
|
|
80
|
+
### Sync
|
|
81
|
+
|
|
82
|
+
| Command | Description |
|
|
83
|
+
|---------|-------------|
|
|
84
|
+
| `fluxloop sync pull` | Pull bundle (inputs, personas, criteria) from server |
|
|
85
|
+
| `fluxloop sync push` | Upload test results to server |
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Scenario configuration lives in YAML files under `scenarios/<name>/configs/`:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
scenarios/
|
|
93
|
+
smoke-test/
|
|
94
|
+
configs/
|
|
95
|
+
simulation.yaml # Runner, iterations, conversation settings
|
|
96
|
+
input.yaml # Input source and items
|
|
97
|
+
scenario.yaml # Scenario metadata
|
|
98
|
+
contracts/
|
|
99
|
+
static.yaml # SKILL.md structure rules
|
|
100
|
+
behavior.yaml # Execution assertions
|
|
101
|
+
pulled/ # Data from sync pull
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Runner Types
|
|
105
|
+
|
|
106
|
+
Configure the executor in `simulation.yaml`:
|
|
107
|
+
|
|
108
|
+
**Function** — call a Python handler directly:
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
runner:
|
|
112
|
+
type: function
|
|
113
|
+
target: "my_agent:handler"
|
|
114
|
+
timeout_seconds: 30
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Skill** — run a SKILL.md in Claude Agent SDK sandbox:
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
runner:
|
|
121
|
+
type: skill
|
|
122
|
+
skill_path: ./SKILL.md
|
|
123
|
+
harness: claude
|
|
124
|
+
allowed_tools: ["Read", "Write", "Shell"]
|
|
125
|
+
skill_max_turns: 10
|
|
126
|
+
budget: 0.50
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Process** — invoke a subprocess via NDJSON protocol:
|
|
130
|
+
|
|
131
|
+
```yaml
|
|
132
|
+
runner:
|
|
133
|
+
type: process
|
|
134
|
+
command: ["python", "agent.py"]
|
|
135
|
+
protocol: ndjson
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Input Sources
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
input:
|
|
142
|
+
source: inline # inline | generated | bundle | pulled
|
|
143
|
+
items:
|
|
144
|
+
- text: "Hello, summarize this document"
|
|
145
|
+
- text: "What are the key takeaways?"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
When `source: pulled`, inputs are loaded from `pulled/inputs.json` after `sync pull`.
|
|
149
|
+
|
|
150
|
+
### Environment Variable Substitution
|
|
151
|
+
|
|
152
|
+
YAML config values support `${VAR}` syntax, resolved from environment variables.
|
|
153
|
+
|
|
154
|
+
## Contracts
|
|
155
|
+
|
|
156
|
+
### Static Contract
|
|
157
|
+
|
|
158
|
+
Validates SKILL.md structure before execution:
|
|
159
|
+
|
|
160
|
+
- Required sections (e.g., `# Purpose`, `# Instructions`)
|
|
161
|
+
- File size limits
|
|
162
|
+
- Encoding checks
|
|
163
|
+
- Forbidden pattern detection
|
|
164
|
+
|
|
165
|
+
### Behavior Contract
|
|
166
|
+
|
|
167
|
+
Asserts conditions on execution results:
|
|
168
|
+
|
|
169
|
+
- `tool_called` / `tool_not_called`
|
|
170
|
+
- `turn_count` (min/max)
|
|
171
|
+
- `output_contains` / `output_matches`
|
|
172
|
+
- `file_exists`
|
|
173
|
+
- `cost_below` / `duration_below`
|
|
174
|
+
|
|
175
|
+
## Authentication
|
|
176
|
+
|
|
177
|
+
FluxLoop uses OAuth device code flow for interactive login:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
fluxloop auth login # Opens browser for approval
|
|
181
|
+
fluxloop auth login --no-browser # Manual code entry
|
|
182
|
+
fluxloop auth login --no-wait # Save pending, resume later
|
|
183
|
+
fluxloop auth login --resume # Resume pending login
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Tokens are stored in `~/.fluxloop/auth.json`. For CI environments, use `FLUXLOOP_API_KEY` instead.
|
|
187
|
+
|
|
188
|
+
## Environment Variables
|
|
189
|
+
|
|
190
|
+
| Variable | Purpose |
|
|
191
|
+
|----------|---------|
|
|
192
|
+
| `FLUXLOOP_API_URL` | Backend API base URL |
|
|
193
|
+
| `FLUXLOOP_API_KEY` | API key for authenticated requests |
|
|
194
|
+
| `FLUXLOOP_SYNC_API_KEY` | API key specifically for sync operations |
|
|
195
|
+
| `ANTHROPIC_API_KEY` | Required for multi-turn UserSimulator |
|
|
196
|
+
| `OPENAI_API_KEY` | Alternative provider for UserSimulator |
|
|
197
|
+
|
|
198
|
+
Workspace-level variables can also be set in `.fluxloop/.env`.
|
|
199
|
+
|
|
200
|
+
## Output
|
|
201
|
+
|
|
202
|
+
Test runs produce standardized output in `.fluxloop/results/<experiment>-<timestamp>/`:
|
|
203
|
+
|
|
204
|
+
| File | Content |
|
|
205
|
+
|------|---------|
|
|
206
|
+
| `trace_summary.jsonl` | Per-run execution traces (tool calls, tokens, cost) |
|
|
207
|
+
| `summary.json` | Aggregated statistics (success rate, duration, cost) |
|
|
208
|
+
| `errors.json` | Failure inventory with diagnostics |
|
|
209
|
+
|
|
210
|
+
## Developing
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
cd cli/python
|
|
214
|
+
|
|
215
|
+
# Install dependencies
|
|
216
|
+
uv sync --group dev
|
|
217
|
+
|
|
218
|
+
# Run in development mode
|
|
219
|
+
uv run fluxloop --help
|
|
220
|
+
|
|
221
|
+
# Run tests
|
|
222
|
+
uv run pytest
|
|
223
|
+
|
|
224
|
+
# Lint
|
|
225
|
+
uv run ruff check .
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Building & Publishing
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Build
|
|
232
|
+
uv build
|
|
233
|
+
|
|
234
|
+
# Publish to PyPI
|
|
235
|
+
uv publish
|
|
236
|
+
# or
|
|
237
|
+
twine upload dist/*
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Tech Stack
|
|
241
|
+
|
|
242
|
+
| Library | Purpose |
|
|
243
|
+
|---------|---------|
|
|
244
|
+
| [Typer](https://typer.tiangolo.com) | CLI framework |
|
|
245
|
+
| [Pydantic](https://docs.pydantic.dev) | Data validation |
|
|
246
|
+
| [ruamel.yaml](https://yaml.readthedocs.io) | YAML parsing |
|
|
247
|
+
| [httpx](https://www.python-httpx.org) | HTTP client |
|
|
248
|
+
| [Rich](https://rich.readthedocs.io) | Terminal output formatting |
|
|
249
|
+
| [claude-agent-sdk](https://pypi.org/project/claude-agent-sdk/) | Skill execution in Claude sandbox |
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
Apache-2.0
|