[
https://issues.apache.org/jira/browse/SOLR-17697?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18071531#comment-18071531
]
Jan Høydahl edited comment on SOLR-17697 at 4/6/26 10:12 PM:
-------------------------------------------------------------
Here is a coding agent prompt that can be used as a template to implement
picocli support for a tool. Procedure for adding more tools will be:
# Pick a tool you want to implement picocli support for
# Check out feature branch {{{}jira/SOLR-17697-picocli{}}},
# Make a new branch for your tool
# Implement the picocli supprt, feel free to use the prompt template below
# Make a PR with target branch {{{}jira/SOLR-17697-picocli{}}},
# Once review is done, it is squash-merged into the feature branch, and at the
end we do a normal merge to main to preserve each commit
{code:java}
Task: Add PicoCli support for XxxxxxTool and YyyyyyTool (replace)
You are adding picocli support to an existing Solr CLI tool in
solr/core/src/java/org/apache/solr/cli/. Respect AGENTS.md at all times.
Solr's CLI already use commons-cli for cmdline parsing. You will add picocli
support in parallel, and the project will remove commons-cli code at a later
stage.
## How the dual-path pattern works
- Every tool extends ToolBase, which has two entry points:
- runImpl(CommandLine cli) — existing commons-cli path, do not touch
- callTool() — picocli path, you must implement this
- SOLR_PICOCLI=true env var activates the picocli path in SolrCLI.main()
## Steps
1. Read the target tool in full before making any changes.
2. Extract business logic:
- if runImpl() does work inline, extract business logic into a private
doXxx(...)
method with explicit parameters
- if runImpl() delegates to methods taking commons-cli CommandLine as method
argument,
refactor such method to be independent of commons-cli and callable from both
paths.
- Both runImpl() and callTool() can now call the generic method(s).
Do not change the business logic behaviour or command output. See ZkRmTool as a
reference.
3. Add @picocli.CommandLine.Command to the class (name,
mixinStandardHelpOptions=true,
description). Do NOT set synopsisHeading — it is propagated from the root
command.
4. Declare picocli fields using mixins wherever possible — prefer reuse over
new @Option:
- ZkConnectionOptions — --zk-host, --solr-url, --credentials (all ZK tools use
this)
- RecursiveOption — --recursive (used by cp, ls, rm)
- ConfigSetOptions — --conf-name, --conf-dir (used by upconfig, downconfig)
- ToolBase already provides --verbose; do not redeclare it
- For remaining options use @Option / @Parameters, copying description wording
from
the existing commons-cli Option. See ZkLsTool or ZkMkrootTool for simple
examples,
ZkCpTool for a more complex one.
5. Implement callTool(): resolve connection, call doXxx() or similar, return 0
on success, throw on
error (ToolBase.call() handles printing and exit code). See ZkRmTool for the
pattern.
6. Register top-level tools in SolrCLI.java subcommands list. ZK subcommands
are already
listed in ZkTool.java — verify the tool is present there.
7. Do NOT resolve ZK/Solr connections during argument parsing (no I/O in
@Option defaults
or initialisers. All I/O belongs in callTool().
## Validation
- Run existing Java tests for the tool:
./gradlew :solr:core:test --tests "org.apache.solr.cli.*<ToolName>*"
- If a BATS test exists in solr/packaging/test/, run it twice:
./gradlew integrationTests --tests=test_<name>.bats
SOLR_PICOCLI=true ./gradlew integrationTests --tests=test_<name>.bats
On picocli-only failures, prefer adjusting picocli output to match existing
assertions
over weakening assertions. Only adjust assertions that check formatting rather
than
functional output, and only if they must accept both code paths.
- ./gradlew tidy
- ./gradlew check -x test
{code}
was (Author: janhoy):
Here is a coding agent prompt that can be used as a template to implement
picocli support for a tool. Procedure for adding more tools will be:
# Pick a tool you want to implement picocli support for
# Check out feature branch {{{}jira/SOLR-17697-picocli{}}},
# Make a new branch for your tool
# Implement the picocli supprt, feel free to use the prompt template below
# Make a PR with target branch {{{}jira/SOLR-17697-picocli{}}},
# Once review is done, it is squash-merged into the feature branch, and at the
end we do a normal merge to main to preserve each commit
{code:java}
Task: Add PicoCli support for XxxxxxTool (replace)
You are adding picocli support to an existing Solr CLI tool in
solr/core/src/java/org/apache/solr/cli/. Respect AGENTS.md at all times.
Solr's CLI already use commons-cli for cmdline parsing. You will add picocli
support in parallel, and the project will remove commons-cli code at a later
stage.
## How the dual-path pattern works
- Every tool extends ToolBase, which has two entry points:
- runImpl(CommandLine cli) — existing commons-cli path, do not touch
- callTool() — picocli path, you must implement this
- SOLR_PICOCLI=true env var activates the picocli path in SolrCLI.main()
## Steps
1. Read the target tool in full before making any changes.
2. Extract business logic: if runImpl() does work inline, move it into a
private
doXxx(...) method with explicit parameters. Both runImpl() and callTool() call
it.
Do not change the behaviour of the commons-cli path. See ZkRmTool as a
reference.
3. Add @picocli.CommandLine.Command to the class (name,
mixinStandardHelpOptions=true,
description). Do NOT set synopsisHeading — it is propagated from the root
command.
4. Declare picocli fields using mixins wherever possible — prefer reuse over
new @Option:
- ZkConnectionOptions — --zk-host, --solr-url, --credentials (all ZK tools use
this)
- RecursiveOption — --recursive (used by cp, ls, rm)
- ConfigSetOptions — --conf-name, --conf-dir (used by upconfig, downconfig)
- ToolBase already provides --verbose; do not redeclare it
- For remaining options use @Option / @Parameters, copying description wording
from
the existing commons-cli Option. See ZkLsTool or ZkMkrootTool for simple
examples,
ZkCpTool for a more complex one.
5. Implement callTool(): resolve connection, call doXxx(), return 0 on success,
throw on
error (ToolBase.call() handles printing and exit code). See ZkRmTool for the
pattern.
6. Register top-level tools in SolrCLI.java subcommands list. ZK subcommands
are already
listed in ZkTool.java — verify the tool is present there.
7. Do NOT resolve ZK/Solr connections during argument parsing (no I/O in
@Option defaults
or initialisers. All I/O belongs in callTool().
## Validation
- Run existing Java tests for the tool:
./gradlew :solr:core:test --tests "org.apache.solr.cli.*<ToolName>*"
- If a BATS test exists in solr/packaging/test/, run it twice:
./gradlew integrationTests --tests=test_<name>.bats
SOLR_PICOCLI=true ./gradlew integrationTests --tests=test_<name>.bats
On picocli-only failures, prefer adjusting picocli output to match existing
assertions
over weakening assertions. Only adjust assertions that check formatting rather
than
functional output, and only if they must accept both code paths.
- ./gradlew tidy
- ./gradlew check -x test
{code}
> Use picocli instead of commons-cli
> ----------------------------------
>
> Key: SOLR-17697
> URL: https://issues.apache.org/jira/browse/SOLR-17697
> Project: Solr
> Issue Type: Improvement
> Components: cli
> Reporter: Jan Høydahl
> Priority: Major
> Labels: pull-request-available
> Time Spent: 1h 10m
> Remaining Estimate: 0h
>
> Apache commons-cli has served us well for years, but our CLI has out-grown
> its capabilities, with multiple sub commands and a plethora of options and
> arguments. We have much custom code to work around limitations.
> By embracing [Picocli|https://picocli.info/], an annotation based cli
> framework, it will be easier to maintain the cli and add further tools. We
> propose to target 10.0 and do work gradually in a feature branch.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]