Terminal adapter for apcore — execute AI-Perceivable modules from the command line
Project description
apcore-cli
Terminal adapter for apcore. Execute AI-Perceivable modules from the command line.
| Python SDK | github.com/aiperceivable/apcore-cli-python |
| Spec repo | github.com/aiperceivable/apcore-cli |
| apcore core | github.com/aiperceivable/apcore |
apcore-cli turns any apcore-based project into a fully featured CLI tool — with zero code changes to your existing modules.
┌──────────────────┐
│ django-apcore │ <- your existing apcore project (unchanged)
│ flask-apcore │
│ ... │
└────────┬─────────┘
│ extensions directory
v
┌──────────────────┐
│ apcore-cli │ <- just install & point to extensions dir
└───┬──────────┬───┘
│ │
v v
Terminal Unix
Commands Pipes
Design Philosophy
- Zero intrusion -- your apcore project needs no code changes, no imports, no dependencies on apcore-cli
- Zero configuration -- point to an extensions directory, everything is auto-discovered
- Pure adapter -- apcore-cli reads from the apcore Registry; it never modifies your modules
- Unix-native -- JSON output for pipes, rich tables for terminals, STDIN input, shell completions
Installation
pip install apcore-cli
Requires Python 3.11+ and apcore >= 0.14.0.
Quick Start
Try it now
The repo includes 8 example modules you can run immediately:
git clone https://github.com/aiperceivable/apcore-cli-python.git
cd apcore-cli-python
pip install -e ".[dev]"
# Run a module
apcore-cli --extensions-dir examples/extensions math.add --a 5 --b 10
# {"sum": 15}
# List all modules
apcore-cli --extensions-dir examples/extensions list --format json
# Run all examples
bash examples/run_examples.sh
See Examples for the full list of example modules and usage patterns.
Zero-code approach
If you already have an apcore-based project with an extensions directory:
# Execute a module
apcore-cli --extensions-dir ./extensions math.add --a 42 --b 58
# Or set the env var once
export APCORE_EXTENSIONS_ROOT=./extensions
apcore-cli math.add --a 42 --b 58
All modules are auto-discovered. CLI flags are auto-generated from each module's JSON Schema.
Programmatic approach (Python API)
from apcore import Registry, Executor
from apcore_cli.__main__ import create_cli
# Build the CLI from your registry
cli = create_cli(extensions_dir="./extensions")
cli(standalone_mode=True)
Or use the LazyModuleGroup directly with Click:
import click
from apcore import Registry, Executor
from apcore_cli.cli import LazyModuleGroup
registry = Registry(extensions_dir="./extensions")
registry.discover()
executor = Executor(registry)
@click.group(cls=LazyModuleGroup, registry=registry, executor=executor)
def cli():
pass
cli()
Adding Custom Commands
Fastest way (30 seconds)
apcore-cli init module ops.deploy -d "Deploy to environment"
# Edit the generated file, add your logic
Zero-import way (convention discovery)
Drop a plain Python function into commands/:
# commands/deploy.py
def deploy(env: str, tag: str = "latest") -> dict:
"""Deploy the app to the given environment."""
return {"status": "deployed", "env": env}
Then run with --commands-dir commands/:
apcore-cli --commands-dir commands/ deploy deploy --env prod
The init module command supports three styles via --style:
- convention (default) — generates a plain Python function in the commands directory
- decorator — generates a
@module-decorated function in the extensions directory - binding — generates a
.binding.yamlfile
Integration with Existing Projects
Typical apcore project structure
your-project/
├── extensions/ <- modules live here
│ ├── math/
│ │ └── add.py
│ ├── text/
│ │ └── upper.py
│ └── ...
├── your_app.py <- your existing code (untouched)
└── ...
Adding CLI support
No changes to your project. Just install and run:
pip install apcore-cli
apcore-cli --extensions-dir ./extensions list
apcore-cli --extensions-dir ./extensions math.add --a 5 --b 10
STDIN piping (Unix pipes)
# Pipe JSON input
echo '{"a": 100, "b": 200}' | apcore-cli math.add --input -
# {"sum": 300}
# CLI flags override STDIN values
echo '{"a": 1, "b": 2}' | apcore-cli math.add --input - --a 999
# {"sum": 1001}
# Chain with other tools
apcore-cli sysutil.info | jq '.os, .hostname'
CLI Reference
apcore-cli [OPTIONS] COMMAND [ARGS]
Global Options
| Option | Default | Description |
|---|---|---|
--extensions-dir |
./extensions |
Path to apcore extensions directory |
--log-level |
WARNING |
Logging: DEBUG, INFO, WARNING, ERROR |
--version |
Show version and exit | |
--help |
Show help and exit |
Built-in Commands
| Command | Description |
|---|---|
list |
List available modules with optional tag filtering |
describe <module_id> |
Show full module metadata and schemas |
completion <shell> |
Generate shell completion script (bash/zsh/fish) |
man <command> |
Generate man page in roff format |
Module Execution Options
When executing a module (e.g. apcore-cli math.add), these built-in options are always available:
| Option | Description |
|---|---|
--input - |
Read JSON input from STDIN |
--yes / -y |
Bypass approval prompts |
--large-input |
Allow STDIN input larger than 10MB |
--format |
Output format: json or table |
--sandbox |
Run module in subprocess sandbox |
Schema-generated flags (e.g. --a, --b) are added automatically from the module's input_schema.
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Module execution error |
2 |
Invalid CLI input |
44 |
Module not found / disabled / load error |
45 |
Schema validation error |
46 |
Approval denied or timed out |
47 |
Configuration error |
48 |
Schema circular reference |
77 |
ACL denied |
130 |
Execution cancelled (Ctrl+C) |
Configuration
apcore-cli uses a 4-tier configuration precedence:
- CLI flag (highest):
--extensions-dir ./custom - Environment variable:
APCORE_EXTENSIONS_ROOT=./custom - Config file:
apcore.yaml - Default (lowest):
./extensions
Environment Variables
| Variable | Description | Default |
|---|---|---|
APCORE_EXTENSIONS_ROOT |
Path to extensions directory | ./extensions |
APCORE_CLI_AUTO_APPROVE |
Set to 1 to bypass all approval prompts |
(unset) |
APCORE_CLI_LOGGING_LEVEL |
CLI-specific log level (takes priority over APCORE_LOGGING_LEVEL) |
WARNING |
APCORE_LOGGING_LEVEL |
Global apcore log level (fallback when APCORE_CLI_LOGGING_LEVEL is unset) |
WARNING |
APCORE_AUTH_API_KEY |
API key for remote registry authentication | (unset) |
APCORE_CLI_SANDBOX |
Set to 1 to enable subprocess sandboxing |
(unset) |
APCORE_CLI_HELP_TEXT_MAX_LENGTH |
Maximum characters for CLI option help text before truncation | 1000 |
Config File (apcore.yaml)
extensions:
root: ./extensions
logging:
level: DEBUG
sandbox:
enabled: false
cli:
help_text_max_length: 1000
Features
- Auto-discovery -- all modules in the extensions directory are found and exposed as CLI commands
- Display overlay --
metadata["display"]["cli"]controls CLI command names, descriptions, and guidance per module (§5.13); set viabinding_pathincreate_cli()/fastapi-apcore - Grouped commands -- modules with dots in their names are auto-grouped into nested subcommands (
apcore-cli product listinstead ofapcore-cli product.list);display.cli.groupin binding.yaml overrides the auto-detected group - Auto-generated flags -- JSON Schema
input_schemais converted to--flag valueCLI options with type validation - Boolean flag pairs --
--verbose/--no-verbosefrom"type": "boolean"schema properties - Enum choices --
"enum": ["json", "csv"]becomes--format jsonwith Click validation - STDIN piping --
--input -reads JSON from STDIN, CLI flags override for duplicate keys - TTY-adaptive output -- rich tables for terminals, JSON for pipes (configurable via
--format) - Approval gate -- TTY-aware HITL prompts for modules with
requires_approval: true, with--yesbypass and 60s timeout - Schema validation -- inputs validated against JSON Schema before execution, with
$ref/allOf/anyOf/oneOfresolution - Security -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing
- Shell completions --
apcore-cli completion bash|zsh|fishgenerates completion scripts with dynamic module ID completion - Man pages --
apcore-cli man <command>generates roff-formatted man pages - Audit logging -- all executions logged to
~/.apcore-cli/audit.jsonlwith SHA-256 input hashing
How It Works
Mapping: apcore to CLI
| apcore | CLI |
|---|---|
metadata["display"]["cli"]["alias"] or module_id |
Command name — auto-grouped by first . segment (apcore-cli product get) |
metadata["display"]["cli"]["description"] or description |
--help text |
input_schema.properties |
CLI flags (--a, --b) |
input_schema.required |
Validated post-collection via jsonschema.validate() (required fields shown as [required] in --help) |
annotations.requires_approval |
HITL approval prompt |
Architecture
User / AI Agent (terminal)
|
v
apcore-cli (the adapter)
|
+-- ConfigResolver 4-tier config precedence
+-- LazyModuleGroup Dynamic Click command generation
+-- schema_parser JSON Schema -> Click options
+-- ref_resolver $ref / allOf / anyOf / oneOf
+-- approval TTY-aware HITL approval
+-- output TTY-adaptive JSON/table output
+-- AuditLogger JSON Lines execution logging
+-- Sandbox Subprocess isolation
|
v
apcore Registry + Executor (your modules, unchanged)
Examples
The examples/extensions/ directory contains 8 runnable modules:
| Module | Description | Usage |
|---|---|---|
math.add |
Add two integers | apcore-cli math.add --a 5 --b 10 |
math.multiply |
Multiply two integers | apcore-cli math.multiply --a 6 --b 7 |
text.upper |
Uppercase a string | apcore-cli text.upper --text hello |
text.reverse |
Reverse a string | apcore-cli text.reverse --text abcdef |
text.wordcount |
Count words/chars/lines | apcore-cli text.wordcount --text "hello world" |
sysutil.info |
OS, hostname, Python version | apcore-cli sysutil.info |
sysutil.env |
Read environment variables | apcore-cli sysutil.env --name HOME |
sysutil.disk |
Disk usage statistics | apcore-cli sysutil.disk --path / |
Running examples
# Set extensions path (one time)
export APCORE_EXTENSIONS_ROOT=examples/extensions
# Execute modules
apcore-cli math.add --a 42 --b 58
apcore-cli text.upper --text "hello apcore"
apcore-cli sysutil.info
apcore-cli sysutil.disk --path /
# Discovery
apcore-cli list --format json
apcore-cli list --tag math --format json
apcore-cli describe math.add --format json
# STDIN piping
echo '{"a": 100, "b": 200}' | apcore-cli math.add --input -
# Shell completion
apcore-cli completion bash >> ~/.bashrc
apcore-cli completion zsh >> ~/.zshrc
apcore-cli completion fish > ~/.config/fish/completions/apcore-cli.fish
# Man pages
apcore-cli man list | man -l -
# Run all examples at once
bash examples/run_examples.sh
Writing your own module
Create a Python file in your extensions directory:
# extensions/greet/hello.py
from pydantic import BaseModel
class Input(BaseModel):
name: str
greeting: str = "Hello"
class Output(BaseModel):
message: str
class GreetHello:
input_schema = Input
output_schema = Output
description = "Greet someone by name"
def execute(self, inputs, context=None):
return {"message": f"{inputs['greeting']}, {inputs['name']}!"}
Then run it:
apcore-cli --extensions-dir ./extensions greet.hello --name World
# {"message": "Hello, World!"}
apcore-cli --extensions-dir ./extensions greet.hello --name Alice --greeting Hi
# {"message": "Hi, Alice!"}
Development
git clone https://github.com/aiperceivable/apcore-cli-python.git
cd apcore-cli-python
pip install -e ".[dev]"
pytest # 319+ tests
pytest --cov # with coverage report
bash examples/run_examples.sh # run all examples
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file apcore_cli-0.3.1.tar.gz.
File metadata
- Download URL: apcore_cli-0.3.1.tar.gz
- Upload date:
- Size: 74.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da8f797789eed2745ab4eff53d8dedc365810715900599f39c3460c0e2be0be6
|
|
| MD5 |
51027ea6af2d5b90fe7fb207fd00ac31
|
|
| BLAKE2b-256 |
6172f22619c77b20ff2fed3f1be8b75803bbfe969f054ca3f10c5e0e0e71aa3b
|
File details
Details for the file apcore_cli-0.3.1-py3-none-any.whl.
File metadata
- Download URL: apcore_cli-0.3.1-py3-none-any.whl
- Upload date:
- Size: 37.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0689214229ba833aa00e6bbb15740cbff10b4d05b78927023331d8b2282acb4a
|
|
| MD5 |
e92650c6c053398a6f082764a7af1fdc
|
|
| BLAKE2b-256 |
0e4fa3c6f74ce923b328d1b6f26efae390bb6a65e38b9ad7b25ad840529b59e0
|