Table of Contents

Command-line tool

OptunaSharp.Cli exposes the optunasharp command for creating and inspecting studies and coordinating ask/tell optimization from scripts or another process. It is a .NET global tool, not a Python wrapper. The tool targets .NET 8 and .NET 10 and bundles Core, the SQLite backend, and the StackExchange.Redis journal adapter.

dotnet tool install --global OptunaSharp.Cli
optunasharp --help

From a source checkout, the equivalent development entry point is:

dotnet run --project src/OptunaSharp.Cli/OptunaSharp.Cli.csproj -f net8.0 -- --help

Storage selection

Pass --storage to each invocation, or set OPTUNA_STORAGE. An explicit argument takes precedence over the environment variable.

Input Resolved backend
URL beginning with redis (including rediss) JournalStorage with StackExchangeJournalRedisBackend
Existing file path JournalStorage with JournalFileBackend
Other input, such as sqlite:///study.db SQLite RDBStorage; invalid input fails with a CLI usage error

An existing SQLite file should be supplied as sqlite:///study.db, not just study.db, because the plain existing-file path selects the journal backend. To create a new journal file, explicitly choose --storage-class JournalFileBackend. The file backend's default uses symlink locking; see journal locking for Windows permissions and the library's alternative lock implementation.

--storage-class accepts RDBStorage, JournalFileBackend, JournalRedisBackend, and the deprecated JournalFileStorage / JournalRedisStorage aliases. Redis class names select the StackExchange adapter. The CLI does not resolve EF Core, gRPC, or the other Redis client adapters; use their .NET APIs for those integrations. Its URL resolution is also separate from Core's StorageFunctions.GetStorage(string).

Ask/tell from an external training process

This Bash example creates a study and obtains a trial's sampled parameters as JSON:

optunasharp create-study --study-name quadratic --storage sqlite:///study.db

optunasharp ask --study-name quadratic --storage sqlite:///study.db \
  --sampler RandomSampler --sampler-kwargs '{"seed": 0}' \
  --search-space '{"x": {"name": "FloatDistribution", "attributes": {"low": -10.0, "high": 10.0, "log": false, "step": null}}}'

Read the returned trial number and params, evaluate those parameters in your training process, then report that trial's result:

# Replace 0 with the number from ask, and 4.0 with the measured objective value.
optunasharp tell --study-name quadratic --storage sqlite:///study.db --trial-number 0 --values 4.0
optunasharp trials --study-name quadratic --storage sqlite:///study.db -f json --flatten
optunasharp best-trial --study-name quadratic --storage sqlite:///study.db

In PowerShell, put each command on one line or use PowerShell continuation syntax instead of Bash backslashes. ask allocates a trial; it does not launch a training program. A worker that exits before tell leaves its trial unfinished, so the orchestrating application must decide how to handle failures. For multi-objective studies, use --directions at creation and supply the corresponding objective values to tell; inspect the front with best-trials.

The sampler factory resolves public sampler types in Core by reflection. It matches keyword names after removing underscores and ignoring case. It does not load BoTorch, PyCma, pymoo, or OptunaHub samplers as command-line plugins. Reconstructing a seeded sampler per CLI invocation also is not the same as keeping a stateful sampler alive in a .NET process.

Keyword binding supports scalar values; arbitrary nested objects or collection constructor arguments, such as a GridSampler search-space dictionary, are not generally constructible through --sampler-kwargs. This is separate from ask's distribution-based --search-space.

Commands and output

Command Purpose
create-study Create a named or generated-name study; --skip-if-exists permits reuse
delete-study Delete a study and its trial records
study set-user-attr Set a study attribute using --key and --value
study-names List study names
studies List study summaries
trials List trial details
best-trial Inspect the single-objective best trial
best-trials Inspect the multi-objective Pareto front
ask Allocate a trial and suggest from an explicit search space
tell Record trial values or a terminal state
storage upgrade Run the SQLite schema migration chain

Common options include --storage, --storage-class, -v / --verbose, -q / --quiet, --log-file, and --debug. Use subcommand help for accepted state names and argument cardinality.

-f value|json|table|yaml selects a format. study-names defaults to value, listing commands to table, and ask to json. --flatten expands structured columns such as parameters, attributes, and multi-objective values. The differential tests compare value, json, and table output against Python Optuna. YAML is valid but not byte-identical to PyYAML; command help and argument validation come from System.CommandLine rather than Python's argparse.

SQLite upgrades and cross-language use

The CLI uses the same SQLite schema as the library. Python Optuna can open compatible database files created through either entry point. storage upgrade invokes the SQLite backend's migration chain; it is not an EF Core migration command. It changes the database, so plan upgrades as part of your database lifecycle.

For Redis, journal log compatibility and snapshot limitations apply to the CLI too. The command-line interface does not broaden a backend's compatibility contract.

Implementation and verification

The command definitions, storage resolver, and sampler factory define the supported surface. The CLI tests cover command-output parity, storage resolution, sampler argument binding, and SQLite upgrades.