Skip to content

Epic: Add an agent-friendly EEGPrep CLI #175

Description

@suraj-ranganath

🤖

Summary

Build a first-class eegprep command-line interface for AI agents, batch jobs, and reproducible EEG preprocessing. This should complement, not replace, the existing human-facing eegprep-gui and mixed GUI/IPython eegprep-console workflows.

The CLI should expose EEGLAB-style workflows in a Python-native, deterministic, machine-readable interface:

EEGPrep CLI = EEGLAB-style workflows + Python reproducibility + machine-readable agent contract

Branch for implementation: feature/eegprep-agent-cli.
Base context: branched from feature/eeglab-full-standalone-completion; this work is stacked until that PR and its upstream stack land in origin/develop.

Product Goal

Agents should be able to inspect datasets, validate state, plan preprocessing, run transformations, capture provenance, recover from errors, and generate reports without importing Python objects or driving the GUI. Human users should still use eegprep-gui and eegprep-console for interactive workflows.

The CLI must be boring, predictable, and reproducible:

eegprep inspect sample_data/eeglab_data.set --json
eegprep validate sample_data/eeglab_data.set --json
eegprep resample sample_data/eeglab_data.set --freq 128 --output /tmp/resampled.set --json
eegprep pipeline validate preprocessing.yaml --json
eegprep pipeline plan preprocessing.yaml --json
eegprep pipeline run preprocessing.yaml --json

Core Design Decisions

  1. Add a new script entry point named eegprep.

    • Keep eegprep-gui and eegprep-console unchanged.
    • CLI runtime must not import Qt, IPython, or open a GUI unless a future explicit command asks for that.
  2. Prefer a real subcommand framework for long-term maintainability.

    • Recommended: Typer/Click, with Rich only for human help/table output if needed.
    • --json output must bypass Rich/color and write clean JSON to stdout.
    • If Typer adds more dependency cost than value during implementation, argparse is acceptable, but the command tree and tests should stay modular.
  3. Make stdout/stderr contracts strict.

    • stdout: command result only, JSON when --json is used.
    • stderr: progress, logs, and warnings.
    • files: datasets, manifests, reports, and artifacts.
  4. Use stable schemas and error codes.

    • Every JSON response includes status, schema_version, and either result payload or structured error.
    • Failures include stable code, message, optional path, and optional suggestion.
    • Suggested initial codes: INPUT_FILE_NOT_FOUND, UNSUPPORTED_FORMAT, OUTPUT_EXISTS, CONFIG_SCHEMA_ERROR, MISSING_CHANNEL_LOCATIONS, INVALID_EVENT_LATENCY, ICA_NOT_FOUND, DEPENDENCY_MISSING, BIDS_VALIDATION_FAILED, COMMAND_NOT_IMPLEMENTED.
  5. Never mutate inputs by surprise.

    • Commands that write data require --output or explicit --overwrite.
    • Default should be no-overwrite.
    • Expensive/destructive commands support --dry-run or --plan where meaningful.
  6. Preserve EEGLAB mental models without copying MATLAB ergonomics blindly.

    • Commands should map to researcher workflows, not internal module names.
    • Under the hood, use existing pop_*, IO, validation, BIDS, QC, and report functionality.
    • Returned manifests should include equivalent pop_* history when available.

Required Agent Help Surface

eegprep --help must include a section near the top:

Start here (for AI agents):
  eegprep skills get eegprep-cli

Skills ship with the CLI, stay version-matched, and include workflow patterns,
JSON contracts, safety boundaries, and copy-paste examples. Prefer this over
guessing from flag docs alone.

Add commands:

eegprep skills list
eegprep skills get eegprep-cli
eegprep skills get eegprep-cli --full
eegprep skills path eegprep-cli

The initial bundled skill should live in package resources and explain:

  • Always use --json for machine-readable output.
  • Use capabilities --json and schema ... --json before constructing commands.
  • Use pipeline validate and pipeline plan before running pipelines.
  • Read manifests after writing outputs.
  • Use stable error codes for recovery.
  • Keep GUI/console workflows separate from headless CLI workflows.

Command Grammar

Use a consistent pattern:

eegprep <workflow> <input> [options] --output <path> --json

Avoid clever positional overloads. Prefer explicit option names.

Global flags expected on commands where relevant:

--json
--quiet
--verbose
--no-progress
--no-color
--manifest <path>
--overwrite / --no-overwrite
--seed <int>
--deterministic
--threads <n>

Initial Command Set

Discovery and agent contract

