Skip to main content
ChatCLI lets you create Customizable Agents (also called Personas) that define specific behaviors for the AI. This system transforms ChatCLI from a tool with a static “System Prompt” into a polymorphic platform.

Core Concept

The central idea is prompt composition:
  • Agents define “who” the AI is (personality, specialization, tone).
  • Skills define “what” it must know/obey (rules, knowledge, compliance).
An Agent can import multiple Skills, creating a “Super System Prompt” composed automatically. Both Skills and Agents support per-turn model and effort preferences, honored automatically by the dispatcher when they activate.

Benefits

Reuse

Skills can be shared across multiple agents.

Versioning

.md files can be versioned in Git.

Collaboration

Teams can share agents and skills.

Consistency

Coding style rules applied automatically.

Specialization

Create agents for Go, Python, DevOps, etc.

Dispatch as Worker

Custom agents are automatically registered in the multi-agent system and can be dispatched via agent_call by the LLM orchestrator.

Skill Auto-activation

Skills with triggers: or paths: in their frontmatter are automatically injected into the system prompt when detected in the user’s message.

Per-Agent Model & Effort

Each skill and each agent can declare ideal model: and effort: — the dispatcher routes correctly without changing the user’s active choice.

Directory Structure

Files live under ~/.chatcli/:

Agent File Format

Agents are Markdown files with YAML frontmatter:

tools Field — Multi-Agent Integration

The tools field in the YAML frontmatter is the key to integration with the multi-agent orchestration system. It defines which commands the agent can use when dispatched as a worker by the LLM orchestrator.
Agents without a tools field automatically receive read, search, tree and are marked as read-only. Agents with Write, Edit, MultiEdit, or Bash have write/execution access. The 12 built-in agent names (file, coder, shell, git, search, planner, reviewer, tester, refactor, diagnostics, formatter, deps) are protected and cannot be overridden.

Example without tools

This agent will be registered as read-only in the multi-agent system (only read, search, tree).

Advanced Agent Frontmatter

Recent releases bring full parity between agents and skills for LLM preference fields. Both are optional and backwards compatible — agents without these fields keep working exactly as before.

How the Dispatcher Applies Model/Effort

When the orchestrator LLM dispatches an agent via <agent_call>, the dispatcher:
1

Reads `agent.Model()` and `agent.Effort()`

For custom agents these come from the frontmatter. For built-ins they come from BuiltinAgentMeta (defaults + env var override).
2

If `Model()` is non-empty, runs the Model Router

The resolver tries, in order: API cache of the active provider → static catalog → family heuristic (claude-*, gpt-*, gemini-*, etc.) → optimistic fallback on the user’s provider. If the target provider is not configured (no API key), it gracefully falls back to the user’s client and logs a clear warning.
3

If `Effort()` is non-empty, attaches to the worker `ctx`

Providers read the hint via client.EffortFromContext(ctx) inside SendPrompt and inject thinking.budget_tokens (Anthropic) or reasoning.effort / reasoning_effort (OpenAI) into the request body — only on models that support it.
4

`cli.Client`, `cli.Provider` and `cli.Model` are **not** mutated

Swaps are worker-turn scoped. When the worker finishes, the next agent dispatch or chat turn uses the user’s original choice.

Example: Custom Agent with Ideal Model

If the user has CLAUDEAI configured but is on claude-sonnet-4-6, this agent runs in claude-opus-4-6 automatically. If the user is on OPENAI with gpt-5 and does not have ANTHROPIC_API_KEY, the dispatcher falls back gracefully to the user’s model and prints a clear notice explaining why.

Skill File Format

Skills contain pure knowledge or compliance rules:

Skills V2 — Packages with Subskills and Scripts

Beyond V1 skills (single .md file), ChatCLI supports V2 Skills: directories with multiple documents and executable scripts.

V2 Skill Structure

Subskills

.md files inside the skill directory (except SKILL.md) are registered as subskills. When the agent is dispatched as a worker, subskill paths appear in the worker’s system prompt, which can read them as needed.

Scripts

Files in scripts/ are registered as executable skills on the worker. The system automatically infers the run command from the extension: Scripts run via the @coder exec command and their results return to the worker.

Advanced Skill Frontmatter

Beyond the basic fields (name, description, allowed-tools), skills support advanced frontmatter for fine-grained behavior control. All advanced fields are optional and backwards compatible — existing skills keep working unchanged.

Automatic Activation: triggers

Keywords that activate the skill automatically when detected in the user message. Case-insensitive, with two tiers:
  1. Contiguous substring (fast path) — the whole trigger appears as-is: servicenow login fires on “do the ServiceNow login”.
  2. All words, any order — multi-word triggers also fire when every word appears as a whole token in the text, regardless of order: servicenow login also fires on “preciso fazer o login no servicenow”. Whole tokens only — short words never match inside other words (message me does not fire on “user message”), and punctuation tokenizes on both sides (unit-testsunit tests).
