# VelozCLI

Command-line tool for managing Veloz CMS deployments and plugins.

**Cross-platform:** Works on Windows, macOS, and Linux.

## Features

- 🔐 Google OAuth authentication with persistent sessions
- 📦 Create, deploy, and manage plugins from the terminal
- 🔄 Push/pull plugin code to/from CMS
- 🎨 Two plugin templates: Django App and Veloz SDK
- 🌐 Works with both local development and production environments

---

## Installation

### Prerequisites

- Python 3.8 or higher
- pip (Python package manager)

### Setup

1. **Clone the repository:**
   ```bash
   git clone https://github.com/Velozsite/velozcli.git
   cd veloz
   ```

2. **Create and activate virtual environment:**
   ```bash
   # Windows
   python -m venv venv
   .\venv\Scripts\Activate.ps1

   # macOS/Linux
   python3 -m venv venv
   source venv/bin/activate
   ```

3. **Install dependencies:**
   ```bash
   pip install -r requirements.txt
   ```

4. **Create `.env` file:**
   ```env
   SERVER_TO_CONNECT_TO=http://localhost:8000
   DEVELOPMENT=True
   ```

   **For production:**
   ```env
   SERVER_TO_CONNECT_TO=https://veloz.site
   DEVELOPMENT=False
   ```

---

## Usage

### Run Commands

```bash
# Direct execution
python main.py <command>

# Or install globally (recommended)
pip install -e .
veloz <command>
```

---

## Commands

### Authentication

#### `login`
Authenticate via Google OAuth. Token persists for 30 days across sessions.

```bash
python main.py login
```

**Flow:**
1. Opens browser for Google authentication
2. Generates and stores JWT token locally (`~/.veloz/credentials.json`)
3. Token synced to all your CMS instances

#### `logout`
Sign out and invalidate token locally and on server.

```bash
python main.py logout
```

#### `status`
Show authentication status, connected CMS, and session info.

```bash
python main.py status
```

**Output:**
- Email address
- Token expiration
- Connected CMS
- Server URL

---

### CMS Management

#### `list`
List all CMS deployments you own.

```bash
python main.py list
```

**Shows:**
- CMS name (Fly app name)
- URL
- Status (running/stopped)
- Created date

#### `connect <cms-name>`
Connect to a specific CMS. Connection persists across sessions.

```bash
python main.py connect my-cms
```

#### `logs`
Stream real-time logs from your connected CMS.

```bash
python main.py logs
```

**Options:**
- `--follow/--no-follow` or `-f` - Follow log output (default: true)

**Examples:**
```bash
# Stream all logs from connected CMS
python main.py logs

# Stop streaming with Ctrl+C
```