eegprep capabilities --json
eegprep schema command inspect --json
eegprep schema pipeline --json
eegprep examples inspect
eegprep examples pipeline
eegprep skills list
eegprep skills get eegprep-cli

Read-only dataset workflows

eegprep inspect dataset <path> --json
eegprep inspect events <path> --json
eegprep inspect channels <path> --json
eegprep inspect ica <path> --json
eegprep validate <path> --json

Transform workflows

eegprep resample <input> --freq 128 --output <output> --json
eegprep rereference <input> --method average --output <output> --json
eegprep filter <input> --highpass 1 --lowpass 40 --notch 60 --output <output> --json
eegprep clean <input> --method asr --burst-criterion 20 --output <output> --json
eegprep epoch <input> --event-type target --tmin -0.2 --tmax 0.8 --output <output> --json
eegprep ica <input> --method runica --seed 42 --output <output> --json

QC, reports, and pipelines

eegprep qc <input> --json
eegprep qc report <input> --html qc.html --json
eegprep report <input> --output report.html --json
eegprep pipeline validate config.yaml --json
eegprep pipeline plan config.yaml --json
eegprep pipeline run config.yaml --json

BIDS and EEGLAB compatibility

eegprep bids validate <bids_root> --json
eegprep bids import <bids_root> --subject 01 --task rest --output sub-01.set --json
eegprep bids export <input.set> --bids-root bids_out --subject 01 --task rest --json
eegprep eeglab history <input.set> --json
eegprep eeglab compare <left.set> <right.set> --json
eegprep eeglab convert-script pipeline.m --to eegprep-yaml --output pipeline.yaml --json

The EEGLAB script converter can be best-effort. It must report confidence and unsupported commands rather than pretending unsupported MATLAB code is fully converted.

Pipeline Config Shape

Support YAML first because the repo already uses PyYAML in dev and pipeline configs are easier to edit than long shell commands.

Example:

schema_version: eegprep.pipeline.v1
input:
  path: sub-01.set
  format: eeglab
output:
  directory: derivatives/eegprep/sub-01
  overwrite: false
steps:
  - name: filter
    highpass: 1.0
    lowpass: 40.0
    notch: 60
  - name: rereference
    method: average
  - name: clean
    method: asr
    burst_criterion: 20
  - name: ica
    method: runica
    seed: 42
  - name: report
    format: html

pipeline plan --json should emit normalized steps, output paths, estimated destructive actions, and unsupported/missing dependency warnings without doing the work.

Manifest Contract

Every command that writes output supports --manifest. If omitted, pipeline commands should write a default manifest next to outputs.

Manifest fields:

{
  "schema_version": "eegprep.manifest.v1",
  "command": "resample",
  "input_files": [{"path": "sub-01.set", "sha256": "..."}],
  "output_files": [{"path": "sub-01_resampled.set", "type": "eeglab_set"}],
  "parameters": {"freq": 128.0},
  "history": "EEG = pop_resample(EEG, freq=128)",
  "software": {"eegprep_version": "...", "python_version": "..."},
  "runtime": {"started_at": "...", "finished_at": "..."},
  "deterministic": true,
  "warnings": []
}

Implementation Phases

Phase 1: CLI Foundation and Agent Contract

Scope:

  • Add eegprep entry point.
  • Add CLI package under a locally appropriate path such as src/eegprep/cli/.
  • Add result/error/manifest helpers.
  • Add global options and clean stdout/stderr routing.
  • Add skills, capabilities, schema, and examples command foundations.
  • Add bundled eegprep-cli skill content as packaged resource.
  • Add Sphinx docs page: Using EEGPrep with AI agents.

Acceptance criteria:

  • uv run eegprep --help shows the AI agents start-here section.
  • uv run eegprep skills get eegprep-cli prints version-matched skill content.
  • uv run eegprep capabilities --json emits parseable JSON.
  • uv run eegprep schema pipeline --json emits parseable schema-like JSON.
  • No CLI command imports Qt/IPython unless explicitly intended.
  • Tests prove JSON stdout is clean and errors are structured.

Phase 2: Read-Only Dataset Inspection and Validation

Scope:

  • Implement inspect dataset/events/channels/ica and validate.
  • Use existing loaders and eeg_checkset/session-neutral helpers.
  • Return stable schema versions and warning/error codes.

Acceptance criteria:

  • sample_data/eeglab_data.set can be inspected and validated from the CLI.
  • Events, channels, ICA, duration, data shape, sampling rate, and file metadata are reported in JSON.
  • Invalid/missing files return stable errors and nonzero exit codes.
  • stdout/stderr separation is tested.

