Metadata-Version: 2.4
Name: forgexa-cli
Version: 1.52.3
Summary: Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform
Author-email: Jason Sun <dev.winds@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://forgexa.net
Project-URL: Documentation, https://docs.forgexa.net
Project-URL: Repository, https://github.com/forgexa/forgexa
Project-URL: Issues, https://github.com/forgexa/forgexa/issues
Keywords: forgexa,ai,software-factory,cli,devops,agent
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24
Requires-Dist: socksio>=1.0.0
Provides-Extra: daemon
Requires-Dist: httpx>=0.24; extra == "daemon"
Requires-Dist: socksio>=1.0.0; extra == "daemon"

# Forgexa CLI

Command-line client and agent runtime for the [Forgexa](https://forgexa.net) platform.

Communicates with the Forgexa server via REST API.
Includes a built-in **daemon** that discovers ten local AI agent integrations (Claude Code, Codex, GitHub Copilot, Gemini CLI, OpenCode, Kimi Code, MiMo Code, Qwen Code, CodeBuddy, and Qoder CLI) and executes tasks on behalf of the server. MiMo Code (`mimo`, v0.1.14+), Qwen Code (`qwen`, v0.24.1+), CodeBuddy (`codebuddy`, v2.156.0+), and Qoder CLI (`qoder`, v1.1.59+) are selected explicitly; automatic routing and generated default fallback chains exclude all four. CodeBuddy and Qoder completed their local AgentHost start/resume acceptance gates. Authentication, endpoint, and model selection remain in each local CLI profile; Forgexa never stores or overrides them.

## Installation

```bash
# From PyPI (recommended)
pip install forgexa-cli

# Or with pipx (isolated environment)
pipx install forgexa-cli

# Upgrade later
forgexa upgrade
forgexa upgrade --target-version 1.12.3

# Verify installation
forgexa version
```

### Development Installation

```bash
# Install from source (editable mode)
git clone https://github.com/forgexa/forgexa.git
cd ai-software-factory/cli
pip install -e .
```

## Quick Start

```bash
# Configure server (default: http://localhost:8000)
export FORGEXA_SERVER_URL=https://your-server.example.com

# Login (saves session to ~/.forgexa/credentials.json)
forgexa login

# List workspaces
forgexa workspace list

# List projects
forgexa project list --workspace <workspace-id>

# Show kanban board
forgexa board --project <project-id>
```

## Commands

| Command | Description |
|---------|-------------|
| `forgexa login` | Login and save access token |
| `forgexa logout` | Remove saved token |
| `forgexa workspace list` | List workspaces |
| `forgexa workspace create <name>` | Create a workspace |
| `forgexa project list --workspace <id>` | List projects |
| `forgexa project create <name> --workspace <id>` | Create a project |
| `forgexa requirement list --project <id>` | List requirements |
| `forgexa requirement create <title> --project <id>` | Create a requirement |
| `forgexa requirement analyze --id <id>` | Analyze a requirement |
| `forgexa board --project <id>` | Show kanban board |
| `forgexa run list --project <id>` | List executions |
| `forgexa run start <execution-id>` | Start an execution |
| `forgexa gates pending` | List pending gates |
| `forgexa gates approve --gate <id>` | Approve a gate |
| `forgexa gates reject --gate <id>` | Reject a gate |
| `forgexa workflow show --project <id>` | Show workflow policy |
| `forgexa workflow reload --project <id>` | Reload workflow |
| `forgexa budget --workspace <id>` | Budget overview |
| `forgexa daemon start` | Start local daemon (discover agents, run tasks) |
| `forgexa daemon start -d` | Start daemon in background |
| `forgexa daemon status` | Show your daemon statuses (credential type, prefix, expiry) |
| `forgexa daemon stop` | Stop local daemon |
| `forgexa daemon enroll` | Issue a dedicated runtime credential for this machine (recommended for long-running daemons) |
| `forgexa daemon rotate-token` | Rotate this runtime's credential (old one is revoked immediately) |
| `forgexa daemon revoke-credential` | Revoke this runtime's credential (keeps your login session) |
| `forgexa check` | Verify locally-installed agent CLIs are genuinely usable (runs a real task per agent) |
| `forgexa check --quick` | Same, but discovery only — no live task, no API calls |
| `forgexa check --agent <name>` | Check a single agent (e.g. `claude`, `codex`, `kimi`) |
| `forgexa runtimes list` | List your runtimes |
| `forgexa version` | Show CLI version |
| `forgexa version --status` | Show auto-upgrade status (mode, active/last success/last failure) |
| `forgexa upgrade` | Upgrade to the latest CLI release |
| `forgexa upgrade --target-version <version>` | Upgrade or roll forward to a specific release |

## Self Upgrade

```bash
# Upgrade to the latest published release
forgexa upgrade

# Upgrade to a specific published release
forgexa upgrade --target-version 1.12.3
```

The command detects how `forgexa-cli` was installed:

- `pipx` install: uses `pipx upgrade --index-url https://pypi.org/simple forgexa-cli`, or `pipx install --force --index-url https://pypi.org/simple forgexa-cli==<version>` for a pinned version
- `pip` install: uses `python -m pip install --upgrade --index-url https://pypi.org/simple forgexa-cli`
- non-editable local path install (`pip install /path/to/cli`): follows the same `pip` upgrade path and switches to the published PyPI release

Self-upgrades pass `--index-url https://pypi.org/simple` to pip or pipx, matching the official PyPI release check and avoiding a configured mirror that has not yet synchronized a new release. A direct `pip install --upgrade forgexa-cli` command always follows that Python environment's pip configuration. When its mirror is behind, upgrade manually with:

```bash
python -m pip install --upgrade --index-url https://pypi.org/simple forgexa-cli==1.12.3
```

For safety, `forgexa upgrade` stops any running local daemon before upgrading. If the daemon was previously started in background mode, the CLI starts it again automatically after a successful upgrade; otherwise it prints a manual restart hint.

`forgexa upgrade` supports standard PyPI / pipx installs and non-editable local path installs. Editable installs, VCS installs, and other direct URL installs are rejected with a manual upgrade hint.

### One-Shot Upgrade Script (recommended for production runtimes)

`forgexa upgrade` alone only auto-restarts the daemon if it was already running in background mode *right before* the upgrade started — if it had already stopped for any other reason (crash, manual stop, first-time setup), you're left to restart it yourself. [`cli/scripts/upgrade.sh`](scripts/upgrade.sh) (macOS/Linux) and [`cli/scripts/upgrade.ps1`](scripts/upgrade.ps1) (Windows) wrap the full, correct sequence explicitly so the daemon is deterministically stopped, upgraded, and started again in the background every time, regardless of its state going in:

```bash
# macOS / Linux
./cli/scripts/upgrade.sh
./cli/scripts/upgrade.sh --target-version 1.21.7
./cli/scripts/upgrade.sh --server-url https://api.forgexa.net --login
```

```powershell
# Windows
.\cli\scripts\upgrade.ps1
.\cli\scripts\upgrade.ps1 -TargetVersion 1.21.7
.\cli\scripts\upgrade.ps1 -ServerUrl https://api.forgexa.net -Login
```

Steps: `daemon stop` (no-op if not running) → `upgrade` → `daemon start -d` → optional `login` → `daemon status`. Login is skipped by default (the previously saved session is reused) unless you pass `--email`/`--password` (`-Email`/`-Password`), set `FORGEXA_LOGIN_EMAIL`/`FORGEXA_LOGIN_PASSWORD`, or pass `--login`/`-Login` to be prompted interactively. Run with `--help`/`Get-Help .\upgrade.ps1` for all options.

### Automatic Background Upgrade

By default (`auto_upgrade=silent`), forgexa checks for updates in the background (once every 24h) and silently installs new releases — no need to run `forgexa upgrade` yourself, the same way GitHub Copilot CLI / Claude Code / Kimi Code work (see [docs/designs/cli-auto-upgrade-design.md](../docs/designs/cli-auto-upgrade-design.md) for the full design). `forgexa upgrade` remains fully available at any time for an immediate manual upgrade or to pin a specific `--target-version` — the two are independent and coexist.

```bash
# Back to notify-only: check and print a footer notice, but never install automatically
forgexa config set auto-upgrade notify

# Disable update checks entirely
forgexa config set auto-upgrade off

# Re-enable silent background installs (the default)
forgexa config set auto-upgrade silent
```

| Mode | Check | Silent background install | Footer notice |
|------|-------|----------------------------|----------------|
| `silent` (default) | ✅ | ✅ | ✅ (one-time "updated to vX" notice next run) |
| `notify` | ✅ | ❌ | ✅ |
| `off` | ❌ | ❌ | ❌ |

A silent install only ever runs for a safe, already-detected install source (pip/pipx — the same sources `forgexa upgrade` supports), never while a local daemon is running (it's skipped and retried on a later invocation instead), never in CI or a non-interactive/`--format json` session, and gives up automatically after 2 consecutive failures for the same target version. Check `forgexa version --status` to see the current mode and the last install attempt's outcome, or `~/.forgexa/upgrade.log` for the raw install output.

`FORGEXA_AUTO_UPGRADE=<silent|notify|off>` overrides the config file for the current shell session; the legacy `FORGEXA_NO_UPDATE_CHECK=1` remains a supported alias for `off`.

## Configuration

| Variable | Default | Description |
|----------|---------|-------------|
| `FORGEXA_SERVER_URL` | `http://localhost:8000` | `Server base URL |
| `FORGEXA_TOKEN` | — | Bearer token (overrides `~/.forgexa/token`) |
| `FORGEXA_AUTO_UPGRADE` | — | Override `auto_upgrade` (`silent`\|`notify`\|`off`) for this session |
| `FORGEXA_NO_UPDATE_CHECK` | — | Legacy alias for `FORGEXA_AUTO_UPGRADE=off` |

## Output Format

```bash
forgexa workspace list                  # Table (default)
forgexa workspace list --format json    # JSON
forgexa workspace list --format quiet   # IDs only
```

## Daemon Management

The daemon discovers locally installed AI agents and registers them with the Forgexa server.
It then polls for tasks and executes them using your local agents.

### Start Daemon

```bash
# Foreground (default — see logs, Ctrl+C to stop)
forgexa daemon start

# Background (detached)
forgexa daemon start -d

# Connect to a specific server
forgexa daemon start --server-url https://your-server.example.com

# Or via the standalone entry point
forgexa-daemon
```

### Other Daemon Commands

```bash
# Check your daemon status (from server)
forgexa daemon status

# Platform admin: list all runtimes
forgexa daemon status --all

# Stop background daemon
forgexa daemon stop

# List your runtimes
forgexa runtimes list

# Platform admin: list all runtimes
forgexa runtimes list --all
```

### Runtime Credentials

A freshly logged-in daemon authenticates with your interactive login session. For a
long-running daemon (e.g. a machine that stays on 24/7), issue it a dedicated,
revocable credential instead so it never depends on your session expiring:

```bash
# Issue a runtime credential for this machine (default 90-day expiry, max 365)
forgexa daemon enroll

# Rotate it (the old credential is revoked immediately — no overlap window)
forgexa daemon rotate-token

# Revoke it (keeps your login session; run 'forgexa daemon enroll' again to reissue)
forgexa daemon revoke-credential
```

`forgexa daemon status` shows which credential type is active, its prefix, and its
expiry — the raw credential value is only ever printed once, at enroll/rotate time.

### Agent Health Check

Before starting the daemon (or when tasks keep failing on this machine), verify that every
installed agent CLI is genuinely usable — not just present on `PATH`. `forgexa check` reuses the
exact discovery and execution code the daemon uses in production, so a `PASS` means the agent
really works (auth, quota, and sandbox problems only ever surface on a real invocation).

```bash
# Check runtime prerequisites, discover installed agents, then run one real,
# minimal task through each to confirm it works
forgexa check

# Fast pass: discovery only, no live task, no API calls
forgexa check --quick

# Check a single agent
forgexa check --agent claude

# Check runtime prerequisites and only the selected agent without a live task
forgexa check --quick --agent claude
```

Example output:

```
Agent Availability Report
----------------------------------------------------------------------
  ✓  claude     v2.1.14 (Claude Code)
  ✗  codex      not installed
       'codex' not found on PATH, or found but 'codex --version' failed / did not
       report a version. Install (or reinstall) the agent CLI and make sure it is
       on PATH, then re-run 'forgexa check'.
  ✓  kimi       v0.27.0
----------------------------------------------------------------------
2/3 agent(s) available for real platform tasks.
```


### Supported AI Agents

The daemon automatically discovers these agents if installed on your system:

| Agent | Command |
|-------|---------|
| Claude Code | `claude` |
| OpenAI Codex | `codex` |
| Gemini CLI | `gemini` |
| OpenCode | `opencode` |
| Kimi Code | `kimi` |

### Environment Variables (Daemon)

| Variable | Default | Description |
|----------|---------|-------------|
| `DAEMON_SERVER_URL` | `http://localhost:8000` | Server to connect to |
| `DAEMON_API_TOKEN` | — | Explicit override token (not persisted, never auto-refreshed); omit this to let the daemon use your login session or an enrolled runtime credential |
| `DAEMON_MAX_CONCURRENT` | `5` | Max parallel tasks |
| `DAEMON_POLL_INTERVAL` | `3` | Poll interval (seconds) |

## Publishing to PyPI

### Prerequisites

```bash
pip install build twine
```

### Build & Publish

```bash
cd cli/

# Build only (creates dist/)
./scripts/publish.sh build

# Publish to TestPyPI (for testing)
./scripts/publish.sh test

# Publish to PyPI (production)
./scripts/publish.sh
```

### Version Bumping

```bash
# Bump version (updates pyproject.toml + __init__.py)
./scripts/bump-version.sh 1.1.0

# Then commit, tag, and publish
git add -A && git commit -m "release(cli): v1.1.0"
git tag cli-v1.1.0
./scripts/publish.sh
```

### PyPI Authentication

Configure via environment variables or `~/.pypirc`:

```bash
# Using API token (recommended)
export TWINE_USERNAME=__token__
export TWINE_PASSWORD=pypi-AgEIcH...

# Or create ~/.pypirc
cat > ~/.pypirc << 'EOF'
[pypi]
username = __token__
password = pypi-AgEIcH...

[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgEIcH...
EOF
chmod 600 ~/.pypirc
```

## Local Development & Debugging

### Editable Install

```bash
cd cli
pip install -e .
```

This installs the `forgexa` command pointing to your local source. Changes take effect immediately.

### Testing Against Local Server

```bash
# Point CLI to local backend
export FORGEXA_SERVER_URL=http://localhost:8000

# Login
forgexa login

# Test commands
forgexa workspace list
forgexa daemon start
```

### Testing Against Remote/LAN Server

```bash
export FORGEXA_SERVER_URL=http://192.168.0.100:8000
forgexa login
forgexa daemon start
```

### Debugging the Daemon

```bash
# Run in foreground to see all logs
forgexa daemon start

# Check which agents are discovered
forgexa runtimes list

# Verbose logging (if supported)
DAEMON_LOG_LEVEL=DEBUG forgexa daemon start
```

### Project Structure

```
cli/
├── forgexa_cli/
│   ├── __init__.py     # Version constant
│   ├── main.py         # CLI entry point (argparse)
│   ├── daemon.py       # Daemon implementation
│   └── py.typed        # PEP 561 marker
├── scripts/
│   ├── bump-version.sh # Version management
│   ├── publish.sh      # PyPI publishing
│   └── sync-daemon.sh  # Sync daemon code from backend
├── pyproject.toml      # Package metadata
└── README.md           # This file
```

### Design Principles

- **Zero external dependencies** — uses only Python stdlib (urllib, json, subprocess)
- **Lightweight** — installs in seconds, no compilation needed
- **Cross-platform** — works on Linux, macOS, Windows
- **Standalone daemon** — discovers local AI agents without server-side configuration
