Skip to content

Commit cdb272c

Browse files
rustyconoverclaude
andcommitted
Improve vgi-client help text for LLM usability
Restructure CLI help to be clearer and more structured: - Add comprehensive epilog with examples, function types, argument format, output formats, and environment variables sections - Add short aliases: -o (output), -f (format), -s (server), -t (type) - Improve option descriptions to be concise and informative - Use Click's \b directive for proper formatting preservation - Organize examples by use case with comments The improved help text makes it easier for LLMs to understand how to use the CLI and construct correct commands. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 982c240 commit cdb272c

1 file changed

Lines changed: 91 additions & 48 deletions

File tree

vgi/client/cli.py

Lines changed: 91 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -168,122 +168,166 @@ def close(self) -> None:
168168
self._output_file_handle.close()
169169

170170

171+
_CLI_EPILOG = """
172+
\b
173+
EXAMPLES:
174+
# Table function (generates data, no input)
175+
vgi-client --function sequence --args '[10]'
176+
\b
177+
# Table-in-out function (transforms input)
178+
vgi-client --input data.parquet --function echo
179+
\b
180+
# Scalar function (per-row, single output column)
181+
vgi-client --input in.parquet --function upper_case -t scalar
182+
\b
183+
# Output to file with format
184+
vgi-client --function sequence --args '[5]' -o out.json
185+
vgi-client --function sequence --args '[5]' -o out.parquet -f parquet
186+
vgi-client --function sequence --args '[5]' -o - -f arrow-ipc
187+
\b
188+
# Catalog operations
189+
vgi-client catalog list -s vgi-example-worker
190+
vgi-client catalog attach mydb -s vgi-example-worker
191+
192+
\b
193+
FUNCTION TYPES:
194+
table No input, generates data (sequence, range)
195+
table-in-out Transforms input (echo, filter) - default with --input
196+
scalar Per-row transform, single column output (upper_case)
197+
auto Default: table-in-out if --input, else table
198+
199+
\b
200+
ARGUMENT FORMAT (--args as JSON array):
201+
'[]' No arguments
202+
'[10]' Single integer
203+
'["name"]' Single string (column name)
204+
'[0, 100, 5]' Multiple integers
205+
'[true, 3.14]' Mixed types
206+
207+
\b
208+
OUTPUT FORMATS (-f/--format):
209+
json JSON Lines, one object per row (default)
210+
csv CSV with header row
211+
parquet Apache Parquet columnar format
212+
arrow-ipc Arrow IPC stream (for debugging/piping)
213+
214+
\b
215+
ENVIRONMENT VARIABLES:
216+
VGI_IPC_DEBUG=1 Trace IPC read/write (protocol debug)
217+
VGI_IPC_STATS=1 Log IPC statistics per invocation
218+
VGI_QUIET=1 Suppress worker startup logging
219+
"""
220+
221+
171222
def _create_cli() -> Any:
172223
"""Create the CLI command group. Separated for testability."""
173224
import click
174225
import pyarrow.parquet as pq
175226

176227
from vgi.client.cli_catalog import catalog
177228

