apcore-cli 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,459 @@
1
+ Metadata-Version: 2.4
2
+ Name: apcore-cli
3
+ Version: 0.1.0
4
+ Summary: Terminal adapter for apcore — execute AI-Perceivable modules from the command line
5
+ Project-URL: Homepage, https://aipartnerup.com
6
+ Project-URL: Repository, https://github.com/aipartnerup/apcore-cli-python
7
+ Project-URL: Documentation, https://github.com/aipartnerup/apcore-cli-python#readme
8
+ Project-URL: Issues, https://github.com/aipartnerup/apcore-cli-python/issues
9
+ Author-email: aipartnerup <team@aipartnerup.com>
10
+ License-Expression: Apache-2.0
11
+ Keywords: agent,ai,apcore,automation,cli,command-line,llm,shell,terminal,unix
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: apcore>=0.13.0
24
+ Requires-Dist: click>=8.1
25
+ Requires-Dist: cryptography>=41.0
26
+ Requires-Dist: jsonschema>=4.20
27
+ Requires-Dist: keyring>=24.0
28
+ Requires-Dist: pyyaml>=6.0
29
+ Requires-Dist: rich>=13.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: apdev[dev]>=0.2.3; extra == 'dev'
32
+ Requires-Dist: mypy>=1.0; extra == 'dev'
33
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
34
+ Requires-Dist: pytest>=7.0; extra == 'dev'
35
+ Requires-Dist: ruff>=0.1; extra == 'dev'
36
+ Description-Content-Type: text/markdown
37
+
38
+ <div align="center">
39
+ <img src="https://raw.githubusercontent.com/aipartnerup/apcore-cli/main/apcore-cli-logo.svg" alt="apcore-cli logo" width="200"/>
40
+ </div>
41
+
42
+ # apcore-cli
43
+
44
+ Terminal adapter for apcore. Execute AI-Perceivable modules from the command line.
45
+
46
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
47
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://python.org)
48
+ [![Tests](https://img.shields.io/badge/tests-244%20passed-brightgreen.svg)]()
49
+
50
+ | | |
51
+ |---|---|
52
+ | **Python SDK** | [github.com/aipartnerup/apcore-cli-python](https://github.com/aipartnerup/apcore-cli-python) |
53
+ | **Spec repo** | [github.com/aipartnerup/apcore-cli](https://github.com/aipartnerup/apcore-cli) |
54
+ | **apcore core** | [github.com/aipartnerup/apcore](https://github.com/aipartnerup/apcore) |
55
+
56
+ **apcore-cli** turns any [apcore](https://github.com/aipartnerup/apcore)-based project into a fully featured CLI tool — with **zero code changes** to your existing modules.
57
+
58
+ ```
59
+ ┌──────────────────┐
60
+ │ django-apcore │ <- your existing apcore project (unchanged)
61
+ │ flask-apcore │
62
+ │ ... │
63
+ └────────┬─────────┘
64
+ │ extensions directory
65
+ v
66
+ ┌──────────────────┐
67
+ │ apcore-cli │ <- just install & point to extensions dir
68
+ └───┬──────────┬───┘
69
+ │ │
70
+ v v
71
+ Terminal Unix
72
+ Commands Pipes
73
+ ```
74
+
75
+ ## Design Philosophy
76
+
77
+ - **Zero intrusion** -- your apcore project needs no code changes, no imports, no dependencies on apcore-cli
78
+ - **Zero configuration** -- point to an extensions directory, everything is auto-discovered
79
+ - **Pure adapter** -- apcore-cli reads from the apcore Registry; it never modifies your modules
80
+ - **Unix-native** -- JSON output for pipes, rich tables for terminals, STDIN input, shell completions
81
+
82
+ ## Installation
83
+
84
+ ```bash
85
+ pip install apcore-cli
86
+ ```
87
+
88
+ Requires Python 3.11+ and `apcore >= 0.13.0`.
89
+
90
+ ## Quick Start
91
+
92
+ ### Try it now
93
+
94
+ The repo includes 8 example modules you can run immediately:
95
+
96
+ ```bash
97
+ git clone https://github.com/aipartnerup/apcore-cli-python.git
98
+ cd apcore-cli-python
99
+ pip install -e ".[dev]"
100
+
101
+ # Run a module
102
+ apcore-cli --extensions-dir examples/extensions math.add --a 5 --b 10
103
+ # {"sum": 15}
104
+
105
+ # List all modules
106
+ apcore-cli --extensions-dir examples/extensions list --format json
107
+
108
+ # Run all examples
109
+ bash examples/run_examples.sh
110
+ ```
111
+
112
+ See [Examples](#examples) for the full list of example modules and usage patterns.
113
+
114
+ ### Zero-code approach
115
+
116
+ If you already have an apcore-based project with an extensions directory:
117
+
118
+ ```bash
119
+ # Execute a module
120
+ apcore-cli --extensions-dir ./extensions math.add --a 42 --b 58
121
+
122
+ # Or set the env var once
123
+ export APCORE_EXTENSIONS_ROOT=./extensions
124
+ apcore-cli math.add --a 42 --b 58
125
+ ```
126
+
127
+ All modules are auto-discovered. CLI flags are auto-generated from each module's JSON Schema.
128
+
129
+ ### Programmatic approach (Python API)
130
+
131
+ ```python
132
+ from apcore import Registry, Executor
133
+ from apcore_cli.__main__ import create_cli
134
+
135
+ # Build the CLI from your registry
136
+ cli = create_cli(extensions_dir="./extensions")
137
+ cli(standalone_mode=True)
138
+ ```
139
+
140
+ Or use the `LazyModuleGroup` directly with Click:
141
+
142
+ ```python
143
+ import click
144
+ from apcore import Registry, Executor
145
+ from apcore_cli.cli import LazyModuleGroup
146
+
147
+ registry = Registry(extensions_dir="./extensions")
148
+ registry.discover()
149
+ executor = Executor(registry)
150
+
151
+ @click.group(cls=LazyModuleGroup, registry=registry, executor=executor)
152
+ def cli():
153
+ pass
154
+
155
+ cli()
156
+ ```
157
+
158
+ ## Integration with Existing Projects
159
+
160
+ ### Typical apcore project structure
161
+
162
+ ```
163
+ your-project/
164
+ ├── extensions/ <- modules live here
165
+ │ ├── math/
166
+ │ │ └── add.py
167
+ │ ├── text/
168
+ │ │ └── upper.py
169
+ │ └── ...
170
+ ├── your_app.py <- your existing code (untouched)
171
+ └── ...
172
+ ```
173
+
174
+ ### Adding CLI support
175
+
176
+ No changes to your project. Just install and run:
177
+
178
+ ```bash
179
+ pip install apcore-cli
180
+ apcore-cli --extensions-dir ./extensions list
181
+ apcore-cli --extensions-dir ./extensions math.add --a 5 --b 10
182
+ ```
183
+
184
+ ### STDIN piping (Unix pipes)
185
+
186
+ ```bash
187
+ # Pipe JSON input
188
+ echo '{"a": 100, "b": 200}' | apcore-cli math.add --input -
189
+ # {"sum": 300}
190
+
191
+ # CLI flags override STDIN values
192
+ echo '{"a": 1, "b": 2}' | apcore-cli math.add --input - --a 999
193
+ # {"sum": 1001}
194
+
195
+ # Chain with other tools
196
+ apcore-cli sysutil.info | jq '.os, .hostname'
197
+ ```
198
+
199
+ ## CLI Reference
200
+
201
+ ```
202
+ apcore-cli [OPTIONS] COMMAND [ARGS]
203
+ ```
204
+
205
+ ### Global Options
206
+
207
+ | Option | Default | Description |
208
+ |--------|---------|-------------|
209
+ | `--extensions-dir` | `./extensions` | Path to apcore extensions directory |
210
+ | `--log-level` | `INFO` | Logging: `DEBUG`, `INFO`, `WARN`, `ERROR` |
211
+ | `--version` | | Show version and exit |
212
+ | `--help` | | Show help and exit |
213
+
214
+ ### Built-in Commands
215
+
216
+ | Command | Description |
217
+ |---------|-------------|
218
+ | `list` | List available modules with optional tag filtering |
219
+ | `describe <module_id>` | Show full module metadata and schemas |
220
+ | `completion <shell>` | Generate shell completion script (bash/zsh/fish) |
221
+ | `man <command>` | Generate man page in roff format |
222
+
223
+ ### Module Execution Options
224
+
225
+ When executing a module (e.g. `apcore-cli math.add`), these built-in options are always available:
226
+
227
+ | Option | Description |
228
+ |--------|-------------|
229
+ | `--input -` | Read JSON input from STDIN |
230
+ | `--yes` / `-y` | Bypass approval prompts |
231
+ | `--large-input` | Allow STDIN input larger than 10MB |
232
+ | `--format` | Output format: `json` or `table` |
233
+ | `--sandbox` | Run module in subprocess sandbox |
234
+
235
+ Schema-generated flags (e.g. `--a`, `--b`) are added automatically from the module's `input_schema`.
236
+
237
+ ### Exit Codes
238
+
239
+ | Code | Meaning |
240
+ |------|---------|
241
+ | `0` | Success |
242
+ | `1` | Module execution error |
243
+ | `2` | Invalid CLI input |
244
+ | `44` | Module not found / disabled / load error |
245
+ | `45` | Schema validation error |
246
+ | `46` | Approval denied or timed out |
247
+ | `47` | Configuration error |
248
+ | `48` | Schema circular reference |
249
+ | `77` | ACL denied |
250
+ | `130` | Execution cancelled (Ctrl+C) |
251
+
252
+ ## Configuration
253
+
254
+ apcore-cli uses a 4-tier configuration precedence:
255
+
256
+ 1. **CLI flag** (highest): `--extensions-dir ./custom`
257
+ 2. **Environment variable**: `APCORE_EXTENSIONS_ROOT=./custom`
258
+ 3. **Config file**: `apcore.yaml`
259
+ 4. **Default** (lowest): `./extensions`
260
+
261
+ ### Environment Variables
262
+
263
+ | Variable | Description | Default |
264
+ |----------|-------------|---------|
265
+ | `APCORE_EXTENSIONS_ROOT` | Path to extensions directory | `./extensions` |
266
+ | `APCORE_CLI_AUTO_APPROVE` | Set to `1` to bypass all approval prompts | *(unset)* |
267
+ | `APCORE_LOGGING_LEVEL` | Log level | `INFO` |
268
+ | `APCORE_AUTH_API_KEY` | API key for remote registry authentication | *(unset)* |
269
+ | `APCORE_CLI_SANDBOX` | Set to `1` to enable subprocess sandboxing | *(unset)* |
270
+
271
+ ### Config File (`apcore.yaml`)
272
+
273
+ ```yaml
274
+ extensions:
275
+ root: ./extensions
276
+ logging:
277
+ level: DEBUG
278
+ sandbox:
279
+ enabled: false
280
+ ```
281
+
282
+ ## Features
283
+
284
+ - **Auto-discovery** -- all modules in the extensions directory are found and exposed as CLI commands
285
+ - **Auto-generated flags** -- JSON Schema `input_schema` is converted to `--flag value` CLI options with type validation
286
+ - **Boolean flag pairs** -- `--verbose` / `--no-verbose` from `"type": "boolean"` schema properties
287
+ - **Enum choices** -- `"enum": ["json", "csv"]` becomes `--format json` with Click validation
288
+ - **STDIN piping** -- `--input -` reads JSON from STDIN, CLI flags override for duplicate keys
289
+ - **TTY-adaptive output** -- rich tables for terminals, JSON for pipes (configurable via `--format`)
290
+ - **Approval gate** -- TTY-aware HITL prompts for modules with `requires_approval: true`, with `--yes` bypass and 60s timeout
291
+ - **Schema validation** -- inputs validated against JSON Schema before execution, with `$ref`/`allOf`/`anyOf`/`oneOf` resolution
292
+ - **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing
293
+ - **Shell completions** -- `apcore-cli completion bash|zsh|fish` generates completion scripts with dynamic module ID completion
294
+ - **Man pages** -- `apcore-cli man <command>` generates roff-formatted man pages
295
+ - **Audit logging** -- all executions logged to `~/.apcore-cli/audit.jsonl` with SHA-256 input hashing
296
+
297
+ ## How It Works
298
+
299
+ ### Mapping: apcore to CLI
300
+
301
+ | apcore | CLI |
302
+ |--------|-----|
303
+ | `module_id` (`math.add`) | Command name (`apcore-cli math.add`) |
304
+ | `description` | `--help` text |
305
+ | `input_schema.properties` | CLI flags (`--a`, `--b`) |
306
+ | `input_schema.required` | Required flag enforcement |
307
+ | `annotations.requires_approval` | HITL approval prompt |
308
+
309
+ ### Architecture
310
+
311
+ ```
312
+ User / AI Agent (terminal)
313
+ |
314
+ v
315
+ apcore-cli (the adapter)
316
+ |
317
+ +-- ConfigResolver 4-tier config precedence
318
+ +-- LazyModuleGroup Dynamic Click command generation
319
+ +-- SchemaParser JSON Schema -> Click options
320
+ +-- RefResolver $ref / allOf / anyOf / oneOf
321
+ +-- ApprovalGate TTY-aware HITL approval
322
+ +-- OutputFormatter TTY-adaptive JSON/table output
323
+ +-- AuditLogger JSON Lines execution logging
324
+ +-- Sandbox Subprocess isolation
325
+ |
326
+ v
327
+ apcore Registry + Executor (your modules, unchanged)
328
+ ```
329
+
330
+ ## Examples
331
+
332
+ The `examples/extensions/` directory contains 8 runnable modules:
333
+
334
+ | Module | Description | Usage |
335
+ |--------|-------------|-------|
336
+ | `math.add` | Add two integers | `apcore-cli math.add --a 5 --b 10` |
337
+ | `math.multiply` | Multiply two integers | `apcore-cli math.multiply --a 6 --b 7` |
338
+ | `text.upper` | Uppercase a string | `apcore-cli text.upper --text hello` |
339
+ | `text.reverse` | Reverse a string | `apcore-cli text.reverse --text abcdef` |
340
+ | `text.wordcount` | Count words/chars/lines | `apcore-cli text.wordcount --text "hello world"` |
341
+ | `sysutil.info` | OS, hostname, Python version | `apcore-cli sysutil.info` |
342
+ | `sysutil.env` | Read environment variables | `apcore-cli sysutil.env --name HOME` |
343
+ | `sysutil.disk` | Disk usage statistics | `apcore-cli sysutil.disk --path /` |
344
+
345
+ ### Running examples
346
+
347
+ ```bash
348
+ # Set extensions path (one time)
349
+ export APCORE_EXTENSIONS_ROOT=examples/extensions
350
+
351
+ # Execute modules
352
+ apcore-cli math.add --a 42 --b 58
353
+ apcore-cli text.upper --text "hello apcore"
354
+ apcore-cli sysutil.info
355
+ apcore-cli sysutil.disk --path /
356
+
357
+ # Discovery
358
+ apcore-cli list --format json
359
+ apcore-cli list --tag math --format json
360
+ apcore-cli describe math.add --format json
361
+
362
+ # STDIN piping
363
+ echo '{"a": 100, "b": 200}' | apcore-cli math.add --input -
364
+
365
+ # Shell completion
366
+ apcore-cli completion bash >> ~/.bashrc
367
+ apcore-cli completion zsh >> ~/.zshrc
368
+ apcore-cli completion fish > ~/.config/fish/completions/apcore-cli.fish
369
+
370
+ # Man pages
371
+ apcore-cli man list | man -l -
372
+
373
+ # Run all examples at once
374
+ bash examples/run_examples.sh
375
+ ```
376
+
377
+ ### Writing your own module
378
+
379
+ Create a Python file in your extensions directory:
380
+
381
+ ```python
382
+ # extensions/greet/hello.py
383
+ from pydantic import BaseModel
384
+
385
+ class Input(BaseModel):
386
+ name: str
387
+ greeting: str = "Hello"
388
+
389
+ class Output(BaseModel):
390
+ message: str
391
+
392
+ class GreetHello:
393
+ input_schema = Input
394
+ output_schema = Output
395
+ description = "Greet someone by name"
396
+
397
+ def execute(self, inputs, context=None):
398
+ return {"message": f"{inputs['greeting']}, {inputs['name']}!"}
399
+ ```
400
+
401
+ Then run it:
402
+
403
+ ```bash
404
+ apcore-cli --extensions-dir ./extensions greet.hello --name World
405
+ # {"message": "Hello, World!"}
406
+
407
+ apcore-cli --extensions-dir ./extensions greet.hello --name Alice --greeting Hi
408
+ # {"message": "Hi, Alice!"}
409
+ ```
410
+
411
+ ## Development
412
+
413
+ ```bash
414
+ git clone https://github.com/aipartnerup/apcore-cli-python.git
415
+ cd apcore-cli-python
416
+ pip install -e ".[dev]"
417
+ pytest # 244 tests
418
+ pytest --cov # with coverage report
419
+ bash examples/run_examples.sh # run all examples
420
+ ```
421
+
422
+ ### Project Structure
423
+
424
+ ```
425
+ src/apcore_cli/
426
+ ├── __init__.py # Package version
427
+ ├── __main__.py # CLI entry point, wiring
428
+ ├── cli.py # LazyModuleGroup, build_module_command, collect_input
429
+ ├── config.py # ConfigResolver (4-tier precedence)
430
+ ├── schema_parser.py # JSON Schema -> Click options
431
+ ├── ref_resolver.py # $ref / allOf / anyOf / oneOf resolution
432
+ ├── output.py # TTY-adaptive output formatting (rich)
433
+ ├── discovery.py # list / describe commands
434
+ ├── approval.py # HITL approval gate with timeout
435
+ ├── shell.py # bash/zsh/fish completion + man pages
436
+ ├── _sandbox_runner.py # Subprocess entry point for sandboxed execution
437
+ └── security/
438
+ ├── __init__.py # Exports
439
+ ├── auth.py # API key authentication
440
+ ├── config_encryptor.py # Keyring + AES-256-GCM encrypted config
441
+ ├── audit.py # JSON Lines audit logging
442
+ └── sandbox.py # Subprocess-based execution isolation
443
+
444
+ examples/
445
+ ├── run_examples.sh # Run all examples end-to-end
446
+ └── extensions/
447
+ ├── math/ # math.add, math.multiply
448
+ ├── text/ # text.upper, text.reverse, text.wordcount
449
+ └── sysutil/ # sysutil.info, sysutil.env, sysutil.disk
450
+
451
+ planning/ # Implementation plans (TDD task breakdowns)
452
+ ├── overview.md
453
+ ├── state.json
454
+ └── *.md # Per-feature plans
455
+ ```
456
+
457
+ ## License
458
+
459
+ Apache-2.0
@@ -0,0 +1,20 @@
1
+ apcore_cli/__init__.py,sha256=3lIlzaNZOEG2Pjee331jFBDNTMzCXpTHO9SxaPKPS4w,86
2
+ apcore_cli/__main__.py,sha256=ayOZiMql6uCGEioHlUlKSnH-RXU47TkTSFapBwAlg_A,4313
3
+ apcore_cli/_sandbox_runner.py,sha256=RG5seBxDlBAIJ7FMG7WjcU0JyG1XSheAOsvE_U7eSEg,585
4
+ apcore_cli/approval.py,sha256=sF5H485pcUQiRbJag17qPNLxzFNZtQFFNIipxtwv_Jc,5444
5
+ apcore_cli/cli.py,sha256=TPvSh7oYnlwj3Kafp9iWl7U9IFjGiSGklKrRhKSrL8I,10047
6
+ apcore_cli/config.py,sha256=fKEecVAtweKhxtdhEoszMXuVA7_dm3Ll0Ly7tJT_d1c,2914
7
+ apcore_cli/discovery.py,sha256=GYCOHaD94HmUMe8j8GqMneGLwZFY7s74sPj_K4ipSoI,2317
8
+ apcore_cli/output.py,sha256=PgBmIg6m3jRKwGe67_ll-b3IQUkeP6e0K2FG5GKNZDs,6599
9
+ apcore_cli/ref_resolver.py,sha256=fwk41dUXTF8BcuEGe4AoyaJIsKpayUu_lkg9UOcava0,3867
10
+ apcore_cli/schema_parser.py,sha256=St1-jzxEufchtuqyYL2d8FBiIyQnwylMLedUJvIl3Gk,5585
11
+ apcore_cli/shell.py,sha256=rzc2ddd6xqrVLoy-rTh-z53LC3jcCQ0z_e7MAofhyk4,6914
12
+ apcore_cli/security/__init__.py,sha256=89dHOZlDjA22JohH5sPb4lT08LFpdNHrgjpoSZB0Z-8,323
13
+ apcore_cli/security/audit.py,sha256=wuaxtyIpWhyqEB3uqYHkuLFlQzMbl4fz7S16IaLDqKo,1588
14
+ apcore_cli/security/auth.py,sha256=Xv9xD3qz_jzXk_XaYwerDDl-uyNX-KMPypLQJ3Tg4R0,1243
15
+ apcore_cli/security/config_encryptor.py,sha256=GpZcaxVA45zHZDqfLwFraSCWPsowaRuJHtbXbByFU0c,3278
16
+ apcore_cli/security/sandbox.py,sha256=yjRwdh8-3NdBPk_kzS3L1WAsCATyVzVu5LSJzz8z9GI,1923
17
+ apcore_cli-0.1.0.dist-info/METADATA,sha256=iuqOHRCLWteFMjtjXXMQX9ZM1NUXbkYV-Y36zu24a5U,15183
18
+ apcore_cli-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
19
+ apcore_cli-0.1.0.dist-info/entry_points.txt,sha256=tB2mK533vfmKAJM9jY4K0_hrGRcUX0bkVR3yDRAre_A,56
20
+ apcore_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ apcore-cli = apcore_cli.__main__:main