che-cli

Architecture

che-cli is intentionally small. There is no plugin manifest, no daemon, no configuration file — just a dispatcher script, a provider router, and a flat tree of single-purpose shell modules.

Source: github.com/chevp/che-cli · Back to overview


Components

bin/che                      dispatcher (~30 lines)
lib/che/
  platform.sh                OS detection: darwin | windows | wsl | linux
  provider.sh                routes calls to the active provider
  ui.sh                      shared UI helpers (spinner)
  frontmatter.sh             YAML frontmatter parser shared by status / issue
  doctor.sh                  che doctor — runs all checks
  status.sh                  che status (incl. issues, PRs, plans via gh)
  issue.sh                   che issue (create / list / close via gh)
  git/
    check.sh                 git + gh availability checks
    commit.sh                che commit
    ship.sh                  che ship (recurses into submodules)
  ollama/
    check.sh
    client.sh                ollama_ping / _has_model / _generate
  claude-code/
    check.sh
    client.sh                wraps the `claude` CLI binary
  copilot/
    check.sh
    client.sh                wraps the `copilot` CLI binary
  docker/
    check.sh
    client.sh
  workflow.sh                sub-dispatcher: list / show / run
  workflow/
    check.sh                 verifies python3 + PyYAML
    loader.sh                shared parsing + ${input} substitution
    yaml_get.py              tiny YAML query helper (replaces yq)
    list.sh                  che workflow list
    show.sh                  che workflow show <name>
    run.sh                   che workflow run <name>  /  che run <name>

Every provider folder follows the same convention:

provider.sh reads $CHE_PROVIDER and dispatches to the matching function set, so the rest of the codebase never branches on provider name.


Control flow: che commit

┌────────────┐    ┌─────────────┐    ┌──────────────────┐
│ user types │ ─► │  bin/che    │ ─► │ lib/che/git/     │
│ che commit │    │ (dispatch)  │    │  commit.sh       │
└────────────┘    └─────────────┘    └────────┬─────────┘
                                              │
       ┌──────────────────────────────────────┘
       ▼
   git add -A
       │
       ▼
   git diff --cached  ──►  truncate at CHE_MAX_DIFF_CHARS
       │
       ▼
   build prompt (commit-format rules + diff)
       │
       ▼
   provider_ping?  ── no ──►  exit with hint
       │ yes
       ▼
   provider_generate (in background)  ◄── ui_spin shows spinner
       │
       ▼
   parse: first line = title, remaining = body bullets
       │
       ▼
   confirm? ─ Y ─►  git commit -F <tmpfile>
            ─ N ─►  abort
            ─ E ─►  git commit -e -F <tmpfile>
       │
       ▼
   --push?  ──►  git push

The commit message is written to a tempfile and passed via git commit -F, which preserves the title/body structure exactly as the model produced it.


Control flow: che ship

che ship is a thin wrapper that recurses through git submodules before doing the work in the outer repo:

.gitmodules?
  yes ─►  for each submodule:
            init if missing
            ff-pull if on a branch (skip if detached HEAD)
            ( cd <submodule> && che ship )           ◄── recursion
  ─────►  che commit --push --yes  in the outer repo

This is why a single che ship at the top of a workspace can update every nested repo in one shot — each submodule self-ships, then the parent commits the updated pointers.


Provider router

provider.sh is the only file that knows the set of valid provider names. Adding a new provider is a three-step change:

  1. Create lib/che/<name>/client.sh that exports <name>_ping, <name>_has_model, and <name>_generate.
  2. Create lib/che/<name>/check.sh for che doctor.
  3. Add <name> to the case arm in provider.sh and register a default model in provider_active_model.

No registration in the dispatcher, no manifest, no module index.


Cross-cutting helpers


Design choices


© 2025 Patrice Chevillat · Terms · Privacy · Impressum · Contact