178-
@click.group(invoke_without_command=True)
229+
@click.group(invoke_without_command=True, epilog=_CLI_EPILOG)
179230
@click.option(
180231
"--input",
181232
"input_file",
182233
required=False,
183-
# This validates the that file exists.
184234
type=click.Path(exists=True),
185-
help="Path to input parquet file (omit for table functions without input)",
235+
help=(
236+
"Input parquet file path. Required for table-in-out and scalar functions. "
237+
"Omit for table functions (generators)."
238+
),
186239
)
187240
@click.option(
188241
"--output",
242+
"-o",
189243
"output_file",
190244
type=str,
191-
help="Path to output file (use - for stdout)",
245+
help="Output file path. Use '-' for stdout. If omitted, outputs to log.",
192246
)
193247
@click.option(
194248
"--format",
249+
"-f",
195250
"output_format",
196251
type=click.Choice(["json", "csv", "parquet", "arrow-ipc"]),
197252
default="json",
198-
help=(
199-
"Output format (default: json). Use 'arrow-ipc' for Apache Arrow IPC "
200-
"streaming format, which is useful for debugging or piping to other "
201-
"Arrow-aware tools."
202-
),
253+
help="Output format: json (default), csv, parquet, or arrow-ipc.",
203254
)
204255
@click.option(
205256
"--function",
206257
"function_name",
207258
required=False,
208259
type=str,
209-
help="Name of the function to run (e.g., echo, sum_all_columns, repeat_inputs)",
260+
help="Function name to invoke (e.g., sequence, echo, upper_case).",
210261
)
211262
@click.option(
212263
"--args",
213264
"arguments",
214265
default="[]",
215266
type=str,
216-
help="JSON array of arguments to pass to the function (default: [])",
267+
help="JSON array of positional arguments. Example: '[10]' or '[\"col\"]'.",
217268
)
218269
@click.option(
219270
"--server",
271+
"-s",
220272
"server_path",
221273
default="vgi-example-worker",
222274
type=str,
223-
help="Path to the VGI worker",
275+
help="VGI worker command or path. Default: vgi-example-worker.",
276+
)
277+
@click.option(
278+
"--type",
279+
"-t",
280+
"function_type",
281+
type=click.Choice(["auto", "table", "table-in-out", "scalar"]),
282+
default="auto",
283+
help=(
284+
"Function type: auto (default), table, table-in-out, or scalar. "
285+
"'auto' uses table-in-out if --input provided, otherwise table."
286+
),
224287
)
225288
@click.option(
226289
"--worker-stderr",
227-
"worker_stderr",
228290
is_flag=True,
229291
default=False,
230-
help="Pass worker stderr through to CLI stderr",
231-
)
232-
@click.option(
233-
"--projection-id",
234-
"projection_ids",
235-
multiple=True,
236-
type=int,
237-
help="Projection column ID (can be specified multiple times)",
292+
help="Pass worker stderr through to CLI stderr (for debugging).",
238293
)
239294
@click.option(
240295
"--max-workers",
241296
"max_workers",
242297
type=int,
243298
default=None,
244-
help="Maximum number of worker processes (clamps function's max_processes)",
299+
help="Max worker processes. Clamps function's max_processes setting.",
300+
)
301+
@click.option(
302+
"--projection-id",
303+
"projection_ids",
304+
multiple=True,
305+
type=int,
306+
help="Column ID for projection pushdown. Can be repeated.",
245307
)
246308
@click.option(
247309
"--table-input-position",
248310
"table_input_position",
249311
type=int,
250312
default=None,
251313
help=(
252-
"Position in positional arguments where table input should be inserted "
253-
"(0-indexed). If not specified, table input is not included in positional "
254-
"args. E.g., --args '[\"prefix\"]' --table-input-position 1 inserts "
255-
'table input at position 1, resulting in ("prefix", TABLE_INPUT).'
314+
"Position (0-indexed) to insert table input in positional args. "
315+
"Example: --args '[\"prefix\"]' --table-input-position 1"
256316
),
257317
)
258318
@click.option(
259319
"--attach-id",
260320
"attach_id",
261321
type=str,
262322
default=None,
263-
help=(
264-
"Unique identifier for the DuckDB database attachment as a hex string. "
265-
"Used to trace calls back to a specific attachment."
266-
),
267-
)
268-
@click.option(
269-
"--type",
270-
"function_type",
271-
type=click.Choice(["auto", "table", "table-in-out", "scalar"]),
272-
default="auto",
273-
help=(
274-
"Function type. 'auto' (default) uses table-in-out if --input is provided, "
275-
"otherwise table. Use 'scalar' for scalar functions."
276-
),
323+
help="DuckDB attachment ID (hex string) for catalog context.",
277324
)
278325
@click.option(
279326
"--transaction-id",
280327
"transaction_id",
281328
type=str,
282329
default=None,
283-
help=(
284-
"Unique identifier for the DuckDB transaction as a hex string. "
285-
"Allows functions to participate in transactional semantics."
286-
),
330+
help="DuckDB transaction ID (hex string) for transactional operations.",
287331
)
288332
@click.pass_context
289333
def cli(
@@ -302,11 +346,10 @@ def cli(
302346
function_type: str,
303347
transaction_id: str | None,
304348
) -> None:
305-
"""VGI client for function invocation and catalog management.
306-
307-
When called without a subcommand and with --function, invokes a VGI function.
308-
Use subcommands (catalog, schema, table, view, transaction) for catalog ops.
349+
"""VGI client - invoke functions and manage catalogs.
309350
351+
QUICK START: Use --function to invoke a VGI function, or use the
352+
'catalog' subcommand for catalog operations. See examples below.
310353
"""
311354
# If a subcommand is being invoked, skip function invocation
312355
if ctx.invoked_subcommand is not None:

0 commit comments

Comments
 (0)