> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getcliq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Building Agents

> Create custom agents with the cliq SDK — manifest, handlers, agents path, and Hub registration.

<div className="cliq-kicker">Guide</div>

A custom agent extends cliq's built-in catalog with your own logic. Agents are Node.js programs that receive an invoke payload from the daemon and return output. The SDK handles the protocol; you implement one method.

***

## How agents work

When a phase fires, cliqd:

1. Resolves the agent name from the **agents path** (filesystem lookup)
2. Spawns the agent's entry point as a child process
3. Pipes the **invoke payload** (JSON) to stdin
4. The agent posts events and a terminator (`complete` / `error`) back to cliqd over HTTP

The agent code **stays on your machine**. Hub only stores manifest metadata for catalog visibility.

***

## 1. Set up the SDK

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# Auth once (GitHub PAT with read:packages)
echo "//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}" >> ~/.npmrc
echo "@getcliqio:registry=https://npm.pkg.github.com" >> ~/.npmrc

mkdir -p ~/.cliqrc/agents/my-agent && cd ~/.cliqrc/agents/my-agent
npm init -y
npm install @getcliqio/cliq-sdk
```

Package: [`@getcliqio/cliq-sdk`](https://github.com/getcliqio/cliq-sdk/pkgs/npm/cliq-sdk).

***

## 2. Write the manifest

Every agent needs a `manifest.json` in its directory. The daemon validates every field on load — invalid manifests are skipped with a warning.

***

### Top-level fields

| Field | Type | Required | Validated | Description |
| - | - | :-: | - | - |
| `name` | string | **yes** | Non-empty | Agent identifier — must match the key in `agents.json` |
| `version` | string | **yes** | Non-empty | Semver version (e.g. `"1.2.0"`) |
| `description` | string | **yes** | Must be a string | Human-readable summary |
| `entry` | string | **yes** | Non-empty | Entry point relative to the manifest directory (e.g. `"./index.js"`, `"./agent.js"`) |
| `agent_type` | string | **yes** | Must be one of: `llm`, `exec`, `gate`, `connector`, `meta` | How the daemon dispatches the agent |
| `min_cliq_version` | string | no | Must be a string when present | Minimum cliq version required to run this agent |
| `inputs` | object | no | Each value validated as an [input field](#inputs) | Declared inputs from the phase YAML or run inputs |
| `settings` | object | no | Shape validated (see [Settings](#settings)) | Daemon settings the agent needs (`agents.<name>.*`) |
| `output` | object | no | Must be an object when present | Shape of the output data the agent emits |
| `binaries` | string\[] | no | Each entry must be a string | System binaries the agent shells out to (checked by `cliq doctor` via `command -v`) |
| `env` | string\[] | no | Each entry must be a string | Host environment variables inherited from the OS (not managed by cliq) |
| `mcp` | object | no | Shape validated (see [MCP](#mcp-llm-agents-only)) | MCP server configuration (LLM agents only) |
| `actions` | object | no | Not validated by SDK | Connector action reference — documents per-action fields for the OpenAPI docs |

Minimal example:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
    "name": "my-agent",
    "version": "0.1.0",
    "description": "Does something useful",
    "entry": "./index.js",
    "agent_type": "exec",
    "inputs": {}
}
```

### Agent types

| `agent_type` | Use for | Base class | Gets from daemon |
| - | - | - | - |
| `exec` | Shell commands, scripts, deterministic work | `StandardAgent` | upstream, commands |
| `llm` | Model-backed work (API calls or coding CLIs) | `LlmAgent` / `CliAgent` | upstream, commands, role → prompt, model, api\_key |
| `gate` | Verdicts (PASS / ROUTE / ESCALATE) | `GateAgent` | upstream, check\_results, verdict helpers |
| `connector` | External system integration (Jira, S3, etc.) | `ConnectorAgent` | action, sources, targets, credentials |
| `meta` | Orchestration helpers (nested teams) | `BaseAgent` | — |

***

### Inputs

