Metadata-Version: 2.4
Name: opencart-cli
Version: 1.0.0
Summary: The OpenCart CLI you wish came in the box — query, edit, and operate your OpenCart store from the terminal. AI-powered queries, live order watching, interactive shell.
Project-URL: Homepage, https://github.com/chrisbray85/opencart-cli
Project-URL: Repository, https://github.com/chrisbray85/opencart-cli
Project-URL: Issues, https://github.com/chrisbray85/opencart-cli/issues
Project-URL: Changelog, https://github.com/chrisbray85/opencart-cli/releases
Project-URL: MCP version, https://github.com/chrisbray85/opencart-mcp
Author: Chris Bray
License-Expression: MIT
License-File: LICENSE
Keywords: ai,cli,developer-tools,devops,ecommerce,opencart,shell,shopify-alternative,terminal
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
Classifier: Topic :: Office/Business :: Financial :: Point-Of-Sale
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Terminals
Requires-Python: >=3.10
Requires-Dist: keyring>=24.0
Requires-Dist: paramiko>=3.4.0
Requires-Dist: platformdirs>=4.0
Requires-Dist: prompt-toolkit>=3.0.43
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.7.0
Requires-Dist: typer>=0.12.0
Provides-Extra: ai
Requires-Dist: anthropic>=0.40.0; extra == 'ai'
Requires-Dist: openai>=1.50.0; extra == 'ai'
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6.0; extra == 'dev'
Requires-Dist: types-paramiko; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Description-Content-Type: text/markdown

# opencart-cli

> **The OpenCart CLI you wish came in the box.**
> Query, edit, and operate your store from the terminal. AI-powered queries, interactive shell, live order watching, dry-run safety on every mutation.

