# Commands ## Обзор команд | Команда | Описание | |---------|----------| | `aevs config` | Настройка глобального конфига (credentials) | | `aevs init` | Инициализация проекта в текущей директории | | `aevs push` | Загрузить .env файлы в storage | | `aevs pull` | Скачать .env файлы из storage | | `aevs list` | Показать список проектов в storage | | `aevs status` | Показать статус текущего проекта | --- ## `aevs config` Интерактивная настройка глобального конфига. ### Синтаксис ```bash aevs config ``` ### Поведение 1. Запрашивает параметры storage интерактивно 2. Проверяет подключение к storage (list bucket) 3. Сохраняет в `~/.config/aevs/config.yaml` 4. Устанавливает права `0600` на файл ### Пример сессии ``` $ aevs config AEVS Configuration ================== Storage type (s3): s3 S3 Endpoint (https://s3.amazonaws.com): AWS Region (us-east-1): eu-central-1 Bucket name: my-envs-bucket Access Key ID: AKIA... Secret Access Key: **** Testing connection... ✓ Successfully connected to s3://my-envs-bucket Config saved to ~/.config/aevs/config.yaml ``` ### Ошибки | Ситуация | Сообщение | |----------|-----------| | Невалидные credentials | `Error: Access Denied. Check your credentials.` | | Bucket не существует | `Error: Bucket "xxx" not found.` | | Сетевая ошибка | `Error: Could not connect to endpoint.` | --- ## `aevs init` Инициализация проекта в текущей директории. ### Синтаксис ```bash aevs init [project-name] ``` ### Аргументы | Аргумент | Обязательный | Описание | |----------|--------------|----------| | `project-name` | нет | Имя проекта. По умолчанию: имя текущей директории | ### Флаги | Флаг | Сокращение | Описание | |------|------------|----------| | `--force` | `-f` | Перезаписать существующий `aevs.yaml` | ### Поведение (новый проект) 1. Проверяет, что `aevs.yaml` не существует 2. Сканирует директорию на `.env*` файлы (см. [File Scanning](#file-scanning)) 3. Если `project-name` не указан — запрашивает интерактивно (default: имя папки) 4. Создаёт `aevs.yaml` с найденными файлами 5. Выводит результат ### Поведение (проект существует) 1. Если `aevs.yaml` существует и нет `--force`: - Сканирует на новые `.env*` файлы - Предлагает добавить новые файлы в конфиг 2. Если `--force`: - Перезаписывает конфиг полностью ### Пример сессии ``` $ aevs init my-project Scanning for env files... Found 3 env files: ✓ .env.prod ✓ .env.dev ✓ docker/.env Created aevs.yaml for project "my-project" Next steps: 1. Review aevs.yaml 2. Run 'aevs push' to upload files ``` ### Пример (добавление новых файлов) ``` $ aevs init Project "my-project" already initialized. Scanning for new env files... Found 1 new file: + services/.env.api Add to aevs.yaml? [Y/n]: y Updated aevs.yaml ``` ### File Scanning **Паттерны для включения:** - `.env` — точное совпадение - `.env.*` — например `.env.prod`, `.env.local`, `.env.development` - `*.env` — например `docker.env`, `app.env` **Игнорируемые директории:** - `node_modules/` - `.git/` - `vendor/` - `venv/`, `.venv/` - `__pycache__/` - `.idea/`, `.vscode/` **Игнорируемые файлы:** - `.env.example` - `.env.sample` - `.env.template` ### Ошибки | Ситуация | Сообщение | |----------|-----------| | Config существует | `Error: aevs.yaml already exists. Use --force to overwrite.` | | Невалидное имя проекта | `Error: Invalid project name. Use only a-z, 0-9, -, _` | | Нет env файлов | `Warning: No env files found. Add files manually to aevs.yaml` | --- ## `aevs push` Загружает локальные `.env` файлы в storage. ### Синтаксис ```bash aevs push ``` ### Флаги | Флаг | Сокращение | Описание | |------|------------|----------| | `--config` | `-c` | Путь к конфигу (default: `./aevs.yaml`) | | `--dry-run` | | Показать что будет загружено, без реальной загрузки | ### Поведение 1. Читает `aevs.yaml` 2. Проверяет существование всех файлов из `files` 3. Создаёт tar.gz архив в памяти 4. Загружает архив в `{bucket}/{project}/envs.tar.gz` 5. Загружает metadata в `{bucket}/{project}/metadata.json` 6. Выводит результат ### Структура архива ``` envs.tar.gz ├── .env.prod ├── .env.dev └── docker/ └── .env ``` Пути в архиве сохраняются относительно корня проекта. ### Пример вывода ``` $ aevs push Pushing "my-project" to storage... ✓ .env.prod (234 bytes) ✓ .env.dev (189 bytes) ✓ docker/.env (56 bytes) Uploaded to s3://my-envs-bucket/my-project/envs.tar.gz Total: 3 files, 479 bytes ``` ### Пример (dry-run) ``` $ aevs push --dry-run Dry run - no changes will be made Would upload: .env.prod (234 bytes) .env.dev (189 bytes) docker/.env (56 bytes) Target: s3://my-envs-bucket/my-project/envs.tar.gz ``` ### Ошибки | Ситуация | Сообщение | |----------|-----------| | Нет aevs.yaml | `Error: No aevs.yaml found. Run 'aevs init' first.` | | Нет глобального конфига | `Error: No storage configured. Run 'aevs config' first.` | | Файл не найден | `Error: File not found: .env.prod` | | Ошибка S3 | `Error: Storage error: {details}` | --- ## `aevs pull` Скачивает `.env` файлы из storage. ### Синтаксис ```bash aevs pull [project-name] ``` ### Аргументы | Аргумент | Обязательный | Описание | |----------|--------------|----------| | `project-name` | нет | Имя проекта для скачивания | ### Флаги | Флаг | Сокращение | Описание | |------|------------|----------| | `--config` | `-c` | Путь к конфигу (default: `./aevs.yaml`) | | `--force` | `-f` | Перезаписать существующие файлы без подтверждения | | `--dry-run` | | Показать что будет скачано | ### Режимы работы **Режим 1: С локальным конфигом** ```bash aevs pull ``` - Читает `project` из `./aevs.yaml` - Скачивает и распаковывает файлы **Режим 2: По имени проекта** ```bash aevs pull my-project ``` - Скачивает архив для указанного проекта - Распаковывает в текущую директорию - Не создаёт и не изменяет `aevs.yaml` ### Поведение 1. Определяет имя проекта (из аргумента или конфига) 2. Скачивает metadata.json для проверки 3. Скачивает envs.tar.gz 4. Для каждого файла в архиве: - Если файл не существует — создаёт (и директории) - Если файл существует и отличается — спрашивает что делать - Если `--force` — перезаписывает без вопросов 5. Выводит результат ### Обработка конфликтов ``` $ aevs pull Pulling "my-project"... File .env.prod already exists and differs from remote. Local: DATABASE_URL=postgres://localhost Remote: DATABASE_URL=postgres://prod.db [o]verwrite / [s]kip / [d]iff / [O]verwrite all / [S]kip all: _ ``` | Опция | Действие | |-------|----------| | `o` | Перезаписать этот файл | | `s` | Пропустить этот файл | | `d` | Показать полный diff | | `O` | Перезаписать все конфликтующие файлы | | `S` | Пропустить все конфликтующие файлы | ### Пример вывода ``` $ aevs pull my-project Pulling "my-project" from storage... ✓ .env.prod (created) ✓ .env.dev (created) ✓ docker/.env (created directory, created file) Done. 3 files pulled. ``` ### Пример (с конфликтами) ``` $ aevs pull --force Pulling "my-project" from storage... ✓ .env.prod (overwritten) - .env.dev (unchanged) ✓ docker/.env (overwritten) Done. 2 files updated, 1 unchanged. ``` ### Ошибки | Ситуация | Сообщение | |----------|-----------| | Проект не указан и нет aevs.yaml | `Error: Project name required. Usage: aevs pull ` | | Проект не найден в storage | `Error: Project "xxx" not found in storage.` | | Нет глобального конфига | `Error: No storage configured. Run 'aevs config' first.` | --- ## `aevs list` Показывает список проектов в storage. ### Синтаксис ```bash aevs list ``` ### Флаги | Флаг | Сокращение | Описание | |------|------------|----------| | `--json` | | Вывод в формате JSON | ### Поведение 1. Читает глобальный конфиг 2. Запрашивает список "директорий" в bucket (S3 list с delimiter `/`) 3. Для каждого проекта читает metadata.json 4. Выводит отсортированный список ### Пример вывода ``` $ aevs list Projects in s3://my-envs-bucket: PROJECT FILES UPDATED SIZE my-awesome-project 3 2 hours ago 479 B another-project 5 3 days ago 1.2 KB old-project 2 45 days ago 234 B Total: 3 projects ``` ### Пример (JSON) ``` $ aevs list --json [ { "project": "my-awesome-project", "files": 3, "updated_at": "2026-01-28T13:30:00Z", "size_bytes": 479 }, ... ] ``` ### Ошибки | Ситуация | Сообщение | |----------|-----------| | Нет глобального конфига | `Error: No storage configured. Run 'aevs config' first.` | | Bucket пустой | `No projects found in storage.` | --- ## `aevs status` Показывает статус текущего проекта. ### Синтаксис ```bash aevs status ``` ### Флаги | Флаг | Сокращение | Описание | |------|------------|----------| | `--config` | `-c` | Путь к конфигу (default: `./aevs.yaml`) | ### Поведение 1. Читает локальный конфиг 2. Скачивает metadata.json из storage 3. Сравнивает локальные файлы с remote 4. Выводит статус ### Пример вывода ``` $ aevs status Project: my-awesome-project Storage: s3://my-envs-bucket/my-awesome-project Remote last updated: 2 hours ago (from MacBook-Pro.local) FILE LOCAL REMOTE STATUS .env.prod 234 B 234 B ✓ up to date .env.dev 195 B 189 B ⚡ local modified docker/.env — 56 B ✗ missing locally .env.staging 128 B — + local only Summary: 1 up to date, 1 modified, 1 missing, 1 new ``` ### Статусы файлов | Статус | Описание | |--------|----------| | `✓ up to date` | Файлы идентичны | | `⚡ local modified` | Локальный файл изменён | | `⚡ remote modified` | Remote файл изменён (другая машина сделала push) | | `✗ missing locally` | Файл есть в remote, но нет локально | | `+ local only` | Файл есть локально, но нет в remote | ### Ошибки | Ситуация | Сообщение | |----------|-----------| | Нет aevs.yaml | `Error: No aevs.yaml found. Run 'aevs init' first.` | | Проект не найден в storage | `Project "xxx" not found in storage. Run 'aevs push' first.` |