If the user types “how do I write tests for this handler?”, the skill is automatically injected into the turn’s system prompt — together with the descriptive and full content of the skill. The LLM then follows the instructions automatically. Implemented in pkg/persona/manager.go#FindTriggeredSkills. Detection runs on every chat turn and, in agent/coder mode, at the start of the run and again on every turn of the ReAct loop (see Mid-task re-activation).

Automatic Activation: paths

File globs that activate the skill when matching files are being discussed. Supports *, ** (recursive doublestar), and ?.
ChatCLI extracts file-path-looking tokens from the user input (@file path/..., @path/to/file.go, or bare tokens like pkg/foo/bar_test.go and main.go) and matches each against the paths: patterns of every installed skill. Examples that trigger *_test.go:
  • "run the tests in pkg/foo/bar_test.go"
  • "@file pkg/foo/bar_test.go"
  • "@pkg/foo/bar_test.go"
Implemented in pkg/persona/types.go#MatchesPath (with a custom doublestar matcher, zero external deps) and pkg/persona/manager.go#FindPathMatchedSkills. Path extraction from input is in cli/skill_activation.go#extractFilePaths.
When the same skill matches via both triggers and paths, it is injected only once (deduplicated by name).

Mid-task re-activation (agent/coder)

In agent/coder mode, activation is not limited to the initial query. On every turn of the ReAct loop, ChatCLI re-scans for skills that haven’t fired yet, matching against:
  • the model’s own reasoning and the file paths inside its tool_call args — if the agent decides mid-task to “write a Helm chart for this”, or starts touching files matching a skill’s paths: globs, the skill activates in time to shape the very next action;
  • follow-up instructions you type mid-session (the type-ahead queue or the coder continuation prompt).
Newly matched skills are injected as an append-only [SKILL AUTO-ACTIVATION — MID-TASK] message at the next turn boundary, so the cached system-prompt prefix is never invalidated mid-run. Each skill fires at most once per run (deduplicated against startup injection), and the dedup set survives @park/resume. Mid-task model:/effort: hints are honored only when no startup skill already claimed them. Disable with CHATCLI_AGENT_SKILL_RESCAN=false (on by default; listed in /config under skills).

model and effort Propagation

When a skill auto-activates (via triggers or paths), is pinned (/skill pin), or is manually invoked, its model: and effort: are propagated to the current turn:
  • model: — the dispatcher/resolver swaps the LLM client for this turn. Works within the same provider (e.g., sonnetopus on Claude) or cross-provider (e.g., user on Claude, skill wants gpt-5 on OpenAI). If the target provider is not configured, it falls back to the user’s client with a visible notice.
  • effort: — mapped to thinking.budget_tokens (Anthropic, Opus 4.x / Sonnet 4.x / 3.7 models) or reasoning_effort / reasoning.effort (OpenAI, o1/o3/o4/gpt-5 models). Unsupported models silently ignore.
Precedence when multiple modes fire in the same turn:
The first non-empty model: in this order wins; subsequent conflicts are logged as warnings but don’t force additional swaps.

Manual Invocation via /<skill-name>

Skills with user-invocable: true are available as direct slash commands:
ChatCLI intercepts /<skill-name> ahead of the default router, validates that the skill exists with user-invocable: true, loads its content, displays the argument-hint (when args are empty), and fires the turn with the skill injected as a ”# Manually Invoked Skill” block in the system prompt — taking precedence over auto-activated skills. The protected command list (/agent, /coder, /run, /switch, /help, /skill, etc.) can never be shadowed by a skill — even a skill named agent won’t shadow the built-in command. Slash command autocomplete also includes all user-invocable: true skills, showing description and argument-hint side by side.

Invocation Control

disable-model-invocation: true together with user-invocable: true = the skill only runs when the user types /skill-name, never through automatic detection. Useful for destructive or highly specific skills.

Pin a Skill for the Session (/skill pin)

When you need a skill to apply to every turn of the session — not only those that match triggers:/paths: — pin it:
Pin is a session-scoped intent (doesn’t persist across runs) and lives in its own # Pinned Skills block in the system prompt, cacheable via cache_control: ephemeral. On hint conflicts, pinned beats auto-activation but loses to a manual /<skill-name> invocation. Skills with disable-model-invocation: true cannot be pinned — the flag exists precisely to forbid automatic injection. Use manual /<skill-name> for those. Full details, examples, and the precedence table: Pin Skills in Skill Registry.

/agent Without Context

Before: typing /agent alone entered agent mode immediately and sent an empty message to the LLM. Now: typing /agent (or /run) without an inline task prints the persona handler help plus a usage hint and does not start the ReAct loop. Same applies to /coder. This avoids token burn on empty messages and makes the UX more predictable.
To enter agent mode with context, pass the task inline:

