Multi-adapter CLI integration SDK for OpenCLI: browser / desktop / public-API adapters, remote agent and center WebSocket 简体中文
Current branch:
feature/2.0.xVersion:2.0.x.x.20260630-SNAPSHOTJDK baseline: 8 Project status: stable (1.0.x line). Not yet published to Maven Central; artifacts are distributed via the Aliyun Maven repository and GitHub Releases.
- 1. Project Overview
- 2. Features & Status
- 3. Requirements & Compatibility
- 4. Architecture & Modules
- 5. Installation
- 6. Quick Start
- 7. Configuration
- 8. Core Usage
- 9. Testing & Build
- 10. Versioning & Branches
- 11. Contributing & License
opencli-java-sdk integrates Java applications with the OpenCLI multi-adapter CLI ecosystem. It executes opencli <adapter> ... subprocesses via Commons Exec, exposes typed results (OpenCliResult / OpenCliTypedResult), unified exception semantics, remote HTTP agent support (Unirest) and a center WebSocket reverse-agent client (Java-WebSocket). It compiles and runs on JDK 8.
- Not OpenCLI itself and not a browser automation engine — it drives the
opencliCLI. - No Spring dependency; Spring Boot applications use the companion
opencli-spring-boot-starter. - Not an SDK generator for new adapters; adapter IDs are generated from the upstream
opencli/docs/adapters/index.mdmanifest.
| Scenario | Recommended entry | Result |
|---|---|---|
| Run any adapter command | cli.adapter("hackernews").invoke("top", "--limit", "5") |
Typed OpenCliResult |
| Typed wrapper for a known adapter | cli.gemini().deepResearch(...), cli.npm(), cli.codex() ... |
Strongly-typed options and results |
| Batch over all adapters | OpenCliAdapterEnumerator + OpenCliAdapterIds.ALL |
Sequential adapter execution |
| Run commands through a remote agent | executionTarget=REMOTE_AGENT_HTTP + remoteAgentBaseUrl |
POST {base}/collect execution |
| Join a center as an edge node | OpenCliWsReverseAgentClient |
Register, receive collect, reply result |
| Capability | Status | Notes |
|---|---|---|
| Local subprocess execution | Available | OpenCliExecutor (Commons Exec), unified exceptions (OpenCliNonZeroExitException, OpenCliTimeoutException, ...) |
| Adapter channel | Available | OpenCliAdapterChannel (invoke(List) / varargs) |
| Adapter registry | Available | OpenCliAdapterIds + OpenCliAdapterTaxonomy — 173 adapter ids (163 browser + 10 desktop) generated from the upstream manifest |
| Typed wrappers | Available | codex, cursor, gemini, claude, chatgpt, jimeng, deepseek, arxiv, npm, pypi, binance, wikipedia |
| Categorized facades | Available | PublicApiClient, BrowserClient, DesktopClient (or publicApis() / browsers() / desktops()) |
| Meta commands | Available | cli.meta(): list, validate, plugin, daemon, profile, completion, skills, auth, antigravity, ... |
| Built-in browser session API | Available | cli.browser(): wait (ms timeout), extract, screenshot, getHtml, ... |
| Availability probe | Available | OpenCliAvailabilityChecker + OpenCliAvailabilityReport (remote mode reports SKIPPED_REMOTE_MODE) |
| Remote agent (HTTP) | Available | OpenCliRemoteAgentHttpClient; remoteCaptureRawHttpResponse debug flag |
| Center WebSocket reverse agent | Available | OpenCliWsReverseAgentClient (register / collect / result / ping-pong) |
| JSON output parsing | Available | OpenCliStdoutJson.typed(raw); OpenCliParsedFields |
| Component | Version | Notes |
|---|---|---|
| JDK | 17+ | 1.0.x line baseline |
| commons-exec | — | Local subprocess execution |
| Unirest Java | — | Remote agent HTTP |
| Java-WebSocket | — | Center WebSocket |
| Jackson databind | 2.17.x | JSON parsing |
| SLF4J | 2.0.18 | Logging facade |
Version-line matrix:
| Version line | Branch | JDK | Version pattern | Purpose |
|---|---|---|---|---|
| 1.0.x | feature/2.0.x (this branch) |
8 | 1.0.x.* |
For Boot 2.x starters and legacy projects |
| 2.0.x | feature/2.0.x |
17 | 2.0.x.* |
For Boot 3.x starters |
| 3.0.x | feature/3.0.x |
21 | 3.0.x.* |
For Boot 4.x starters / new projects |
[ Java Application ]
|
| opencli-java-sdk
v
+------------------------------------------+
| OpenCliClient (facade) |
| core OpenCliExecutor -> local |
| `opencli <adapter> ...` |
| adapters browser / desktop / publicapi |
| typed wrappers (codex, npm...) |
| meta list / validate / plugin / ... |
| browser session API (wait, extract...) |
| remote POST {base}/collect (Unirest) |
| center WebSocket reverse agent |
+------------------------------------------+
|
v
[ opencli CLI ] / [ remote agent ] / [ center WS ]
Single-module library (packaging jar). Package layout:
| Package | Responsibility |
|---|---|
io.github.easy4j.opencli |
Facade OpenCliClient, OpenCliProperties, OpenCliExecutionTarget |
io.github.easy4j.opencli.core |
OpenCliExecutor, OpenCliAdapterChannel, results, availability |
io.github.easy4j.opencli.adapter |
Typed adapter clients (browser: chatgpt/claude/deepseek/gemini/jimeng; desktop: codex/cursor; publicapi: arxiv/binance/npm/pypi/wikipedia) |
io.github.easy4j.opencli.browser |
Built-in browser session client + options |
io.github.easy4j.opencli.facade |
PublicApiClient / BrowserClient / DesktopClient |
io.github.easy4j.opencli.meta |
Meta clients (list, plugin, daemon, profile, skills, auth, ...) |
io.github.easy4j.opencli.registry |
OpenCliAdapterIds (173 ids), OpenCliAdapterTaxonomy |
io.github.easy4j.opencli.remote |
Remote agent HTTP client |
io.github.easy4j.opencli.center.ws |
Center WebSocket reverse agent + path/URL helpers |
io.github.easy4j.opencli.parser / spi / util |
Stdout-JSON parsing, adapter enumeration SPI, helpers |
Maven:
<dependency>
<groupId>io.github.easy4j</groupId>
<artifactId>opencli-java-sdk</artifactId>
<version>2.0.x.x.20260630-SNAPSHOT</version>
</dependency>Gradle:
implementation 'io.github.easy4j:opencli-java-sdk:2.0.x.x.20260630-SNAPSHOT'Snapshot builds require an enabled snapshot repository (Aliyun Maven snapshot repository per distributionManagement in pom.xml).
OpenCliProperties props = new OpenCliProperties();
props.getEnvironment().put("OPENCLI_CDP_ENDPOINT", "http://127.0.0.1:9222");
OpenCliClient cli = new OpenCliClient(props);
// Any adapter (ids match `opencli list` / the generated registry)
OpenCliResult r = cli.adapter("hackernews").invoke("top", "--limit", "5");
System.out.println(r.getExitCode() + ": " + r.getStdout());
// Typed example: Gemini deep-research (--confirm is the button label, not a boolean)
cli.gemini().deepResearch("topic",
GeminiOpenCliClient.GeminiDeepResearchOptions.builder().confirmLabel("Start").build(),
null);Expected result: the first call spawns opencli hackernews top --limit 5 locally and returns a typed OpenCliResult; the second invokes the Gemini adapter's deep-research command with typed options. When the opencli executable is missing, OpenCliExecutor surfaces the failure through the unified exception hierarchy (OpenCliStartupException / OpenCliExecutableFailureException).
Configuration is object-based via OpenCliProperties:
| Property | Default | Description |
|---|---|---|
executionTarget |
LOCAL_PROCESS |
LOCAL_PROCESS or REMOTE_AGENT_HTTP |
executable |
opencli |
Executable name or absolute path |
workingDirectory |
— | Subprocess working directory |
commandTimeoutMillis |
300000 |
Command timeout (ms; reused as HTTP timeout in remote mode) |
maxConcurrentExecutions |
0 |
Max concurrent subprocesses (0 = unlimited) |
startupProbeTimeoutMillis |
30000 |
Availability-probe timeout |
environment |
{} |
Extra environment variables (e.g. OPENCLI_CDP_ENDPOINT) |
remoteAgentBaseUrl |
— | Remote agent base URL |
remoteCollectMode |
cdp |
bridge or cdp (must match the agent side) |
remoteOutputFormat |
json |
Output format requested from the agent |
remoteCdpEndpoint |
— | Optional CDP endpoint overriding the agent default |
remoteCaptureRawHttpResponse |
false |
Keep the raw HTTP body in OpenCliResult#getRemoteRawHttpBody() (large responses — use with care) |
Notes:
- In remote mode the
stdoutis the JSONitemsthe agent returned (parsed into line items performat), which may differ from local raw subprocess text;leadingArgumentsare local-only and are not injected on the remote path. execution-target=REMOTE_AGENT_HTTPmakes the availability probe reportSKIPPED_REMOTE_MODE(treated as startable).
cli.meta().list("json");
cli.meta().completion("zsh");
cli.browser().session("work", "background").waitFor("selector", ".loaded", null, 10_000L);OpenCliProperties exec = new OpenCliProperties();
exec.getEnvironment().put("OPENCLI_CDP_ENDPOINT", "http://127.0.0.1:9222");
OpenCliWsAgentConnectionProperties conn = new OpenCliWsAgentConnectionProperties();
conn.setCentralApiBaseUrl("http://center-host:8031");
conn.setAgentAdvertiseUrl("http://this-host:19823");
conn.setWebSocketPath(io.github.easy4j.opencli.center.ws.OpenCliCenterWebSocketPath.NODES_WS);
conn.setMode("cdp");
conn.setNodeType("shell");
conn.setLabel("my-java-agent");
OpenCliWsReverseAgentClient agent = new OpenCliWsReverseAgentClient(exec, conn);
agent.start();
// ...
agent.close();Protocol: edge sends register; center replies registered; center sends collect (request_id, site, command, args, positional_args, format, mode); the SDK executes opencli locally (via copyForLocalCliExecution() to avoid loops) and replies result; plus ping / pong.
mvn clean verify- Unit tests cover the adapter registry, core execution, browser/meta/remote paths and WS helpers (14 test sources under
src/test). - JaCoCo runs
prepare-agent,reportandcheckon theverifyphase with a 90% line-coverage rule (haltOnFailure=false). scripts/generate_opencli_adapter_ids.pyregeneratesOpenCliAdapterIds/OpenCliAdapterTaxonomyfrom the upstreamopencli/docs/adapters/index.md+cli-manifest.json(setOPENCLI_ROOTto point at the upstream tree).- Release packaging (
mvn -Prelease deploy) attaches sources and javadoc jars, GPG-signs artifacts and is wired for Sonatype Central Publishing; plainmvn deployroutes SNAPSHOT/release artifacts to the Aliyun Maven repository perdistributionManagement.
| Branch | Version pattern | JDK | Maintenance policy |
|---|---|---|---|
feature/1.0.x (this branch) |
1.0.x.* |
8 | Compatibility fixes and JDK-8-safe dependency upgrades only |
feature/2.0.x |
2.0.x.* |
17 | JDK 17 line |
feature/3.0.x |
3.0.x.* |
21 | JDK 21 line |
Branch POMs (JDK and dependency stack per line) are rendered by scripts/render-branch-pom.py.
Contributions are welcome. Run mvn clean verify before opening a pull request and describe compatibility, testing and migration impact. This project is licensed under the Apache License 2.0.