# Gantt Board CLI (API Passthrough)

Shell CLI for Gantt Board task/project/sprint/auth workflows.

The CLI is intentionally thin:

- API is the only source of business logic.
- CLI parses args, resolves names to IDs, calls API endpoints, and formats output.
- CLI must never call the database directly.

## Scripts

- `gantt.sh`: full API wrapper (task, project, sprint, auth, debug)
- `task.sh`: task-focused CRUD helpers
- `project.sh`: project-focused CRUD helpers
- `sprint.sh`: sprint-focused CRUD helpers
- `lib/api_client.sh`: shared HTTP client (`api_call`, cookie handling, URL encoding)

## Requirements

- `bash`
- `curl`
- `jq`
- `uuidgen` (used by `task.sh create`)

Install `jq` on macOS:

```bash
brew install jq
```

## Configuration

Environment variables:

- `API_URL` (default: `http://localhost:3000/api`)
- `GANTT_COOKIE_FILE` (default: `~/.config/gantt-board/cookies.txt`)
- `DEFAULT_PROJECT_ID` (optional task default)
- `DEFAULT_ASSIGNEE_ID` (optional task default)

Authenticate once:

```bash
./gantt.sh auth login <email> <password>
```

## Command Reference

## `task.sh`

```bash
./task.sh list [status] [--status <v|v1,v2,...>] [--priority <v>] [--project <name-or-id>] [--assignee <name-or-id>] [--type <v>] [--limit <n>] [--json]
./task.sh get <task-id>
./task.sh current-sprint
./task.sh create --title "<title>" [--description "..."] [--type <task|bug|research|plan|idea>] [--status <status>] [--priority <priority>] [--project <name-or-id>] [--sprint <name-or-id|current>] [--assignee <name-or-id>] [--due-date YYYY-MM-DD] [--tags "a,b"] [--comments "..."]
./task.sh create --file <task.json>
./task.sh update <task-id> [--status <v>] [--priority <v>] [--title "..."] [--description "..."] [--type <v>] [--project <name-or-id>] [--assignee <name-or-id>] [--sprint <name-or-id|current>] [--due-date YYYY-MM-DD] [--add-comment "..."] [--clear-tags] [--tags "a,b"]
./task.sh update <task-id> <field> <value>   # legacy form
./task.sh delete <task-id>
./task.sh bulk-create <tasks.json>
```

Notes:

- `--interactive` is not supported in passthrough mode.
- `--auto-create` is not supported in passthrough mode.
- `task.sh list` requests `GET /api/tasks?scope=active-sprint` and only returns tasks in the current sprint.
- If there is no current sprint, `task.sh list --json` returns `[]`.

Bulk JSON format:

```json
[
  {
    "title": "Task 1",
    "description": "Description",
    "type": "task",
    "status": "todo",
    "priority": "high",
    "project": "Project Name",
    "sprint": "Sprint 1",
    "assignee": "Max",
    "due_date": "2026-03-01",
    "tags": "tag1,tag2",
    "comments": "Initial comment"
  }
]
```

## `project.sh`

```bash
./project.sh list [--json]
./project.sh get <project-id-or-name>
./project.sh create --name "<name>" [--description "..."] [--color "#hex"]
./project.sh update <project-id-or-name> [--name "..."] [--description "..."] [--color "#hex"]
./project.sh delete <project-id-or-name>
```

## `sprint.sh`

```bash
./sprint.sh list [--status <planning|active|completed>] [--active] [--json]
./sprint.sh get <sprint-id-or-name>
./sprint.sh create --name "<name>" [--goal "..."] [--start-date YYYY-MM-DD] [--end-date YYYY-MM-DD]
./sprint.sh update <sprint-id-or-name> [--name "..."] [--goal "..."] [--start-date YYYY-MM-DD] [--end-date YYYY-MM-DD]
./sprint.sh close <sprint-id-or-name>
./sprint.sh delete <sprint-id-or-name>
```

Sprints are global and no longer accept `project` filters/fields.

## `gantt.sh`

High-level wrapper for full API surface:

- `task`: list/get/create/natural/update/delete/comment/attach
- `project`: list/get/create/update/delete
- `sprint`: list/get/create/update/close/delete
- `auth`: login/logout/session/register/forgot-password/reset-password/account/users
- `debug`

Examples:

```bash
./gantt.sh task list open
./gantt.sh task natural "Fix login bug by Friday, high priority"
./gantt.sh project create "Mobile App" "iOS and Android app" "#3b82f6"
./gantt.sh sprint close <sprint-id>
./gantt.sh auth session
```

## Name Resolution

The task/project/sprint scripts support name-to-ID resolution against API data:

- project names -> `projectId`
- sprint names -> `sprintId`
- assignee names/emails -> `assigneeId`
- sprint value `current` -> `/api/sprints/current`

Sprint status is derived from `start_date`/`end_date`; no manual sprint status writes are required.
`./sprint.sh list --active` uses `/api/sprints?inProgress=true` and returns all sprints whose date window includes the API server's current date at execution time.

## Testing

Run refactor safety suite:

```bash
npm run test:refactor
```

This runs:

1. TypeScript unit tests for sprint-selection logic.
2. Shell contract tests that mock API transport and validate CLI passthrough behavior.

The shell contract test also fails if direct Supabase/DB references appear in `scripts/`.

## AI/Agent Guidance

If you are extending CLI behavior:

1. Add/modify API behavior first (`src/app/api/*` and server modules).
2. Keep CLI as passthrough only.
3. Add or update tests (unit + mocked CLI contract tests).
4. Do not introduce direct database calls in `scripts/`.

## Exit Codes

- `0`: success
- `1`: error (invalid input, missing entity, API failure)