Skills from Remote Registries

Besides creating skills manually, you can search and install skills from remote registries via the /skill command:
Skills installed via registry are saved in ~/.chatcli/skills/<name>/SKILL.md as V2 packages and are immediately available for agents. ChatCLI supports multiple registries simultaneously (ChatCLI.dev, ClawHub, corporate registries) with fan-out parallel search. See Skill Registry for full details.

Dispatch as Worker (Multi-Agent)

When starting /coder or /agent, all custom agents are automatically registered in the multi-agent orchestration system. The LLM orchestrator can then dispatch them via <agent_call>:

What the worker gets

When dispatched, CustomAgent runs with:
1

Personalized system prompt

Includes agent content (markdown body), loaded skills, subskill paths, script commands, and tool_call instructions.
2

Mini ReAct loop

The same ReAct loop as built-in agents, with reasoning, action, and observation.
3

Permitted commands

Based on the tools field of the frontmatter.
4

Per-turn resolved client

If the agent declares model:, the dispatcher calls ResolveModelRouting to obtain the correct client before each mini-ReAct turn.
5

Effort applied to ctx

If the agent declares effort:, the worker’s ctx receives WithEffortHint, read by the provider inside SendPrompt.
6

Parallel reads

Read-only tool calls run in parallel goroutines.
7

File locks

Writes use per-filepath mutex for anti-race safety.
8

Error recovery

The orchestrator can use direct tool_call to diagnose and fix failures.

End-to-End Example


Management Commands

All management commands are integrated under /agent:

Prompt Assembly Order

When an agent is loaded, the system prompt is assembled in this order:
1

[ROLE]

Agent identity (name, description)
2

[PERSONALITY]

Agent base content (markdown body)
3

[SKILLS]

Imported skill knowledge (numbered)
4

[AUTO-LOADED SKILLS]

Skills auto-activated via triggers: or paths: on the current message
5

[MANUAL SKILL]

Extra block when the message was invoked via /<skill-name>
6

[PLUGINS]

Enabled plugin hints
7

[REMINDER]

Anchor with application instructions
This ordering ensures the AI receives context in a structured way, with explicit user intent (manual) taking precedence over auto-activation.

Full Practical Example

1. Create an agent

Create the file ~/.chatcli/agents/python-data.md:

2. Use the agent

Agent and Skill Precedence (Project > Global)

Both agents and skills support per-project directories with precedence over the globals. ChatCLI auto-detects the project root by looking for a .agent/ or .git/ directory upward from the current directory.

Search Order

If an agent or skill with the same name exists in both directories, the project version wins.

Project Structure

If your project already has .git/, ChatCLI uses that directory as the project root automatically. .agent/ is optional — use it when you want project-local agents/skills without depending on Git.

Integration with /coder

When an agent is loaded:
  • /agent <task> — Uses the agent’s persona.
  • /coder <task> — Combines the agent’s persona with the coder prompt.
This lets you have a Go-expert agent using @coder tools to edit files, run tests, etc. The agent’s model: and effort: preferences are honored in both modes.

Tips

Start Simple

Create agents with a few skills and add more as needed.

Version on Git

Keep your agents and skills in a repo.

Share with the Team

Coding-style skills enforce consistency.

Use Clear Descriptions

Helps understand each agent/skill’s purpose.

Test the Prompt

Use /agent show to inspect the assembled prompt.

Assign `effort` Carefully

effort: high costs more tokens. Reserve it for agents that truly need deep reasoning (reviewers, planners, diagnostics).

Useful Skill Examples

  • clean-code — Clean code principles
  • error-handling — Error handling patterns
  • testing-patterns — Automated testing patterns
  • docker-master — Dockerfile best practices
  • clean-scripts — Safe Bash scripting patterns
  • aws-security — AWS security rules
  • team-conventions — Team-specific conventions

Remote Agents and Skills

When connected to a ChatCLI server via chatcli connect, the client automatically discovers agents and skills available on the server. They are transferred to the client and composed locally, allowing merge with local resources. Since the recent update, the gRPC wire (pb.AgentInfo) carries all the advanced fields — model, effort, category, version, author, tags — so remote agents behave exactly like local ones for routing purposes.

Provisioning via Kubernetes

ConfigMaps are mounted at /home/chatcli/.chatcli/agents/ and /home/chatcli/.chatcli/skills/, and are available for remote discovery automatically. Advanced frontmatter fields (model, effort, category, etc.) are read by the chatcli binary inside the pod — the CRD and operator do not need changes to support them.

Next steps

Multi-Agent Orchestration

How multiple custom agents run in parallel via <agent_call>.

Skill Registry

Publish and discover skills shared across teams.

Subagent Delegation

Focused delegation for concentrated analysis over a large payload.

Server Mode

Distribute agents via ConfigMap to the entire team.