The `inputs` block declares what the agent accepts. Each key is the input name; the value is a field descriptor.

**Validation rules:** Each input must be an object with `type` (valid type string) and `required` (boolean). `required_unless` must be an array when present. `enum` must be an array when present.

| Property | Type | Required | Description |
| - | - | :-: | - |
| `type` | string | **yes** | One of: `string`, `number`, `boolean`, `object`, `string[]`, `command[]`, `source_entry[]`, `target_entry[]` |
| `required` | boolean | **yes** | Whether the field must be present in the phase YAML |
| `source` | `"phase"` \| `"runtime"` | no | Where the input comes from. `"phase"` = team YAML at build time (default). `"runtime"` = user supplies at run time via `cliq run -i`. |
| `default` | any | no | Default value when not supplied |
| `required_unless` | string\[] | no | Field is required **unless** one of these other fields is present |
| `enum` | string\[] | no | Allowed values (for string fields) |
| `description` | string | no | Human-readable description |
| `fields` | object | no | Nested subfield definitions for `object`-typed inputs (see [Subfields](#subfields)) |

#### Type reference

| Type | Phase YAML shape | Example |
| - | - | - |
| `string` | Scalar string | `role: "You are a reviewer"` |
| `number` | Scalar number | `temperature: 0.7` |
| `boolean` | `true` / `false` | `needs_filesystem: true` |
| `object` | Arbitrary object | `review: { reviewers: [...], timeout: 60 }` |
| `string[]` | Array of strings | `tags: ["v2", "hotfix"]` |
| `command[]` | Array of `{ run: string }` | `commands: [{ run: "npm test" }]` |
| `source_entry[]` | Array of source entries | `sources: [{ ref: "PROJ-123", name: "ticket" }]` |
| `target_entry[]` | Array of target entries | `target_entries: [{ ref: "PROJ-123", name: "comment", file: "out.md" }]` |

#### `required_unless` — conditional requirements

Use when two fields are mutually exclusive (at least one must be present):

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"inputs": {
    "sources": {
        "type": "source_entry[]",
        "required": false,
        "required_unless": ["target_entries"],
        "description": "Resources to fetch"
    },
    "target_entries": {
        "type": "target_entry[]",
        "required": false,
        "required_unless": ["sources"],
        "description": "Resources to write"
    }
}
```

This is how the Jira agent declares that a phase must have either `sources` or `target_entries` (or both).

#### `source: "runtime"` — run-time inputs

Inputs with `source: "runtime"` are not set in the team YAML — they come from the user at run time via `cliq run -i`:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"task": {
    "type": "string",
    "required": false,
    "source": "runtime",
    "description": "Requirement or instruction"
}
```

#### Subfields

When an input has `type: "object"`, you can document its internal structure with `fields`. This is used for validation and documentation — the daemon passes the object through to the agent:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"review": {
    "type": "object",
    "required": true,
    "source": "phase",
    "description": "HUG review configuration",
    "fields": {
        "reviewers": {
            "type": "array",
            "required": true,
            "description": "Reviewer groups — who should review this gate"
        },
        "timeout": {
            "type": "number",
            "required": false,
            "description": "Review timeout in minutes"
        },
        "on_timeout": {
            "type": "string",
            "required": false,
            "description": "Behavior on timeout: escalate or wait"
        },
        "remind_every": {
            "type": "number",
            "required": false,
            "description": "Reminder interval in minutes"
        },
        "artifacts": {
            "type": "array",
            "required": false,
            "description": "File globs to attach for the reviewer"
        },
        "message": {
            "type": "string",
            "required": false,
            "description": "Custom message shown to the reviewer"
        }
    }
}
```

This is the real `hug` agent's `review` input — team authors see exactly what fields the object expects.

#### Full LLM agent inputs example

From the built-in `cursor` agent:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"inputs": {
    "role": {
        "type": "string",
        "required": true,
        "description": "Instructions for the agent — what role it plays in this phase"
    },
    "model": {
        "type": "string",
        "required": false,
        "default": "claude-sonnet-4-20250514",
        "description": "LLM model to use"
    },
    "temperature": {
        "type": "number",
        "required": false,
        "description": "Sampling temperature (0.0–2.0)"
    },
    "max_turns": {
        "type": "number",
        "required": false,
        "description": "Maximum conversation turns"
    },
    "needs_filesystem": {
        "type": "boolean",
        "required": false,
        "default": true,
        "description": "Whether the agent needs workspace filesystem access"
    },
    "task": {
        "type": "string",
        "required": false,
        "source": "runtime",
        "description": "Requirement or instruction"
    }
}
```

***

### Settings

The `settings` block declares daemon settings the agent reads from `ctx.settings`. Users configure them with `cliq settings set agents.<name>.<key> <value>`.

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"settings": {
    "required": [ ... ],
    "optional": [ ... ]
}
```

**Validation rules:** `settings` must be an object. `settings.required` must be an array. `settings.optional` must be an array when present. Each entry must be a plain string **or** an object with a non-empty `key` string.

#### Entry formats

Entries in `required` and `optional` accept two forms:

**Plain string** — just the key name:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"required": ["api_key"]
```

**Object** — key with metadata:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"required": [
    {
        "key": "api_key",
        "description": "API key for authentication"
    }
]
```

#### Object entry fields

| Property | Type | Description |
| - | - | - |
| `key` | string | **Required.** Setting key, relative to `agents.<name>.` |
| `description` | string | Human-readable description (shown in `cliq settings`, Hub UI) |
| `default` | any | Default value. When present on a required setting, the setting is treated as satisfied even without a user-supplied value. Seeded at daemon boot. |
| `when` | object | Conditional requirement — only require this setting when listed peer settings match (see below) |

#### `when` — conditional settings

The `when` field gates a setting on another setting's value. Each key in `when` is a peer setting name; the value is the required match:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"settings": {
    "required": [
        {
            "key": "provider",
            "description": "Git hosting provider: github or bitbucket",
            "default": "github"
        },
        {
            "key": "github.token",
            "description": "GitHub personal access token (repo scope)",
            "when": { "provider": "github" }
        },
        {
            "key": "bitbucket.email",
            "description": "Bitbucket account email",
            "when": { "provider": "bitbucket" }
        },
        {
            "key": "bitbucket.api_token",
            "description": "Bitbucket API token / app password",
            "when": { "provider": "bitbucket" }
        }
    ],
    "optional": [
        {
            "key": "github.base_branch",
            "description": "Default PR base branch",
            "default": "main",
            "when": { "provider": "github" }
        }
    ]
}
```

This is the real `git` agent: `github.token` is only required when `provider` is `"github"`. When `provider` is `"bitbucket"`, the GitHub settings are ignored and the Bitbucket ones are required instead.

**Validation:** `when` must be an object with string values. Each value must be a string.

***

### Output

The `output` block describes the shape of data the agent returns via `ctx.complete()`:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"output": {
    "data": {
        "action": "string",
        "url": "string",
        "pr_created": "boolean"
    },
    "text": "PR URL (pr_created is always true on success)"
}
```

| Property | Type | Description |
| - | - | - |
| `data` | `Record<string, string>` \| `null` | Keys and type names for the structured data the agent emits. `null` means no structured data. |
| `text` | string | Description of the text output |

The `data` field is documentation — it describes what keys appear in the `data` array that `on_invoke` returns. The daemon does not validate output shape at runtime.

***

### Binaries

List system binaries the agent needs on `$PATH`:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"binaries": ["git"]
```

`cliq doctor` checks each binary with `command -v`. Agents that are pure Node.js / HTTP can omit this.

***

### Env

Host environment variables the agent needs inherited from the OS:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"env": ["HOME", "PATH"]
```

These are **not** managed by cliq — they must already be set in the user's shell. Most agents omit this.

***

### Actions (connector agents)

Connector agents can document their per-action API with an `actions` block. This is not validated by the SDK but powers the OpenAPI docs generated for the **Agents** tab:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"actions": {
    "get_issue": {
        "direction": "source",
        "description": "Fetch a single issue by key",
        "phase_requires": ["sources"],
        "phase_fields": [],
        "entry_fields": [
            {
                "name": "name",
                "type": "string",
                "required": true,
                "description": "Output filename"
            },
            {
                "name": "ref",
                "type": "string",
                "required": true,
                "description": "Issue key (e.g. PROJ-123)"
            }
        ]
    },
    "create_pr": {
        "direction": "phase",
        "description": "Create a pull request",
        "phase_requires": [],
        "phase_fields": [
            {
                "name": "action",
                "type": "string",
                "required": true,
                "description": "Must be 'create_pr'"
            },
            {
                "name": "base_branch",
                "type": "string",
                "required": false,
                "description": "PR destination branch override"
            }
        ],
        "entry_fields": []
    }
}
```

| Action field | Description |
| - | - |
| `direction` | `"source"` (reads data), `"target"` (writes data), or `"phase"` (phase-level action) |
| `description` | What this action does |
| `phase_requires` | Which phase inputs must be present (`["sources"]`, `["target_entries"]`, etc.) |
| `phase_fields` | Fields set on the phase itself (in `team.yml`) |
| `entry_fields` | Fields on each entry inside `sources` or `target_entries` |

***

### MCP (LLM agents only)

The `mcp` block declares MCP (Model Context Protocol) server support. Users configure servers in the agent's settings (`agents.<name>.mcp.servers`).

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
"mcp": {
    "transports": ["http", "stdio"],
    "allow_custom": true,
    "presets": [ ... ]
}
```

**Validation rules:** `mcp.transports` must be a non-empty array of `"http"` and/or `"stdio"`. `mcp.allow_custom` must be a boolean when present. `mcp.presets` must be an array when present. Preset names must be 1–64 characters (`[A-Za-z0-9_-]`), no duplicates.

| Property | Type | Required | Description |
| - | - | :-: | - |
| `transports` | string\[] | **yes** | Supported transports: `"http"`, `"stdio"`, or both |
| `allow_custom` | boolean | no | Whether users can add servers beyond the presets (default `false`) |
| `presets` | object\[] | no | One-click server configurations |

#### Preset format

Each preset is a server the user can enable with one click in the Hub UI:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
    "name": "github",
    "label": "GitHub",
    "description": "Repositories, issues and pull requests",
    "transport": "http",
    "url": "https://api.githubcopilot.com/mcp/",
    "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
    },
    "secrets": [
        {
            "key": "GITHUB_TOKEN",
            "description": "GitHub personal access token",
            "help_url": "https://github.com/settings/personal-access-tokens"
        }
    ]
}
```

| Preset field | Type | Required | Description |
| - | - | :-: | - |
| `name` | string | **yes** | Server name (key in `mcp.servers`). 1–64 chars, `[A-Za-z0-9_-]`. |
| `label` | string | **yes** | Display name in the UI |
| `transport` | string | **yes** | Must be one of the manifest's `transports` |
| `description` | string | no | What this server provides |
| `url` | string | http | Server URL (http transport) |
| `headers` | object | no | HTTP headers. Values may contain `${SECRET_NAME}` placeholders. |
| `command` | string | stdio | Command to start (stdio transport) |
| `args` | string\[] | no | Command arguments (stdio transport) |
| `env` | object | no | Environment variables for the command. Values may contain `${SECRET_NAME}` placeholders. |
| `secrets` | object\[] | no | Secrets needed by this preset (fills `${NAME}` placeholders) |

**Secret format:** Each secret has `key` (required, `UPPER_SNAKE_CASE`), optional `description`, optional `help_url`. Users set secrets with `cliq settings set agents.<name>.mcp.secrets.<KEY> <value>`.

**stdio example** (Notion):

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
    "name": "notion",
    "label": "Notion",
    "description": "Pages and databases in Notion",
    "transport": "stdio",
    "command": "npx",
    "args": ["-y", "@notionhq/notion-mcp-server"],
    "env": { "NOTION_TOKEN": "${NOTION_TOKEN}" },
    "secrets": [
        {
            "key": "NOTION_TOKEN",
            "description": "Notion integration token",
            "help_url": "https://www.notion.so/profile/integrations"
        }
    ]
}
```

***

## 3. Write the handler

Extend one of the SDK base classes and implement `on_invoke`:

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import { StandardAgent } from '@getcliqio/cliq-sdk';
import type { StandardContext, AgentOutput } from '@getcliqio/cliq-sdk';

class MyAgent extends StandardAgent {
    constructor() {
        super('my-agent');
    }

    protected async on_invoke(ctx: StandardContext): Promise<AgentOutput> {
        // Your logic here
        ctx.log.info('starting work');
        ctx.progress('Processing...', 50);

        const result = `Processed: ${ctx.requirement}`;

        return {
            text: result,
            data: [{ status: 'done' }],
        };
    }
}

// Start when spawned by the daemon
const agent = new MyAgent();
agent.start().catch((err) => {
    console.error(err);
    process.exit(1);
});
```

### The context object

Every agent gets a context (`ctx`) with these fields and methods:

**Data fields:**

| Field | Description |
| - | - |
| `ctx.requirement` | The run's requirement / task text |
| `ctx.role` | Role text from the team manifest (LLM agents) |
| `ctx.settings` | Operator-provided settings (`agents.<name>.*`) |
| `ctx.inputs` | Run inputs (from `cliq run -i key=value`) |
| `ctx.config` | Team-authored config from the YAML `payload:` block |
| `ctx.upstream` | Output from completed upstream phases, keyed by phase name |
| `ctx.upstream_text` | Pre-rendered text summary of all upstream outputs |
| `ctx.commands` | Shell commands declared on this phase |
| `ctx.messages` | Conversation turns for multi-turn agents |
| `ctx.checkpoint` | Opaque cursor from a prior pause (null on fresh start) |

**Methods:**

| Method | Description |
| - | - |
| `ctx.complete(output)` | Signal success with output. **Terminator** — ends the agent. |
| `ctx.error(code, message)` | Signal failure. **Terminator** — ends the agent. |
| `ctx.progress(message, percent?)` | Send an intermediate progress update |
| `ctx.log.info(msg)` / `.warn` / `.error` / `.debug` | Structured logging into the run trail |
| `ctx.emit(type, payload)` | Emit a typed event to the orchestrator |
| `ctx.input_required(bundle)` | Park the phase until inputs are supplied. **Terminator**. |
| `ctx.submit_artifact(spec)` | Upload a durable artifact to Hub storage |
| `ctx.get_artifact(uri)` | Download a stored artifact into the workspace |
| `ctx.request_human_input(request)` | Pause and request human input via HUG |

**Returning vs calling `ctx.complete`:** If `on_invoke` returns an `AgentOutput`, the SDK auto-sends it as `complete`. You can also call `ctx.complete()` explicitly and return void.

### Class hierarchy

Pick the base class that matches your agent type:

```text theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
BaseAgent
  └── StandardAgent        (+upstream, +commands)
        ├── LlmAgent       (+model, +api_key, +prompt)
        │     ├── CliAgent     (+project_dir, +binary, +args)
        │     └── GateAgent    (+check_results, +pass/route/escalate)
        └── ConnectorAgent  (+action, +sources, +targets, +credentials)
```

* **`StandardAgent`** — most custom agents start here. Gets upstream data and commands.
* **`ConnectorAgent`** — for agents that talk to external APIs. Gets `action`, `sources`, `targets`, and `credentials`.
* **`GateAgent`** — for custom gate logic. Gets `check_results` and verdict methods (`pass`, `route`, `escalate`).

***

## 4. Add to the agents path

Create an `agents.json` in your agents directory:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
    "version": 1,
    "agents": {
        "my-agent": {}
    }
}
```

Then tell cliqd where to find it:

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# Option A: env var (session-scoped)
export CLIQ_AGENTS_PATH="/path/to/my-agents"

# Option B: persistent setting
cliq settings set agents.path "/path/to/my-agents"

# Option C: drop it in the system directory
# Copy to ~/.cliqrc/agents/my-agent/
```