[![PyPI](https://img.shields.io/pypi/v/opencart-cli.svg)](https://pypi.org/project/opencart-cli/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![OpenCart 2.x · 3.x · 4.x](https://img.shields.io/badge/OpenCart-2.x_·_3.x_·_4.x-success)](https://www.opencart.com/)

```bash
$ pip install opencart-cli
$ opencart init
$ opencart ask "which products are low on stock?"
```

That's it. You're operating an OpenCart store from the terminal.

---

## What you get

![opencart-cli demo](demo.svg)

— sparklines, pretty tables, money formatting, all out of the box. Pipe it through `jq` and it switches to JSON automatically.

> **Want to see it yourself in your own terminal?** Run `opencart demo sales` (or `products`, `orders`, `doctor`, `all`) — works without setting up a profile, uses canned data through the real rendering pipeline.

---

## ✨ Features

- 🤖 **`opencart ask "..."`** — ask in plain English, get SQL generated with full schema context, see the SQL, confirm, run it. Powered by Claude or OpenAI.
- 🐚 **`opencart shell`** — interactive REPL with persistent connection. ~30× faster for multi-command workflows.
- 📡 **`opencart watch orders`** — live tail of new orders with terminal-bell notifications.
- 🏥 **`opencart doctor`** — diagnoses SSH/DDEV/MySQL/PHP/OpenCart in one command. Tells you exactly what's wrong.
- 🛡️ **Safety-first defaults** — dry-run on every mutation, `--read-only` mode, auto-readonly on profiles named `prod*`, audit log of every change.
- 🔌 **3 connection backends** — remote SSH, local DDEV, local PHP/Docker. Same commands, same UX.
- 🌎 **Multi-profile** — manage many stores from one CLI. `opencart --profile staging products list`.
- 🔐 **Secrets in OS keychain** — DB passwords stored in macOS Keychain / Linux Secret Service / Windows Credential Manager. Never in plaintext config.
- 📊 **Beautiful output** — Unicode sparklines, ANSI tables, money formatting. Auto-falls-back to JSON when piped.
- 🐚 **Shell completions** — bash, zsh, fish, PowerShell. Generated by typer.
- 📦 **Works with OpenCart 2.x, 3.x, 4.x** — schema differences auto-detected.

---

## 🚀 Quick start

### Install

**Recommended — using `pipx`** (puts `opencart` on your PATH globally in an isolated environment):

```bash
brew install pipx && pipx ensurepath
pipx install opencart-cli                    # core CLI
pipx install 'opencart-cli[ai]'              # plus `opencart ask` (Claude/OpenAI)
```

**Or plain `pip`** (works but you'll need to manage your own venv or `pip install --user`):

```bash
pip install opencart-cli
```

> If `opencart` is "command not found" after a plain `pip install`, the script likely landed somewhere not on your PATH. `pipx` solves this universally.

### Configure (interactive)

```bash
opencart init
```

The wizard asks for connection type (SSH / DDEV / local), credentials, OpenCart paths, and tests the connection before saving. Config lands at `~/.config/opencart-cli/config.yaml`, DB password in the OS keychain.

### Use

```bash
opencart products list --low-stock-under 5
opencart orders list --days 7 --min-total 100
opencart sales summary --days 30
opencart customers list --search "jane@"
opencart ask "what's our best-selling category this month?"
```

---

## 🧠 `opencart ask` — the headline feature

You don't always remember the exact column names. AI does.

```bash
$ opencart ask "show me products under £10 with less than 5 in stock"

Reading schema...
Asking Claude (Anthropic)...

Explanation: Find active products priced below £10 with low stock.
Generated SQL:
  SELECT p.product_id, p.model, pd.name, p.price, p.quantity
  FROM oc_product p
  LEFT JOIN oc_product_description pd ON pd.product_id = p.product_id
  WHERE p.price < 10 AND p.quantity < 5 AND p.status = 1
  LIMIT 50

Run this query? [Y/n]: y

┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┓
┃ product_id ┃ model         ┃ name               ┃  price ┃ quantity ┃
┣━━━━━━━━━━━━╋━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━╋━━━━━━━━━━┫
┃ 42         ┃ MOUSE-WL-01   ┃ Wireless Mouse Pro ┃  £9.99 ┃        3 ┃
┃ 87         ┃ CABLE-USBC-1M ┃ USB-C Cable 1m     ┃  £8.50 ┃        2 ┃
┗━━━━━━━━━━━━┻━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━┻━━━━━━━━━━┛
```

Set `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` in your environment. The CLI picks whichever it finds. AI only ever generates SELECT statements — mutations are blocked.

---

## 🔌 Connection backends

### SSH (remote VPS / shared hosting)

```yaml
profiles:
  prod:
    connection:
      type: ssh
      host: 12.34.56.78
      user: youruser
      key: ~/.ssh/id_ed25519
    db: {user: yourdb, name: yourshop}
    opencart: {root: /home/youruser/public_html, version: 3.x}
```

### DDEV (local development)

```yaml
profiles:
  local:
    connection:
      type: ddev
      project_path: ~/Sites/my-opencart
    db: {user: db, name: db}
    opencart: {root: /var/www/html}
```

### Local (Docker Compose, MAMP, native PHP)

```yaml
profiles:
  docker:
    connection:
      type: local
      php_bin: "docker compose exec web php"
      cwd: ~/Sites/my-shop
    db: {user: oc, name: opencart, host: 127.0.0.1, port: 3306}
    opencart: {root: /var/www/html}
```

Run `opencart doctor` to verify any profile end-to-end.

---

## 🛡️ Safety model

Every mutation command runs through the same safety pipeline:

1. **Read-only mode wins.** Profiles named `prod*` are auto-read-only. Explicit `read_only: true` makes any profile read-only. `--read-only` flag forces it per-invocation.
2. **Dry-run by default for big changes.** `--dry-run` previews the plan, applies nothing.
3. **Confirmation prompts.** Every mutation prompts unless `--yes` is passed.
4. **Audit log.** Every change is logged to `~/.config/opencart-cli/audit.jsonl` with before/after diff, timestamp, user, host. View with `opencart audit show`.
5. **Parameterised SQL.** Nothing user-supplied is concatenated into SQL — uses `mysqli_prepare` end-to-end.
6. **Raw `opencart sql` blocks mutations and DDL.** Only `SELECT/SHOW/DESCRIBE/EXPLAIN` allowed there.

```bash
$ opencart -y products update 183 --price 99.99
Plan: Update product 183
  price: 65.99 → 99.99
✗ Profile 'prod' is read-only — refusing to execute mutation.
```

---

## 🤝 opencart-cli vs [opencart-mcp](https://github.com/chrisbray85/opencart-mcp)

Same engine, two cockpits. Pick the one that matches how you work — or use both.

|                       | [`opencart-mcp`](https://github.com/chrisbray85/opencart-mcp) | `opencart-cli` (this repo) |
|-----------------------|--------------------------|-------------------------|
| Who uses it           | Claude (or another AI)   | You, with the keyboard  |
| Invoked via           | Natural language in Claude Code / Cursor | Terminal commands       |
| Output                | JSON for the AI to read  | Tables / JSON / YAML / CSV |
| AI involvement        | Required                 | Optional (`opencart ask` only) |
| Connection cost       | New SSH per call         | Persistent SSH — ~30× faster |
| Best for              | Conversational ops while chatting | Scripts, cron, REPL, headless servers |

The CLI is everything the MCP is, plus a terminal-first interface, persistent connections, AI inside the terminal (no Claude Code needed), shell completions, pipes for `jq`, watch mode, and an interactive REPL.

---

## 📦 Configuration

Config file (paths + connection details only — never secrets):
- macOS: `~/Library/Application Support/opencart-cli/config.yaml`
- Linux: `~/.config/opencart-cli/config.yaml`
- Windows: `%APPDATA%\opencart-cli\config.yaml`

Override with `OPENCART_CLI_CONFIG=/some/path.yaml`.

Secrets (DB passwords): OS keychain by default. Override via env var `OPENCART_<PROFILE>_DB_PASS` (e.g. `OPENCART_PROD_DB_PASS`). CI-friendly — no keychain needed.

SSH keys: referenced by path, never embedded.

---

## 🎛 Output formats

```bash
opencart products list                    # auto: table if TTY, JSON if piped
opencart -f json products list            # explicit JSON
opencart -f yaml settings list            # explicit YAML
opencart -f csv orders list --days 7      # explicit CSV
opencart products list | jq '.[] | select(.price | tonumber > 50)'
```

---

## 🩺 `opencart doctor`

When things don't work, run this first.

```
$ opencart doctor

Diagnosing profile: prod
  Connection: ssh

✓ Connection: built SSHConnection
✓ Shell exec: responsive
✓ PHP: 7.4.33
✓ MySQL: 8.0.45
✓ OpenCart tables: found (oc_product exists)
✓ OpenCart version: 3.x

✓ All checks passed.
```

If anything fails, the message tells you what to fix.

---

## 🛠 Command reference

```
opencart init                    Interactive setup wizard
opencart demo <sales|products|orders|doctor|all>   Try the CLI without a profile
opencart doctor                  Diagnostic checks
opencart ask "..."               AI natural-language query
opencart shell                   Interactive REPL
opencart watch orders            Live tail new orders
opencart sql "SELECT ..."        Raw SQL (SELECT/SHOW/DESCRIBE only)
opencart version                 Print version

opencart products list           List products (filters: --search, --status, --low-stock-under)
opencart products get <id>       Full product detail
opencart products update <id>    Update product fields (dry-run default)

opencart orders list             Recent orders (filters: --days, --status, --min-total)
opencart orders get <id>         Order header + line items + history

opencart customers list          List/search customers

opencart settings list           List OpenCart settings (filters: --group, --key)
opencart settings set <group> <key> <value>   Update a setting

opencart stock low               Low stock report (filter: --threshold)

opencart sales summary           Sales totals + sparkline + top sellers
opencart sales daily             Daily breakdown

opencart profile list            List profiles
opencart profile use <name>      Set default profile
opencart profile show [name]     Show full profile config
opencart profile remove <name>   Remove a profile

opencart --install-completion    Shell completion (bash/zsh/fish/PowerShell)
```

Global flags (place before the subcommand):
```
-p, --profile <name>      Use a specific profile
-f, --format <fmt>        Output format: auto/table/json/yaml/csv
-y, --yes                 Skip confirmation prompts
--dry-run                 Show what would change, do nothing
--read-only               Force read-only mode this invocation
-V, --version             Print version
```

---

## 🤝 Contributing

PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Issues for bug reports and feature requests. The codebase is small, well-typed, and ruff-clean.

## 📜 License

MIT — do whatever you like.

---

## ⭐ If this saved you 10 minutes of admin-panel clicking, please star the repo.