**Features:**
- **Real-time streaming** directly from your CMS (not via Heroku)
- **True zero overhead** when not connected (handler doesn't exist)
- **Auto-reconnects** on network issues or server restarts
- **Captures from moment you connect:**
  - Django framework logs
  - Plugin logs (if using `logging` module)
  - Errors and exceptions
  - Background tasks
- **No backlog** - streams from connection moment onward (true zero overhead)
- **Automatic cleanup** when disconnected (handler removed completely)

**Note:** 
- Only shows logs from the moment you connect (no history).
- **`print()` statements are NOT captured** - plugins must use Python's `logging` module.
- For print statements, historical logs, or infrastructure logs (runner/proxy), use `fly logs -a <app>`.

---

### Plugin Development

#### `init <plugin-name>`
Initialize a plugin. Pulls from CMS if exists, creates new if not.

```bash
python main.py init my_plugin
```

**Note:** Plugin names are automatically sanitized:
- Hyphens (`-`) → underscores (`_`)
- Spaces → underscores
- Invalid characters removed
- Example: `my-plugin` becomes `my_plugin`

**Templates:**

1. **Django App Template** - Traditional Django structure
   - `apps.py` with URL hooking
   - `models.py`, `views.py`, `urls.py`, `forms.py`
   - Working hello world view out of the box
   - Templates folder

2. **Veloz SDK Template** - Modern SDK with decorators
   - `@route`, `@menu`, `@function_tool`, `@agent`
   - AI agent integration ready
   - Cleaner, more declarative code

#### `push`
Upload plugin to connected CMS. Run from inside plugin folder.

```bash
cd my_plugin
python main.py push
```

**What it does:**
1. Zips plugin files
2. Uploads to CMS
3. Installs plugin
4. Runs migrations
5. Restarts server

#### `pull`
Download latest plugin code from CMS.

```bash
python main.py pull
```

#### `migrate`
Generate Django migrations locally without pushing.

```bash
cd my_plugin
python main.py migrate
```

---

## Configuration

### Environment Variables

Create a `.env` file in the project root:

```env
SERVER_TO_CONNECT_TO=http://localhost:8000
DEVELOPMENT=True
```

**Variables:**

- `SERVER_TO_CONNECT_TO` - Central server URL
  - Local: `http://localhost:8000`
  - Production: `https://veloz.site`

- `DEVELOPMENT` - Development mode flag
  - `True` - Local development (both central and CMS local)
  - `False` - Production mode

### User Configuration

CLI stores user data in `~/.veloz/`:

```
~/.veloz/
├── credentials.json    # Auth token, email, expiration
└── config.json         # Connected CMS, preferences
```

**These files persist across:**
- Terminal sessions
- PC restarts
- CLI updates

---

## Development Workflow

### Typical Plugin Development Flow

```bash
# 1. Login
python main.py login

# 2. Check status
python main.py status

# 3. List your CMS instances
python main.py list

# 4. Connect to one
python main.py connect my-cms

# 5. Create plugin
python main.py init hello_world

# 6. Edit plugin files
cd hello_world
# ... make changes ...

# 7. Push to CMS
python main.py push

# 8. Test in browser
# Visit: http://localhost:8000/hello_world/
```

---

## Architecture

### Token Management

- **JWT-based authentication** with 30-day expiration
- **Single token** works across central server + all tenants
- **Token synced** to central DB and all tenant databases
- **Revocation support** via logout

### API Endpoints

The CLI communicates with these backend endpoints:

```
POST   /api/cli/auth/device-code/    # Start OAuth flow
GET    /api/cli/auth/poll/           # Check auth status
DELETE /api/cli/auth/revoke/         # Logout
GET    /api/cli/tenants/             # List CMS
GET    /api/cli/plugins/<name>/info/ # Plugin info
POST   /api/cli/plugins/<name>/upload/ # Upload plugin
GET    /api/cli/plugins/<name>/files/ # Download plugin
```

---

## Troubleshooting

### Windows UTF-8 Encoding

The CLI automatically sets UTF-8 encoding on Windows to support emojis in output.

### Plugin Name Issues

Plugin names must be valid Python module names:
- ✅ `my_plugin`, `hello_world`, `test123`
- ❌ `my-plugin`, `my.plugin`, `123test`

The CLI auto-converts invalid names with a warning.

### Database Errors

If push fails with "plugin already exists":
1. Delete old plugin from Django admin
2. Or use Django shell: `AgenticApp.objects.filter(name="plugin_name").delete()`

---

## Technology Stack

- **Typer** - Modern CLI framework
- **Rich** - Beautiful terminal output
- **Requests** - HTTP client
- **PyJWT** - JWT token handling
- **Django** - For migration generation
- **python-dotenv** - Environment variables

---

## Contributing

This CLI is part of the Veloz ecosystem. For issues or contributions, please follow the standard pull request workflow.

---

## License

Proprietary - Veloz Platform

---

## Support

For questions or issues:
- Check `VELOZ_SDK_GUIDE.md` for SDK documentation
- Review `IMPLEMENTATION_PLAN.md` for architecture details