The agents path is colon-separated, searched left-to-right. `~/.cliqrc/agents` (built-ins) is always appended last. **No restart needed** — agent resolution is JIT (reads from disk on every phase start).

Verify:

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
cliq agent list
cliq agent info my-agent
```

### Directory layout

```text theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
/path/to/my-agents/
├── agents.json              ← catalog for this directory
└── my-agent/
    ├── manifest.json        ← name, version, agent_type, entry, inputs, settings
    ├── index.js             ← entry point (or index.ts compiled to JS)
    └── package.json         ← depends on @getcliqio/cliq-sdk
```

Each agents directory has its own `agents.json`. The optional `path` field in an entry supports absolute or relative paths:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
    "version": 1,
    "agents": {
        "my-agent": {},
        "shared-agent": { "path": "/opt/shared-agents/reviewer" }
    }
}
```

### Shadowing built-ins

To override a built-in agent, place an agent with the same name in a directory that precedes the system dir. The first match on the path wins. cliqd logs when an agent is shadowed.

***

## 5. Use in a team

Reference your agent by name in `team.yml`:

```yaml theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
phases:
  - name: process
    type: standard
    agent: my-agent
    depends_on: [fetch]
```

The daemon resolves `my-agent` from the agents path when the phase fires.

***

## 6. Register on Hub (optional)

Registration pushes your agent's **manifest metadata** to Hub so it appears in the catalog. The code stays on your machine.

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
cliq agent register my-agent
cliq agent register /path/to/my-agent --force
```

This is needed when:

* Other users in your org want to see the agent in the Hub UI
* You publish a team that references the agent (Hub dispatch validates that referenced agents are registered)

To remove:

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
cliq agent unregister my-agent
cliq agent unregister my-agent --agent-version 0.1.0
```

### What registration does NOT do

* It does **not** upload your code — Hub stores manifest metadata only
* It does **not** install the agent on other machines — teammates add it to their own agents path
* It does **not** make the agent available for download — there is no agent distribution system

***

## Example: a complete exec agent

`manifest.json`:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
    "name": "line-counter",
    "version": "0.1.0",
    "description": "Counts lines in upstream text",
    "entry": "./index.js",
    "agent_type": "exec",
    "inputs": {},
    "output": {
        "data": { "line_count": "string" },
        "text": "Line count summary"
    }
}
```

`index.js`:

```javascript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import { StandardAgent } from '@getcliqio/cliq-sdk';

class LineCounter extends StandardAgent {
    constructor() {
        super('line-counter');
    }

    async on_invoke(ctx) {
        const lines = ctx.upstream_text.split('\n').length;
        ctx.log.info('counted lines', { lines });

        return {
            text: `Upstream text has ${lines} line(s).`,
            data: [{ line_count: String(lines) }],
        };
    }
}

new LineCounter().start().catch(() => process.exit(1));
```

***

## Validation and debugging

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
cliq team validate           # checks that referenced agents exist
cliq agent list              # see what's resolved
cliq agent info my-agent     # check manifest details
cliq doctor                  # checks agents, settings, binaries
```

Run logs show agent output and events:

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
cliq logs -f                 # follow the live run
cliq logs <run_id>           # read a past run
```

Per-run logs are at `~/.cliqrc/logs/runs/<daemon_id>/<run_id>.log`.

***

## Related

* Agent catalog and built-ins → [Agents](/agents)
* SDK package → [`@getcliqio/cliq-sdk`](https://github.com/getcliqio/cliq-sdk/pkgs/npm/cliq-sdk)
* CLI agent commands → [CLI — Agents](/cli#agents)
* Local development → [Local Development](/local-development)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.