FeatCopilot command-line interface.
Provides a stable, agent-friendly CLI for invoking FeatCopilot from shells,
notebooks, agentic workflows (e.g. Copilot/LLM tool-use), and CI pipelines
without writing Python glue code.
Subcommands
info
Print version and supported engines/methods. Always machine-readable
when --json is passed.
transform
Run :class:featcopilot.AutoFeatureEngineer on a tabular input file
(CSV / Parquet / JSON) and write engineered features to an output file.
Emits a JSON status line on stdout when --json is passed so that
agents can parse the result deterministically.
explain
Fit the engineer and print a JSON document describing each generated
feature (name, explanation, code) for downstream LLM consumption.
Examples:
Agentic usage (machine-readable result on stdout, errors on stderr)::
featcopilot info --json
featcopilot transform \
--input data.csv --target label --output features.csv \
--engines tabular --max-features 50 --json
featcopilot explain --input data.csv --target label --json
Equivalent module invocation::
python -m featcopilot info --json
Parquet I/O is supported only when pyarrow or fastparquet is
installed (FeatCopilot's base distribution does not pin either); info
reports the runtime availability via parquet_available.
main(argv=None)
CLI entry point.
Returns the process exit code; suitable for both the console_scripts
entry point (featcopilot) and python -m featcopilot. Argparse
usage errors (missing subcommand, unknown flag) and the cooperative
--help / --version actions all normally raise :class:SystemExit;
we trap those here and return their exit code so that programmatic
callers (and agent harnesses) get a consistent integer-returning API.
Source code in featcopilot/cli.py
| def main(argv: list[str] | None = None) -> int:
"""CLI entry point.
Returns the process exit code; suitable for both the ``console_scripts``
entry point (``featcopilot``) and ``python -m featcopilot``. Argparse
usage errors (missing subcommand, unknown flag) and the cooperative
``--help`` / ``--version`` actions all normally raise :class:`SystemExit`;
we trap those here and return their exit code so that programmatic
callers (and agent harnesses) get a consistent integer-returning API.
"""
parser = _build_parser()
try:
args = parser.parse_args(argv)
except SystemExit as exc:
# argparse uses SystemExit(0) for ``--help`` / ``--version`` and
# SystemExit(2) for usage errors (also writing to stderr). We let the
# output through but convert the exit into a return value so
# ``main(argv) -> int`` is honored even on parse-time failures.
code = exc.code
if code is None:
return 0
if isinstance(code, int):
return code
# Non-int code (e.g. error string): print to stderr, return 2.
sys.stderr.write(f"{code}\n")
return 2
try:
return args.func(args)
except (FileNotFoundError, ValueError) as exc:
# User-facing input/config errors: print a clean message to stderr
# without a traceback so agents can parse the failure.
sys.stderr.write(f"featcopilot: error: {exc}\n")
return 2
except KeyboardInterrupt:
sys.stderr.write("featcopilot: interrupted\n")
return 130
except Exception as exc: # pragma: no cover - defensive backstop
# Single deterministic stderr line so agents can parse the failure.
# We deliberately do NOT call ``logger.exception(...)`` here:
# FeatCopilot loggers write to stderr, which would append a second
# timestamped traceback after our structured line and break the
# CLI's "stderr is exactly one error message" contract. Internal
# failure introspection is the caller's job (e.g. set
# ``PYTHONFAULTHANDLER=1`` or attach a debugger).
sys.stderr.write(f"featcopilot: unexpected error: {type(exc).__name__}: {exc}\n")
return 1
|