Phase 3: Core Transform Commands

Scope:

  • Implement resample, rereference, filter, clean, epoch, and ica as headless commands.
  • Require explicit outputs unless --overwrite is supplied.
  • Write manifests and preserve pop_* history strings.
  • Support deterministic options where the underlying method supports them.

Acceptance criteria:

  • Commands run on sample_data/eeglab_data.set and write valid .set outputs.
  • Output overwrite/cancel/error behavior is deterministic and tested.
  • Commands return machine-readable summaries, warnings, and manifests.
  • Expensive commands provide progress on stderr without polluting JSON stdout.

Phase 4: Pipeline, Batch, QC, and Reports

Scope:

  • Implement pipeline validate, pipeline plan, and pipeline run.
  • Implement qc and qc report with JSON metrics and optional HTML.
  • Add batch execution for BIDS-like subject lists or explicit input lists.

Acceptance criteria:

  • Pipeline validation catches schema errors before work starts.
  • Plan mode emits normalized steps and expected outputs without mutating files.
  • Pipeline run produces outputs plus manifest.
  • Batch mode returns per-subject status and partial-success summaries.
  • QC outputs include stable recommendation codes agents can reason about.

Phase 5: BIDS and EEGLAB Migration Commands

Scope:

  • Implement bids validate/import/export using existing EEGPrep BIDS functionality.
  • Implement eeglab history, eeglab compare, and best-effort eeglab convert-script.

Acceptance criteria:

  • BIDS commands are explicit about missing optional dependencies.
  • EEGLAB history parsing maps recognized pop_* commands to CLI/pipeline equivalents with confidence.
  • Unsupported MATLAB commands are reported with stable codes and suggestions.
  • Comparison command emits structured differences, not free-form prose.

Phase 6: Closeout, Docs, and Agent QA

Scope:

  • Finish Sphinx CLI reference docs.
  • Add quickstarts for humans and agents.
  • Add examples for single command, pipeline, batch, BIDS, and EEGLAB migration.
  • Run mixed verification with shell-agent style subprocess tests.

Acceptance criteria:

  • Docs clearly distinguish eegprep, eegprep-gui, and eegprep-console.
  • Agent guide explains the stable contract and recovery patterns.
  • uv run --no-sync ruff check ., uv run --no-sync ruff format --check ., uv run --no-sync ty check, ./pre-commit.py --changed-from origin/develop, focused CLI tests, and EEGPREP_SKIP_MATLAB=1 uv run --no-sync pytest -m "not slow" pass.

MVP Recommendation

The first implementation PR should complete Phase 1 and enough of Phase 2 to prove the architecture:

  • eegprep --help
  • eegprep skills list|get|path
  • eegprep capabilities --json
  • eegprep schema pipeline --json
  • eegprep inspect dataset sample_data/eeglab_data.set --json
  • eegprep validate sample_data/eeglab_data.set --json

Then subsequent PRs can add transforms, pipelines, BIDS, and reports without reworking the contract.

Required References

  • AGENTS.md
  • .agents/skills/eegprep-feature-development/SKILL.md
  • .agents/skills/gui-agent-flow-qa/SKILL.md only for any workflow that crosses back into GUI/console behavior
  • Existing eegprep-console docs and tests, especially tests/test_console_workspace.py
  • Existing dataset IO, BIDS, QC, pop_*, and report code before adding new implementations

Suggested /goal Prompt

/goal Build the first agent-friendly EEGPrep CLI PR from issue <ISSUE_NUMBER> on branch feature/eegprep-agent-cli. Preserve existing eegprep-gui and eegprep-console behavior, add a new headless eegprep command with agent-focused help, skills retrieval, JSON/stdout-stderr contracts, stable errors, capabilities/schema discovery, and inspect/validate commands over sample_data. Use existing EEGPrep loaders and pop/session-neutral helpers rather than duplicating processing logic. Verify with subprocess CLI tests, sample_data integration tests, clean JSON stdout tests, manifest/error-code tests where applicable, docs updates, ruff/format/ty, pre-commit, and the relevant non-slow pytest subset. Fix review findings unless they are explicit scope creep and report any accepted non-goals.

Explicit Non-Goals For The First PR

  • Do not replace or rename eegprep-gui or eegprep-console.
  • Do not require agents to drive the GUI.
  • Do not add a hidden global session for the CLI.
  • Do not implement every preprocessing command before the JSON contract and discovery surface are stable.
  • Do not silently fake BIDS validation, MATLAB script conversion, or missing optional dependencies.

Metadata

Metadata

Labels

P1High priorityenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions