apcore-cli 0.6.0 → 0.8.0
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.
- package/CHANGELOG.md +187 -0
- package/LICENSE +13 -17
- package/README.md +160 -38
- package/dist/bin/apcore-cli.js +3712 -584
- package/dist/bin/apcore-cli.js.map +1 -1
- package/dist/index.d.ts +495 -133
- package/dist/index.js +2225 -1079
- package/dist/index.js.map +1 -1
- package/package.json +17 -10
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,193 @@ All notable changes to apcore-cli (TypeScript SDK) will be documented in this fi
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.0] - 2026-05-08
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
|
|
12
|
+
- **D11-008 — `AuditLogger.getUser` now includes `LOGNAME` in the env-var fallback chain** (`src/security/audit.ts:138`). The canonical user-resolution chain per spec `security.md` is `getlogin → pwd.getpwuid(getuid).pw_name → USER → LOGNAME → USERNAME → unknown`. The TS port collapsed the first two POSIX steps via `os.userInfo()` (correct) but then jumped from `USER` straight to `USERNAME`, dropping `LOGNAME`. On systems where only `LOGNAME` is set (some CI runners), audit entries fell through to `USERNAME` or `"unknown"` while Python/Rust/Go correctly resolved to `LOGNAME` — a cross-SDK divergence affecting the audit trail's user attribution. Fix inserts `process.env.LOGNAME` between `USER` and `USERNAME`.
|
|
13
|
+
|
|
14
|
+
### Removed (BREAKING)
|
|
15
|
+
|
|
16
|
+
- **D9-002 — root-level deprecation shims removed (FE-13 §11.3).** Pre-v0.8
|
|
17
|
+
`createCli()` registered 13 hidden root-level commands (`list`, `describe`,
|
|
18
|
+
`exec`, `init`, `validate`, `health`, `usage`, `enable`, `disable`,
|
|
19
|
+
`reload`, `config`, `completion`, `describe-pipeline`) that printed a
|
|
20
|
+
`WARNING: '<name>' as a root-level command is deprecated. ... Will be
|
|
21
|
+
removed in v0.8` line on stderr and forwarded to `apcli <name>`. Per
|
|
22
|
+
PROTOCOL_SPEC FE-13 §11.3 these shims are removed in v0.8 — the `apcli`
|
|
23
|
+
sub-group (or the renamed `builtinGroupName`) is now the only path to
|
|
24
|
+
built-in commands. Internal `_DEPRECATED_ROOT_COMMANDS`,
|
|
25
|
+
`_registerDeprecationShims`, `_collectShimForwardArgs`, and the
|
|
26
|
+
`__isDeprecationShim` collision-detection branch in `createCli`'s
|
|
27
|
+
`extraCommands` handler are deleted.
|
|
28
|
+
- **D9-W1 — raw mutable bindings `verboseHelp` / `docsUrl` no longer exported** from `src/main.ts:50,58`. The setter pair `setVerboseHelp` / `setDocsUrl` is the sanctioned API and remains exported. Mutable `let` exports are brittle as a public surface (live-binding semantics depend on the importer's bundler) and no embedder imports the raw bindings; the public surface now only includes the setters.
|
|
29
|
+
- **D9-W2 — `emitErrorJson` / `emitErrorTty` no longer exported** from `src/main.ts:158,180` and dropped from the `src/index.ts` public re-export list. Both are only consumed inside `main.ts` (`buildModuleCommand` action handler). Now annotated `@internal`.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **`builtinGroupName?: string` option on `createCli`** — downstream branded CLIs that embed apcore-cli can now expose the built-in commands under a custom namespace (e.g. `mycorp-cli admin health` instead of `mycorp-cli apcli health`). `ApcliGroup` gains a `name` getter and the constructor option is threaded through `fromCliConfig` / `fromYaml` / `tryFromYaml` / `_build`. Default `"apcli"` is unchanged. Validated against `/^[a-z][a-z0-9_-]*$/`; invalid values exit 2. Two new module-level accessors `getReservedGroupNames()` / `setReservedGroupNames()` expose the live reserved-set so `cli.ts`'s `assertNotReserved` and `listCommands` honour the renamed group. Env var `APCORE_CLI_APCLI` and config keys `apcli.*` deliberately do NOT rename — they are apcore-cli-internal toggles, not user-facing. Cross-SDK parity with Python `create_cli(builtin_group_name=...)`. New `DEFAULT_BUILTIN_GROUP_NAME` constant exported from `./builtin-group.js`.
|
|
34
|
+
- **Client-side approval gate for `apcli enable / disable / reload / config set`** — new `requireApprovalForSystemCommand(moduleId, autoApprove)` helper in `src/system-cmd.ts` synthesises a minimal `ModuleDescriptor` with `annotations.requires_approval = true` and invokes `checkApproval(...)` before dispatching the executor call. `ApprovalDeniedError` / `ApprovalTimeoutError` propagate to `emitErrorAndExit` which maps them to exit 46 via `exitCodeForError`. `apcli config set` gains a `-y, --yes` flag for parity with the other three. Mirrors Python `_check_system_approval` and Rust `require_approval_for_system_command`. Audit D11-B-001 (see Fixed).
|
|
35
|
+
- **14 new tests in `tests/builtin-group.test.ts`** — `ApcliGroup builtin-group rename` describe block covers default name, custom name via both factories, validation of 6 invalid + 5 valid name shapes.
|
|
36
|
+
- **5 new tests in `tests/system-cmd.test.ts`** — `client-side approval gate (D11-B-001)` describe block covers `enable / disable / reload / config set` deny path on non-TTY without `--yes` (exit 46 + executor never called) and the `--yes` bypass.
|
|
37
|
+
- **D1-info-1 — `ApcliGroupError` typed exception** (`src/builtin-group.ts:101`, re-exported from `src/index.ts`) for cross-SDK error-class parity with Rust (`apcore_cli::ApcliGroupError`, re-exported at `lib.rs:183`). The previous plain `Error` throw on invalid `builtinGroupName` gave consumers no programmatic way to discriminate apcli config errors from generic ones. Existing `catch (e) { if (e instanceof Error) ... }` blocks continue to work; new code can use `instanceof ApcliGroupError`. The neighbouring throw at `builtin-group.ts:464` (caller-bug guard for `isSubcommandIncluded` invoked under wrong mode) stays as plain `Error` — out of scope for apcli config validation.
|
|
38
|
+
- **D1-004 — `Sandbox` builder methods `withExtensionsRoot` and `withMaxOutputBytes`** (`src/security/sandbox.ts`). Cross-SDK parity with Python `with_extensions_root` / `with_max_output_bytes` and the new Rust builders. Both fields drive runtime behaviour: `extensions_root` takes precedence over inherited `APCORE_EXTENSIONS_ROOT`, `max_output_bytes` replaces the per-stream output cap. The "future builder (Python parity)" comment at `sandbox.ts:77` is removed.
|
|
39
|
+
- **D1-006 — `allowedPrefixes?: string[]` option on `CreateCliOptions`** plumbed through `createCli → applyToolkitIntegration → loadBindingDisplayOverlay` so non-allowlisted `target:` entries are dropped before they pollute the display map. Mirrors Python `factory.py:78 allowed_prefixes` safety knob. New `ApplyToolkitIntegrationOptions` type exported.
|
|
40
|
+
- **D1-007 — `formatModuleList`, `formatModuleDetail`, `resolveFormat` re-exported from `src/index.ts`** alongside `formatExecResult`. The output-formatter feature spec declares contracts for all four; embedders building custom output paths can now consume the canonical formatters from the package root.
|
|
41
|
+
- **D5-003 — dedicated `tests/system-usage.test.ts`** covering the new `src/system-usage.ts` aggregator (period filtering, per-module aggregates, missing-audit-log fallback) — previously coverage for the aggregator was only incidental via the discovery-layer integration tests.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **D11-B-001 — `system-cmd.ts` skipped the client-side approval gate entirely**. Each of the four mutating subcommands (`enable`, `disable`, `reload`, `config set`) declared `--yes` but never read it; no `checkApproval(...)` call existed in the file. Operators on Python or Rust SDKs got an interactive 60s confirmation prompt; TS users got nothing — server-side enforcement was the only gate, and the `--yes` flag was completely dead. Fix wires `requireApprovalForSystemCommand(moduleId, opts.yes)` into all four action handlers (see Added). Description text updated from "Signal explicit intent (forwarded to server-side approval gate)" to "Skip approval prompt" — the original copy was misleading because nothing was actually forwarded.
|
|
46
|
+
- **D11-NEW-005 — TS RESERVED_NAMES exit code was 2, not 48**. `schema-parser.ts:101` previously called `process.exit(EXIT_CODES.INVALID_CLI_INPUT)` (=2) when a schema property collided with a reserved CLI option name. Spec mandates exit 48 (cross-SDK parity with Python `sys.exit(48)` and Rust `CliError::SchemaParserFailure → EXIT_SCHEMA_CIRCULAR_REF`). Fix changes to `EXIT_CODES.SCHEMA_CIRCULAR_REF`. The neighbour flag-collision branch already exited 48; both schema-author errors are now consistent. 6 existing tests updated from "exits 2" assertions to "exits 48".
|
|
47
|
+
- **D11-NEW-001 — `resolveRefs` dropped parent `required` when resolving `anyOf` / `oneOf` branches**. A schema like `{required: ["x"], anyOf: [{required: ["a"]}, {required: ["a"]}]}` resolved to `required: ["a"]` in TS — silently losing `"x"`. Per JSON Schema semantics, `parent.required` applies in addition to the branch intersection. Branch handling now preserves the parent node's `required` field (deduplicated, sibling-first ordering). Aligned with Python `ref_resolver.py:100-118`; Rust got the same fix in a sibling commit. 4 new ref-resolver regression tests.
|
|
48
|
+
- **D11-NEW-003 — `max_depth` over-counted plain nested-object recursion**. Previously a schema with >32 levels of nested object `properties` (no `$refs`) was rejected; the depth budget should only count `$ref` hops + composition-branch descents, not pure structural recursion. Aligned with Rust's interpretation of the spec ("Maximum $ref resolution recursion depth").
|
|
49
|
+
- **D11-NEW-004 — `schema_to_cli_options` flag-collision sites exited 2, not 48**. The two flag-collision sites in `src/schema-parser.ts` (regular flag collision, no-flag collision) previously exited 2 (`INVALID_CLI_INPUT`) instead of 48 (`SCHEMA_CIRCULAR_REF`) — observable: a CI / embedder checking `$? == 48` to detect schema-related failures missed the TS path. Fix matches Python `sys.exit(48)`. 2 updated schema-parser collision tests.
|
|
50
|
+
- **D11-W4 — `schema_to_cli_options` did not warn on `required` entries missing from `properties`** (`src/schema-parser.ts:81`). Python (`schema_parser.py:93-98`) and Rust (`schema_parser.rs:220-228`) iterate the schema `required` list and warn for entries not present in `properties`. The TS SDK skipped that loop, so schemas like `{required: ["foo"]}` with no matching property parsed silently — schema authors lost the cross-SDK guard rail. Now emits the same warning text as Python: `Required property '%s' not found in properties, skipping.` 3 new regression tests cover missing-only, all-present, and multiple-missing cases.
|
|
51
|
+
- **D10-info-1 — `APCORE_CLI_APCLI` env-var parser did not trim** (`src/builtin-group.ts:488`). Per spec invariant 2 in `features/builtin-group.md`, the parser is case-insensitive AND trim-on-read. The TS port lowercased but skipped the trim, so values like `" show "` or `"\thide\n"` silently fell through to the unknown-value warning branch — diverging from Python and Rust. Fix adds `.trim()` before `.toLowerCase()` and short-circuits to `null` when the trimmed value is empty (all-whitespace env is now treated as unset without emitting a warning, matching empty-string handling).
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **`vitest.config.ts` `coverage.thresholds`** added — `lines / functions / statements: 85`, `branches: 75`. Cross-SDK CI parity with Python `pyproject.toml [tool.coverage.report] fail_under = 85` and Rust `make coverage --fail-under-lines 85`. Audit D5-004.
|
|
56
|
+
|
|
57
|
+
- **D8-W2 — `validateModuleId` extracted to dedicated `src/validate.ts`** for parallel-layout parity with Python (`apcore_cli/validate.py`) and Rust (`src/validate.rs`). Embedders reading multiple SDKs side-by-side previously had to grep for the helper inside `main.ts`. The existing import path is preserved via re-export from `main.ts`, so `discovery.ts` and tests need no changes. Adds an exported `MAX_MODULE_ID_LENGTH` constant for spec parity.
|
|
58
|
+
|
|
59
|
+
- **D1-W4 — `formatPreflightResult` / `firstFailedExitCode` annotated `@internal`** (`src/output.ts:406`). Both stay `export`ed because `main.ts` and `discovery.ts` import them across module boundaries, but they are not re-exported from `index.ts` and have no documented embedder use case. The `@internal` JSDoc tag now matches the import-graph reality so doc generators and human readers see they are not part of the package's stable API.
|
|
60
|
+
|
|
61
|
+
- **D6-TS-info — `@sinclair/typebox` ^0.32 → ^0.34** (`package.json:41`, resolves to 0.34.48). Cross-SDK dependency hygiene: Rust and Python pulled their matching schema-validation deps to current minors months ago; TS was the laggard. The only usage is the stable `Type.*` builder facade in `src/init-cmd.ts` (`Type.Object` / `Type.Array` / `Type.Optional` / `Type.String` / `Type.Number` / `Type.Boolean`), all of which are identical between 0.32 and 0.34 — no source changes required.
|
|
62
|
+
|
|
63
|
+
- **D6-001 — `apcore-toolkit` devDependency switched from local `link:` path to registry version `^0.6.0`**. The previous entry pointed at a developer's absolute local clone, which broke `pnpm install` for any other contributor. Clean clones now resolve `apcore-toolkit` identically to the peer-dependency declaration (`>=0.6.0`).
|
|
64
|
+
|
|
65
|
+
- **`apcli list` and `apcli describe` `--format` choices** are now validated
|
|
66
|
+
via Commander's `Option.choices(...)` against the canonical set
|
|
67
|
+
`[table, json, csv, yaml, jsonl, markdown, skill]`. Unknown values exit
|
|
68
|
+
with code 2 instead of silently no-op'ing. Issue
|
|
69
|
+
[aiperceivable/apcore-cli#20](https://github.com/aiperceivable/apcore-cli/issues/20).
|
|
70
|
+
- **Dependency bump**: peer-dep `apcore-js >= 0.21.0` (was `>= 0.19.0`) and the
|
|
71
|
+
optional `apcore-toolkit >= 0.6.0` (was `>= 0.5.0`). Aligns with upstream
|
|
72
|
+
`apcore 0.21.0` (Module.preview / PreflightResult.predicted_changes) and
|
|
73
|
+
`apcore-toolkit 0.6.0` (surface-aware formatters).
|
|
74
|
+
- **Issue #19 — drop "apcore" branding from embedded-mode `--help`**: top-level
|
|
75
|
+
CLI description now resolves from a new `description?: string` field on
|
|
76
|
+
`CreateCliOptions` (defaults to `${progName} CLI`); the `apcli` subgroup
|
|
77
|
+
description is now `Built-in commands` instead of `apcore-cli built-in
|
|
78
|
+
commands`; `--verbose` option text and the help footer drop the trailing
|
|
79
|
+
`apcore` from `(including built-in apcore options)`. Standalone bin entry
|
|
80
|
+
(`bin/apcore-cli.ts → main()`) passes `description="<prog> — execute apcore
|
|
81
|
+
modules from the command line"` explicitly so the standalone surface is
|
|
82
|
+
unchanged.
|
|
83
|
+
- **Conformance fixtures (`aiperceivable/apcore-cli/conformance/fixtures/apcli-visibility/`)**
|
|
84
|
+
refreshed to match the new debranded help output and to forward `version` /
|
|
85
|
+
`description` from the fixture inputs through `captureHelp()`.
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **`--format markdown` and `--format skill`** for `apcli list` and `apcli describe`
|
|
90
|
+
(issue [aiperceivable/apcore-cli#20](https://github.com/aiperceivable/apcore-cli/issues/20)).
|
|
91
|
+
Both delegate to `apcore-toolkit` (`formatModule` / `formatModules`, peer dep
|
|
92
|
+
≥0.6) so the output is byte-identical to the same toolkit call in the Python
|
|
93
|
+
and Rust SDKs. `--format skill` emits vendor-neutral SKILL.md content
|
|
94
|
+
directly loadable by Claude Code (`.claude/skills/<id>/SKILL.md`) and
|
|
95
|
+
Gemini CLI (`.gemini/skills/<id>/SKILL.md`):
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
apcore-cli apcli describe users.create --format skill > .claude/skills/users.create/SKILL.md
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
A new internal adapter `descriptorToScanned()` maps `ModuleDescriptor`
|
|
102
|
+
to the toolkit's `ScannedModule`. The `formatModuleList` and
|
|
103
|
+
`formatModuleDetail` functions are now `async` to support the dynamic
|
|
104
|
+
toolkit import (the existing five-format paths remain effectively
|
|
105
|
+
synchronous and complete before the returned promise resolves).
|
|
106
|
+
- **Issue #18 — host-app `--version` opt-in**: new `version?: string` field on
|
|
107
|
+
`CreateCliOptions`. When supplied, registers `-V/--version` with the host's
|
|
108
|
+
version string. **When omitted, the `--version` flag is no longer registered**
|
|
109
|
+
— embedded CLIs that do not opt in stop leaking the SDK's own version. The
|
|
110
|
+
standalone bin entry passes `version: VERSION` (the SDK package version)
|
|
111
|
+
explicitly so the `apcore-cli` binary's behaviour is preserved. The
|
|
112
|
+
`configureManHelp(...)` man-page generator falls back to the SDK version
|
|
113
|
+
when the host does not supply one, so manpages always carry a version stamp.
|
|
114
|
+
- **Issue #19 — `description?: string`** on `CreateCliOptions`.
|
|
115
|
+
- **Issue #17 — `system.usage` aggregator + `list --sort calls|errors|latency`**:
|
|
116
|
+
new module `src/system-usage.ts` reads `~/.apcore-cli/audit.jsonl`, filters
|
|
117
|
+
by period (default 24h), and returns per-module aggregates (`calls`,
|
|
118
|
+
`errors`, `avg latency_ms`). `list --sort {calls,errors,latency}` now
|
|
119
|
+
consults the aggregator instead of falling back to id-sort with a buried
|
|
120
|
+
`process.stderr.write("Warning: ...")`. When the audit log has no entries
|
|
121
|
+
in the period window the discovery layer prints a user-visible note to
|
|
122
|
+
stderr (`note: no usage data available for --sort <field>; sorted by id.
|
|
123
|
+
...`) and falls back to id-sort. Module-protocol registration of
|
|
124
|
+
`system.usage.summary` / `system.usage.module` as registry-callable
|
|
125
|
+
built-ins is tracked as a follow-up — today the readers are invoked
|
|
126
|
+
directly by the discovery layer.
|
|
127
|
+
- New file: `src/system-usage.ts`.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## [0.7.0] - 2026-04-25
|
|
132
|
+
|
|
133
|
+
### Added
|
|
134
|
+
|
|
135
|
+
- **Canonical clap v4 / GNU-style help formatter** (`src/canonical-help.ts`) overriding Commander's default `formatHelp` so `--help` output is byte-stable across SDK implementations. Disables terminal-width wrapping, uppercases `<PLACEHOLDER>`s, enforces `Commands:` before `Options:`, and renders `-h, --help` / `-V, --version` last with `Print help` / `Print version` descriptions.
|
|
136
|
+
- **Cross-language conformance test harness** (`tests/conformance/apcli-visibility.test.ts`) now consumes the shared fixtures from the `aiperceivable/apcore-cli` spec repo (`conformance/fixtures/apcli-visibility/`). Dynamically discovers scenarios and byte-matches `--help` output against each `expected_help.txt`. Set `APCORE_CLI_SPEC_REPO` to point at a non-sibling checkout; defaults to `../apcore-cli/`.
|
|
137
|
+
- **CI — spec-repo checkout**: `.github/workflows/ci.yml` now checks out `aiperceivable/apcore-cli` into `.apcore-cli-spec/` and exposes it to `pnpm test` via `APCORE_CLI_SPEC_REPO`.
|
|
138
|
+
- **FE-13: Built-in command group (`apcli`)** — consolidates the 13 canonical built-in commands (`list`, `describe`, `exec`, `validate`, `init`, `health`, `usage`, `enable`, `disable`, `reload`, `config`, `completion`, `describe-pipeline`) under a single `apcli` sub-group. Invocation shifts from `<cli> list` to `<cli> apcli list`.
|
|
139
|
+
- `ApcliGroup` class + `ApcliConfig` / `ApcliMode` types, exported from `src/index.ts`.
|
|
140
|
+
- `RESERVED_GROUP_NAMES = new Set(["apcli"])` as the enforced collision surface (replaces the retired per-command `BUILTIN_COMMANDS` constant).
|
|
141
|
+
- New env var `APCORE_CLI_APCLI` — accepts `show`, `hide`, `1`, `0`, `true`, `false` (case-insensitive).
|
|
142
|
+
- New config keys (snake_case DEFAULTS): `apcli.mode`, `apcli.include`, `apcli.exclude`, `apcli.disable_env`.
|
|
143
|
+
- `ConfigResolver.resolveObject(key)` — non-leaf accessor that returns object-shaped config values without flattening.
|
|
144
|
+
- `createCli({ apcli })` option — accepts `boolean | object | ApcliGroup` to configure the built-in group surface.
|
|
145
|
+
- See [migration guide](../apcore-cli/docs/features/builtin-group.md#11-migration) for the full v0.7 → v0.8 timeline.
|
|
146
|
+
- **New error-code → exit-code mappings** in `src/errors.ts` and `src/main.ts`: `DEPENDENCY_NOT_FOUND` and `DEPENDENCY_VERSION_MISMATCH` both map to exit code 44. Preserves the pre-0.19.0 exit code (`MODULE_LOAD_ERROR` = 44) for missing / version-mismatched module dependencies, now that apcore-js surfaces these through dedicated error types per PROTOCOL_SPEC §5.15.2.
|
|
147
|
+
- **Binding-overlay tests** in `tests/display-helpers.test.ts`: a tmp binding YAML is written, `applyToolkitIntegration` is called, and `getDisplay()` is verified to return the overlay for a descriptor that has no baked-in `metadata.display`.
|
|
148
|
+
- **`createCli({ app })` — `APCore` unified client**: `CreateCliOptions` now accepts an `app?: APCore` field. When provided, `app.registry` and `app.executor` are extracted and used in place of explicit `registry`/`executor` fields. Passing `app` together with `registry` or `executor` throws `"app is mutually exclusive with registry/executor"`.
|
|
149
|
+
- `APCore` interface exported from package index. `StrategyInfo` and `StrategyStep` interfaces exported from package index.
|
|
150
|
+
- `Executor` interface extended with optional `describePipeline(strategyName?: string): StrategyInfo` and `strategy?: { steps: StrategyStep[] }` fields.
|
|
151
|
+
- **FE-12: Module Exposure Filtering** — Declarative control over which discovered modules are exposed as CLI commands.
|
|
152
|
+
- `ExposureFilter` class in `exposure.ts` with `isExposed(moduleId)` and `filterModules(ids)` methods.
|
|
153
|
+
- Three modes: `all` (default), `include` (whitelist), `exclude` (blacklist) with glob-pattern matching.
|
|
154
|
+
- `ExposureFilter.fromConfig(obj)` static method for loading from `apcore.yaml` `expose` section.
|
|
155
|
+
- `CreateCliOptions.expose` field accepting object or `ExposureFilter` instance.
|
|
156
|
+
- `list --exposure {exposed,hidden,all}` filter flag in discovery commands.
|
|
157
|
+
- `GroupedModuleGroup` integration: applies exposure filter during command registration.
|
|
158
|
+
- `ConfigResolver` gains `expose.*` config keys.
|
|
159
|
+
- 4-tier config precedence: `CreateCliOptions.expose` > `--expose-mode` CLI flag > env var > `apcore.yaml`.
|
|
160
|
+
- Hidden modules remain invocable via `exec <module_id>`.
|
|
161
|
+
- New file: `exposure.ts`.
|
|
162
|
+
|
|
163
|
+
### Changed
|
|
164
|
+
|
|
165
|
+
- Built-in commands now live under the `apcli` sub-group. Pre-v0.7 invocations (`<cli> list`, `<cli> describe`, etc.) still work in **standalone mode** via deprecation shims that print a `WARNING` to stderr and forward to `apcli <name>`. Shims are not installed in embedded mode.
|
|
166
|
+
- Discovery flags (`--extensions-dir`, `--commands-dir`, `--binding`) are now gated on standalone mode — they are only registered when no `registry` is injected.
|
|
167
|
+
- Shell-completion generators (bash/zsh/fish) enumerate registered Commander subcommands dynamically; hardcoded command lists are gone.
|
|
168
|
+
- **Dependency bump**: requires `apcore-js >= 0.19.0` (was `>= 0.18.0`) and `apcore-toolkit >= 0.5.0` (was `>= 0.4.0`). Aligns with upstream releases `apcore-js 0.19.0` (dependency graph errors, async `buildStrategyFromConfig`, auto-schema adapter chain, `BindingSchemaMissingError` rename) and `apcore-toolkit 0.5.0` (`BindingLoader`, `ScannedModule.display`, `apcore-toolkit/browser` subpath).
|
|
169
|
+
- **Placeholder types in `src/cli.ts` realigned with real apcore-js shapes.** `PipelineTrace` / `StepTrace` / `PreflightResult` / `StrategyStep` now use camelCase (`strategyName`, `totalDurationMs`, `durationMs`, `skipReason`, `requiresApproval`, `timeoutMs`) matching the apcore-js runtime object shape. `Executor.describePipeline` is typed as `(): StrategyInfo` (zero arguments — the previous `describePipeline?(strategyName?: string)` signature declared an argument that the real apcore-js method ignores). `Executor.strategy` renamed to `Executor.currentStrategy` to match the upstream getter.
|
|
170
|
+
- **`--trace` output now reads the correct runtime fields.** `main.ts` previously read `trace.strategy_name` / `trace.total_duration_ms` / `s.duration_ms` / `s.skip_reason` (snake_case) from the camelCase `PipelineTrace` returned by apcore-js, so those values surfaced as `undefined` at runtime. Now reads `strategyName` / `totalDurationMs` / `durationMs` / `skipReason` correctly. JSON output keys remain snake_case to preserve the cross-language CLI output contract.
|
|
171
|
+
- **`formatPreflightResult` now reads `result.requiresApproval`** (was `result.requires_approval`). The JSON output key remains `requires_approval`.
|
|
172
|
+
- **`MAX_MODULE_ID_LENGTH` 128 → 192**: `validateModuleId()` now enforces a 192-character limit for module IDs, up from 128, to accommodate Java/.NET deep-namespace FQN-derived IDs (PROTOCOL_SPEC §2.7 spec 1.6.0-draft).
|
|
173
|
+
- **`Executor.describePipeline()` returns `StrategyInfo`**: `describe-pipeline` command in `strategy.ts` now calls `executor.describePipeline(strategyName)` and consumes the returned `StrategyInfo` object (`name`, `stepCount`, `stepNames`, `description`). Pipeline header format updated to `Pipeline: ${info.name} (${info.stepCount} steps)`. Step metadata (Pure/Removable/Timeout columns) sourced from `executor.strategy.steps` (`pure: boolean`, `removable: boolean`, `timeoutMs: number`). Falls back to static preset table when `describePipeline` is not available.
|
|
174
|
+
|
|
175
|
+
### Deprecated
|
|
176
|
+
|
|
177
|
+
- Root-level v0.6 built-in commands continue to work in standalone mode but emit a `WARNING` and forward to `apcli <name>`. **Scheduled for removal in v0.8.**
|
|
178
|
+
|
|
179
|
+
### Removed
|
|
180
|
+
|
|
181
|
+
- The per-command `BUILTIN_COMMANDS` constant and its re-export from `src/index.ts`. Replaced by `RESERVED_GROUP_NAMES`.
|
|
182
|
+
- Monolithic registrars `registerDiscoveryCommands`, `registerSystemCommands`, `registerShellCommands` — replaced by per-subcommand exports invoked through `ApcliGroup`.
|
|
183
|
+
|
|
184
|
+
### Fixed
|
|
185
|
+
|
|
186
|
+
- **`describe-pipeline --strategy <name>` now works for non-current strategies.** Previously the command called `executor.describePipeline(strategyName)` — the real apcore-js signature takes no arguments and always returns info for the executor's *current* strategy, so all `--strategy` values produced identical output. `src/strategy.ts` now uses a two-step lookup: if the requested name matches the current strategy, use `describePipeline()`; otherwise fall back to the static `Executor.listStrategies()` (reached via `executor.constructor.listStrategies`) to introspect other registered strategies.
|
|
187
|
+
- **`--binding <path>` flag now actually applies display overlay.** `applyToolkitIntegration` previously instantiated a `DisplayResolver` and discarded it. The implementation now uses apcore-toolkit 0.5.0's `BindingLoader` + `DisplayResolver` pipeline to parse the binding YAML, resolve the sparse overlay, and populate a module-level binding display map. `display-helpers.ts#getDisplay` consults the map as a fallback when the descriptor itself has no `metadata.display`, so `cli.alias` / `cli.description` / tags from `.binding.yaml` are now honored by `list`, `describe`, and command help output. New exports: `lookupBindingDisplay(moduleId)` and `clearBindingDisplayMap()` from `src/main.ts`.
|
|
188
|
+
|
|
189
|
+
### Breaking
|
|
190
|
+
|
|
191
|
+
- Reserved-name enforcement is now a **hard exit 2** when a module's explicit group, auto-group prefix, or top-level name/alias equals `apcli`. Previously this was warn-and-drop.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
8
195
|
## [0.6.0] - 2026-04-06
|
|
9
196
|
|
|
10
197
|
### Changed
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
2
4
|
|
|
3
|
-
Copyright
|
|
5
|
+
Copyright 2024 aiperceivable <tercel.yi@gmail.com>
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
copies or substantial portions of the Software.
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Terminal adapter for apcore. Execute AI-Perceivable modules from the command lin
|
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
[](https://nodejs.org)
|
|
11
|
-
[]()
|
|
12
12
|
|
|
13
13
|
| | |
|
|
14
14
|
|---|---|
|
|
@@ -49,7 +49,14 @@ Terminal adapter for apcore. Execute AI-Perceivable modules from the command lin
|
|
|
49
49
|
pnpm add apcore-cli apcore-js
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
Requires Node.js 18+ and `apcore-js >= 0.
|
|
52
|
+
Requires Node.js 18+ and `apcore-js >= 0.21.0`.
|
|
53
|
+
|
|
54
|
+
**Optional:** install `apcore-toolkit` (>=0.6.0) to enable display overlay and registry writer integration via `applyToolkitIntegration`, `DisplayResolver`, and `RegistryWriter`.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm add apcore-cli apcore-js
|
|
58
|
+
pnpm add -D apcore-toolkit # optional, for display overlay / registry writer
|
|
59
|
+
```
|
|
53
60
|
|
|
54
61
|
## Quick Start
|
|
55
62
|
|
|
@@ -95,21 +102,34 @@ const cli = createCli({
|
|
|
95
102
|
cli.parse(process.argv);
|
|
96
103
|
```
|
|
97
104
|
|
|
98
|
-
Or
|
|
105
|
+
Or wire the `createCli` options-object form directly with a runtime-supplied registry/executor:
|
|
99
106
|
|
|
100
107
|
```typescript
|
|
101
|
-
import {
|
|
102
|
-
import { Registry, Executor } from "apcore-js";
|
|
103
|
-
|
|
104
|
-
const registry = new Registry("./extensions");
|
|
105
|
-
registry.discover();
|
|
106
|
-
const executor = new Executor(registry);
|
|
108
|
+
import { createCli } from "apcore-cli";
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
async function main() {
|
|
111
|
+
// Obtain registry/executor from your apcore-js setup
|
|
112
|
+
// (e.g., via ExtensionsLoader or your framework's module discovery).
|
|
113
|
+
// See apcore-js docs for the exact bootstrap API.
|
|
114
|
+
const { registry, executor } = await bootstrapApcoreRuntime("./extensions");
|
|
115
|
+
|
|
116
|
+
const cli = createCli({
|
|
117
|
+
registry,
|
|
118
|
+
executor,
|
|
119
|
+
progName: "myapp",
|
|
120
|
+
// expose: { mode: "include", include: ["admin.*"] },
|
|
121
|
+
// apcli: { mode: "exclude", exclude: ["init"] }, // hide init from the apcli group
|
|
122
|
+
// apcli: false, // or hide the entire apcli group
|
|
123
|
+
// extraCommands: [customCmd1, customCmd2],
|
|
124
|
+
});
|
|
125
|
+
cli.parse(process.argv);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main();
|
|
111
129
|
```
|
|
112
130
|
|
|
131
|
+
> **Known gap:** The `Registry`, `Executor`, and `ModuleDescriptor` types re-exported by `apcore-cli` are currently **local placeholder interfaces** pending upstream export from `apcore-js`. Direct construction (`new Registry(...)` / `new Executor(registry)`) is **not supported** at this version. Structural typing allows runtime apcore-js objects to satisfy these interfaces, so `createCli({ registry, executor })` works when you pass in objects produced by your apcore-js runtime.
|
|
132
|
+
|
|
113
133
|
## Integration with Existing Projects
|
|
114
134
|
|
|
115
135
|
### Typical apcore project structure
|
|
@@ -168,15 +188,66 @@ apcore-cli [OPTIONS] COMMAND [ARGS]
|
|
|
168
188
|
| `--verbose` | | Show all options in help (including built-in apcore options) |
|
|
169
189
|
| `--man` | | Output man page in roff format (use with `--help`) |
|
|
170
190
|
|
|
171
|
-
### Built-in Commands
|
|
191
|
+
### Built-in Commands (the `apcli` group)
|
|
192
|
+
|
|
193
|
+
Starting in **v0.7.0**, all built-in commands live under an `apcli` sub-group
|
|
194
|
+
(see the `RESERVED_GROUP_NAMES` collision surface in `src/builtin-group.ts`).
|
|
195
|
+
Invocation:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
apcore-cli apcli list
|
|
199
|
+
apcore-cli apcli describe math.add
|
|
200
|
+
apcore-cli apcli exec math.add --a 5 --b 10
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
> **Migration note (v0.8):** Root-level built-ins (`apcore-cli list`, `apcore-cli describe`, …) were removed in v0.8 — use `<cli> apcli <subcommand>`.
|
|
204
|
+
> Only the `apcli` group is supported; legacy root-level shims have been retired.
|
|
205
|
+
> Embedded integrations (host CLIs that inject a `registry`) never had root-level
|
|
206
|
+
> built-ins in the first place. See the full migration timeline in the spec repo:
|
|
207
|
+
> [`docs/features/builtin-group.md §11 Migration`](../apcore-cli/docs/features/builtin-group.md#11-migration).
|
|
208
|
+
|
|
209
|
+
The canonical 13 `apcli` subcommands:
|
|
210
|
+
|
|
211
|
+
**Module invocation & discovery**
|
|
212
|
+
|
|
213
|
+
| Command | Description |
|
|
214
|
+
|---------|-------------|
|
|
215
|
+
| `apcli list` | List available modules with search, status, tag/annotation filters, sort, and dependency inspection (see `registerListCommand` in `src/discovery.ts`) |
|
|
216
|
+
| `apcli describe <module_id>` | Show full module metadata, schemas, and annotations (see `registerDescribeCommand` in `src/discovery.ts`) |
|
|
217
|
+
| `apcli describe-pipeline <module_id>` | Inspect the execution pipeline for a module (strategies, hooks, middleware; see `registerPipelineCommand` in `src/strategy.ts`) |
|
|
218
|
+
| `apcli exec <module_id>` | Internal routing alias for module execution (see `registerExecCommand` in `src/discovery.ts`) |
|
|
219
|
+
| `apcli usage <module_id>` | Show usage examples and flag hints for a module (see `registerUsageCommand` in `src/system-cmd.ts`) |
|
|
220
|
+
|
|
221
|
+
**System management**
|
|
172
222
|
|
|
173
223
|
| Command | Description |
|
|
174
224
|
|---------|-------------|
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
225
|
+
| `apcli config` | Inspect effective configuration and precedence (see `registerConfigCommand` in `src/system-cmd.ts`) |
|
|
226
|
+
| `apcli health` | Run health checks on registry, executor, config, and auth (see `registerHealthCommand` in `src/system-cmd.ts`) |
|
|
227
|
+
| `apcli reload` | Reload registry / rediscover extensions (see `registerReloadCommand` in `src/system-cmd.ts`) |
|
|
228
|
+
| `apcli enable <module_id>` | Enable a disabled module (see `registerEnableCommand` in `src/system-cmd.ts`) |
|
|
229
|
+
| `apcli disable <module_id>` | Disable a module without removing it (see `registerDisableCommand` in `src/system-cmd.ts`) |
|
|
230
|
+
|
|
231
|
+
**Workflow**
|
|
232
|
+
|
|
233
|
+
| Command | Description |
|
|
234
|
+
|---------|-------------|
|
|
235
|
+
| `apcli init module <id>` | Scaffold a new module (TS/JS/YAML binding) into the extensions or commands directory (see `registerInitCommand` in `src/init-cmd.ts`) |
|
|
236
|
+
| `apcli validate` | Validate modules and configuration against JSON Schema (see `registerValidateCommand` in `src/discovery.ts`) |
|
|
237
|
+
|
|
238
|
+
**Shell integration**
|
|
239
|
+
|
|
240
|
+
| Command | Description |
|
|
241
|
+
|---------|-------------|
|
|
242
|
+
| `apcli completion <shell>` | Generate shell completion script for bash / zsh / fish (see `registerCompletionCommand` in `src/shell.ts`) |
|
|
243
|
+
| `man [command]` (root) | Generate a man page in roff format for a single command or the whole program (see `configureManHelp` in `src/shell.ts`). Stays at the root (meta-command). |
|
|
244
|
+
|
|
245
|
+
#### Standalone vs. embedded surfaces
|
|
246
|
+
|
|
247
|
+
| Mode | Invocation | Notes |
|
|
248
|
+
|------|------------|-------|
|
|
249
|
+
| **Standalone** (`apcore-cli`) | `apcore-cli apcli <subcommand>` | Discovery flags (`--extensions-dir`, `--commands-dir`, `--binding`) are registered. Only the `apcli` group is supported (legacy root-level shims were removed in v0.8). |
|
|
250
|
+
| **Embedded** (`createCli({ registry, … })`) | `<host-cli> apcli <subcommand>` | Discovery flags are gated off (injected registry already supplies modules). Only the `apcli` group is supported. |
|
|
180
251
|
|
|
181
252
|
### Module Execution Options
|
|
182
253
|
|
|
@@ -187,25 +258,48 @@ When executing a module (e.g. `apcore-cli math.add`), these built-in options are
|
|
|
187
258
|
| `--input -` | Read JSON input from STDIN |
|
|
188
259
|
| `--yes` / `-y` | Bypass approval prompts |
|
|
189
260
|
| `--large-input` | Allow STDIN input larger than 10MB |
|
|
190
|
-
| `--format
|
|
191
|
-
| `--sandbox` | Run module in subprocess sandbox (
|
|
261
|
+
| `--format <fmt>` | Output format: `json`, `table`, `csv`, `yaml`, or `jsonl` |
|
|
262
|
+
| `--sandbox` | Run module in a subprocess sandbox (re-exec with stripped env; 64MiB stdout/stderr cap; 300s default timeout). Hidden by default — set `APCORE_CLI_SANDBOX=1` to enable globally. |
|
|
263
|
+
| `--dry-run` | Run preflight checks (schema, ACL, approval) without executing (FE-11) |
|
|
264
|
+
| `--trace` | Emit execution pipeline trace (strategy, hooks, middleware timings) |
|
|
265
|
+
| `--stream` | Stream results line-by-line for stream-capable modules |
|
|
266
|
+
| `--strategy <name>` | Override execution strategy: `standard`, `internal`, `testing`, `performance`, or `minimal` |
|
|
267
|
+
| `--fields <csv>` | Select output fields via dot-path notation (e.g. `result.sum,meta.duration`) |
|
|
268
|
+
| `--approval-timeout <seconds>` | Override approval timeout (default `60`) |
|
|
269
|
+
| `--approval-token <token>` | Provide a pre-obtained approval token (bypasses interactive prompt) |
|
|
192
270
|
|
|
193
271
|
Schema-generated flags (e.g. `--a`, `--b`) are added automatically from the module's `input_schema`.
|
|
194
272
|
|
|
273
|
+
#### `list` command flags (v0.6.0)
|
|
274
|
+
|
|
275
|
+
The `list` command supports enhanced filtering and inspection flags:
|
|
276
|
+
|
|
277
|
+
| Option | Description |
|
|
278
|
+
|--------|-------------|
|
|
279
|
+
| `--search <query>` | Fuzzy search across module IDs, descriptions, and annotations |
|
|
280
|
+
| `--status <state>` | Filter by status (e.g. `enabled`, `disabled`, `deprecated`) |
|
|
281
|
+
| `--annotation <key=value>` | Filter by an annotation key/value pair |
|
|
282
|
+
| `--sort <field>` | Sort by `name`, `status`, or other indexed fields |
|
|
283
|
+
| `--reverse` | Reverse sort order |
|
|
284
|
+
| `--deprecated` | Include deprecated modules in the output |
|
|
285
|
+
| `--deps` | Show dependency graph for each module |
|
|
286
|
+
|
|
195
287
|
### Exit Codes
|
|
196
288
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
| `
|
|
200
|
-
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
289
|
+
The exit codes below are also exported as the `EXIT_CODES` const-object from `apcore-cli` (canonical source: `src/errors.ts`) and are mapped from thrown errors via `exitCodeForError()`.
|
|
290
|
+
|
|
291
|
+
| Code | `EXIT_CODES` key | Meaning |
|
|
292
|
+
|------|------------------|---------|
|
|
293
|
+
| `0` | `SUCCESS` | Success |
|
|
294
|
+
| `1` | `MODULE_EXECUTE_ERROR` / `MODULE_TIMEOUT` | Module execution error |
|
|
295
|
+
| `2` | `INVALID_CLI_INPUT` | Invalid CLI input |
|
|
296
|
+
| `44` | `MODULE_NOT_FOUND` / `MODULE_LOAD_ERROR` / `MODULE_DISABLED` / `DEPENDENCY_NOT_FOUND` / `DEPENDENCY_VERSION_MISMATCH` | Module not found / disabled / load error |
|
|
297
|
+
| `45` | `SCHEMA_VALIDATION_ERROR` | Schema validation error |
|
|
298
|
+
| `46` | `APPROVAL_DENIED` / `APPROVAL_TIMEOUT` | Approval denied or timed out |
|
|
299
|
+
| `47` | `CONFIG_NOT_FOUND` / `CONFIG_INVALID` | Configuration error |
|
|
300
|
+
| `48` | `SCHEMA_CIRCULAR_REF` | Schema circular reference |
|
|
301
|
+
| `77` | `ACL_DENIED` | ACL denied |
|
|
302
|
+
| `130` | *(no key — set by signal handler)* | Execution cancelled (Ctrl+C) |
|
|
209
303
|
|
|
210
304
|
## Configuration
|
|
211
305
|
|
|
@@ -227,6 +321,10 @@ apcore-cli uses a 4-tier configuration precedence:
|
|
|
227
321
|
| `APCORE_AUTH_API_KEY` | API key for remote registry authentication | *(unset)* |
|
|
228
322
|
| `APCORE_CLI_SANDBOX` | Set to `1` to enable subprocess sandboxing | *(unset)* |
|
|
229
323
|
| `APCORE_CLI_HELP_TEXT_MAX_LENGTH` | Maximum characters for CLI option help text before truncation | `1000` |
|
|
324
|
+
| `APCORE_CLI_APPROVAL_TIMEOUT` | Default approval prompt timeout in seconds | `60` |
|
|
325
|
+
| `APCORE_CLI_STRATEGY` | Default execution strategy (`standard`, `internal`, `testing`, `performance`, `minimal`) | `standard` |
|
|
326
|
+
| `APCORE_CLI_GROUP_DEPTH` | Maximum nesting depth when rendering grouped module command trees | `2` |
|
|
327
|
+
| `APCORE_CLI_APCLI` | Override apcli group visibility (Tier 2). Accepts `show`/`1`/`true` → all, `hide`/`0`/`false` → none. Sealed by `apcli.disable_env: true`. | *(unset)* |
|
|
230
328
|
|
|
231
329
|
### Config File (`apcore.yaml`)
|
|
232
330
|
|
|
@@ -239,6 +337,14 @@ sandbox:
|
|
|
239
337
|
enabled: false
|
|
240
338
|
cli:
|
|
241
339
|
help_text_max_length: 1000
|
|
340
|
+
approval_timeout: 60 # seconds
|
|
341
|
+
strategy: standard # standard | internal | testing | performance | minimal
|
|
342
|
+
group_depth: 2 # grouped-module command-tree nesting depth
|
|
343
|
+
apcli: # built-in command group visibility (FE-13)
|
|
344
|
+
mode: all # all | none | include | exclude
|
|
345
|
+
include: [] # subcommand allowlist when mode=include
|
|
346
|
+
exclude: [] # subcommand denylist when mode=exclude
|
|
347
|
+
disable_env: false # set true to seal Tier 2 (APCORE_CLI_APCLI env var)
|
|
242
348
|
```
|
|
243
349
|
|
|
244
350
|
## Features
|
|
@@ -251,7 +357,7 @@ cli:
|
|
|
251
357
|
- **TTY-adaptive output** -- rich tables for terminals, JSON for pipes (configurable via `--format`)
|
|
252
358
|
- **Approval gate** -- TTY-aware HITL prompts for modules with `requires_approval: true`, with `--yes` bypass and 60s timeout
|
|
253
359
|
- **Schema validation** -- inputs validated against JSON Schema before execution, with `$ref`/`allOf`/`anyOf`/`oneOf` resolution
|
|
254
|
-
- **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing
|
|
360
|
+
- **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing (re-exec model, env stripping, 64MiB output cap)
|
|
255
361
|
- **Shell completions** -- `apcore-cli completion bash|zsh|fish` generates completion scripts with dynamic module ID completion
|
|
256
362
|
- **Man pages** -- `apcore-cli man <command>` for single commands, or `--help --man` for a complete program man page. `configureManHelp()` provides one-line integration for downstream projects
|
|
257
363
|
- **Documentation URL** -- `setDocsUrl()` adds doc links to help footers and man pages
|
|
@@ -284,7 +390,7 @@ apcore-cli (the adapter)
|
|
|
284
390
|
+-- approval TTY-aware HITL approval
|
|
285
391
|
+-- output TTY-adaptive JSON/table output
|
|
286
392
|
+-- AuditLogger JSON Lines execution logging
|
|
287
|
-
+-- Sandbox Subprocess isolation
|
|
393
|
+
+-- Sandbox Subprocess isolation (re-exec, env stripped, output capped)
|
|
288
394
|
|
|
|
289
395
|
v
|
|
290
396
|
apcore Registry + Executor (your modules, unchanged)
|
|
@@ -292,24 +398,40 @@ apcore Registry + Executor (your modules, unchanged)
|
|
|
292
398
|
|
|
293
399
|
## API Overview
|
|
294
400
|
|
|
295
|
-
**Classes:** `LazyModuleGroup`, `ConfigResolver`, `AuthProvider`, `ConfigEncryptor`, `AuditLogger`, `Sandbox`
|
|
401
|
+
**Classes:** `LazyModuleGroup`, `GroupedModuleGroup`, `ApcliGroup`, `ExposureFilter`, `CliApprovalHandler`, `ConfigResolver`, `AuthProvider`, `ConfigEncryptor`, `AuditLogger`, `Sandbox`
|
|
296
402
|
|
|
297
|
-
**Interfaces:** `CreateCliOptions`, `Registry`, `Executor`, `ModuleDescriptor`
|
|
403
|
+
**Interfaces:** `CreateCliOptions`, `Registry`, `Executor`, `ModuleDescriptor`, `APCore`, `ApcliConfig`, `ApcliMode`, `StrategyInfo`, `StrategyStep`
|
|
298
404
|
|
|
299
|
-
**Functions:** `createCli`, `main`, `buildModuleCommand`, `validateModuleId`, `collectInput`, `schemaToCliOptions`, `reconvertEnumValues`, `resolveRefs`, `checkApproval`, `
|
|
405
|
+
**Functions:** `createCli`, `main`, `buildModuleCommand`, `validateModuleId`, `collectInput`, `schemaToCliOptions`, `reconvertEnumValues`, `resolveRefs`, `checkApproval`, `formatExecResult`, `registerListCommand`, `registerDescribeCommand`, `registerExecCommand`, `registerValidateCommand`, `registerHealthCommand`, `registerUsageCommand`, `registerEnableCommand`, `registerDisableCommand`, `registerReloadCommand`, `registerConfigCommand`, `registerCompletionCommand`, `registerPipelineCommand`, `registerInitCommand`, `setAuditLogger`, `getAuditLogger`, `setVerboseHelp`, `setDocsUrl`, `configureManHelp`, `exitCodeForError`
|
|
300
406
|
|
|
301
407
|
**Errors:** `ApprovalTimeoutError`, `ApprovalDeniedError`, `AuthenticationError`, `ConfigDecryptionError`, `ModuleExecutionError`, `ModuleNotFoundError`, `SchemaValidationError`
|
|
302
408
|
|
|
303
409
|
## Development
|
|
304
410
|
|
|
411
|
+
The conformance suite under `tests/conformance/` reads shared fixtures from
|
|
412
|
+
the **spec repo** (`aiperceivable/apcore-cli`). Clone it as a sibling of
|
|
413
|
+
this repo, or point `APCORE_CLI_SPEC_REPO` at an existing checkout:
|
|
414
|
+
|
|
305
415
|
```bash
|
|
416
|
+
# One-time: clone both repos side by side
|
|
417
|
+
git clone https://github.com/aiperceivable/apcore-cli.git
|
|
306
418
|
git clone https://github.com/aiperceivable/apcore-cli-typescript.git
|
|
419
|
+
|
|
307
420
|
cd apcore-cli-typescript
|
|
308
421
|
pnpm install
|
|
309
|
-
pnpm test #
|
|
422
|
+
pnpm test # reads fixtures from ../apcore-cli/conformance/
|
|
310
423
|
pnpm build # compile TypeScript
|
|
311
424
|
```
|
|
312
425
|
|
|
426
|
+
Alternative layout (spec repo checked out elsewhere):
|
|
427
|
+
|
|
428
|
+
```bash
|
|
429
|
+
export APCORE_CLI_SPEC_REPO=/path/to/apcore-cli
|
|
430
|
+
pnpm test
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
CI does this automatically — see `.github/workflows/ci.yml`.
|
|
434
|
+
|
|
313
435
|
## License
|
|
314
436
|
|
|
315
437
|
Apache-2.0
|