Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions agents/cli-expert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
meta:
name: cli-expert
description: |
**THE authoritative expert on the Amplifier CLI application itself** — the
`amplifier` command, its slash commands, provider/model switching, session
lifecycle, context loading, output formats, and what spawned sub-agents
inherit. Carries the reference docs that shipped with THIS installed CLI
version, so its answers match the binary the user is actually running.

Use PROACTIVELY when the user asks how the CLI itself behaves, rather than
asking for help with their own code. CLI behavior is version-specific and
changes between releases — answering from memory produces confident, wrong
instructions, which is the precise failure this agent exists to prevent.

**Authoritative on:** `/provider`, provider pinning, switching models
mid-conversation, `amplifier provider`, `/config`, `/mode`, `/modes`,
`/goal`, autonomous continuation, stop conditions, `/fork`, `/save`,
`/rename`, `/clear`, `/status`, `/agents`, `/tools`, `/skills`, `/skill`,
`/allowed-dirs`, `/denied-dirs`, `/help`, interactive mode, session
resume, session state location, `@mention` context loading, bundle
context precedence, `amplifier bundle`, app bundles, `--output json`,
`--output json-trace`, output formats for automation, spawn-time
precedence, what tools and providers a sub-agent inherits

**MUST be used for:**
- "How do I switch models / pin a provider / use a different model?"
- Any question naming a slash command or an `amplifier <subcommand>`
- "Why did this session load that context / where does session state live?"
- Scripting or automating Amplifier (output formats, exit behavior)
- "What does a spawned agent inherit?" / delegation precedence questions

<example>
<context>User wants a different model partway through a conversation</context>
<user>How do I switch models without losing this conversation?</user>
<assistant>I'll delegate to app-cli:cli-expert — provider pinning and the
/provider command are its domain, and it carries the docs matching this
installed CLI version.</assistant>
<commentary>Model/provider switching is version-specific CLI behavior. The
root session should route rather than guess at flag names that may not
exist in this build.</commentary>
</example>

<example>
<context>User is scripting Amplifier in CI</context>
<user>I need to parse Amplifier's output in a CI job — what formats are there?</user>
<assistant>Let me bring in app-cli:cli-expert to cover the --output json
and json-trace formats and their schemas.</assistant>
<commentary>Output formats are a documented CLI contract; the expert owns
OUTPUT_FORMATS.md and can give exact, current field names.</commentary>
</example>

<example>
<context>User is confused about sub-agent capabilities</context>
<user>Why doesn't my sub-agent have the tool I configured?</user>
<assistant>I'll consult app-cli:cli-expert — spawn-time precedence
determines what a spawned agent inherits.</assistant>
<commentary>SPAWN_PRECEDENCE.md defines the three-level policy; this is a
CLI-application question, not a bug in the user's code.</commentary>
</example>

model_role: general
---

# Amplifier CLI Expert

You are the specialist consultant on the **Amplifier CLI application itself** —
not on the user's project code, and not on the Amplifier kernel or bundle
authoring internals.

**Execution model:** You run as a one-shot sub-session. Answer from the
reference documentation below and return complete, actionable guidance.

**Version-matched authority:** The docs in your knowledge base shipped in the
same package as the CLI the user is running. Prefer them over anything you
recall about Amplifier from training — where they disagree, the docs win.

## Knowledge Base

@app-cli:docs/PROVIDER_PINNING.md
@app-cli:docs/INTERACTIVE_MODE.md
@app-cli:docs/GOAL_COMMAND.md
@app-cli:docs/CONTEXT_LOADING.md
@app-cli:docs/OUTPUT_FORMATS.md
@app-cli:docs/SPAWN_PRECEDENCE.md

Additional references you may `read_file` when a question needs them (paths
are relative to this bundle root):

- `docs/AGENT_DELEGATION_IMPLEMENTATION.md` — delegation internals
- `docs/decisions/` — ADRs recording why defaults are what they are
- `docs/designs/` — design docs for in-flight and shipped features

## When Consulted

1. **Identify the surface** — is this a slash command, an `amplifier`
subcommand, a config setting, or session behavior?
2. **Ground the answer in the docs above.** Quote exact command names, flags,
and config keys rather than paraphrasing them.
3. **Give a concrete next step** — the literal command or config edit to run.

## Boundaries — hand these off rather than guessing

- **Bundle/agent authoring, behaviors, composition semantics** → that is
foundation's domain, not the CLI application's.
- **Kernel contracts, module protocols, hooks API** → core's domain.
- **The user's own project code** → the root session handles it.

## Output Contract

Your response MUST include:

- The exact command, flag, or config key involved — as written in the docs
- A concrete next step the user can run or edit
- An explicit flag when the docs do not cover the question

**When the docs do not answer it, say so.** Your value is being right about
this CLI version. If the shipped documentation does not cover what was asked,
state plainly which docs you checked and that the behavior is undocumented,
and point at the relevant source path if you can identify it. Do not
reconstruct plausible-sounding flags or commands from general Amplifier
knowledge — a confidently invented flag is worse than an honest gap, because
the user will run it.

---

@foundation:context/shared/common-agent-base.md
4 changes: 2 additions & 2 deletions amplifier_app_cli/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def run(
console.print(
"[red]Error:[/red] --model requires --provider\n"
"Specify which provider to use: --provider anthropic --model claude-opus-4-6\n"
"Run 'amplifier provider use --help' for configuration options"
"Run 'amplifier provider list' to see your configured providers"
)
sys.exit(1)

Expand Down Expand Up @@ -256,7 +256,7 @@ def run(
console.print(
f"[red]Error:[/red] Provider '{provider}' not configured\n"
f"Available providers: {', '.join(p.get('id') or p.get('instance_id') or p.get('module', '?').replace('provider-', '') for p in providers_list if isinstance(p, dict))}\n"
f"Run 'amplifier provider use --help' for configuration options"
"Add one with 'amplifier provider add', or see all options with 'amplifier provider --help'"
)
sys.exit(1)

Expand Down
109 changes: 109 additions & 0 deletions amplifier_app_cli/runtime/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ def _on_progress(action: str, detail: str) -> None:
# Always available - users choose to use /mode commands or not
compose_behaviors.extend(_build_modes_behaviors())

# CLI self-expertise (app-cli:cli-expert + a thin awareness pointer).
# Always composed: every session should be able to answer "how does
# this CLI work?" by delegating rather than guessing. Sourced from the
# installed package on disk, never a git URI, so the expert's docs
# always match the running CLI version.
compose_behaviors.extend(_build_app_cli_behaviors())

# Notification behaviors (desktop and push notifications). The flags
# object is the single source of truth for "is this enabled?" — the
# hook-override emitter in AppSettings.get_notification_hook_overrides()
Expand Down Expand Up @@ -897,6 +904,108 @@ def _build_modes_behaviors() -> list[str]:
]


# The app-cli bundle overlay lives at the REPO ROOT (bundle.md, behaviors/,
# agents/, context/, docs/), matching how amplifier, amplifier-core, and
# amplifier-foundation lay out their overlays.
#
# Those repos are cloned into ~/.amplifier/cache, so their repo-root dirs are
# on disk at runtime. This repo is not -- it installs from a wheel -- so
# pyproject.toml force-includes the same tree into the wheel under
# `amplifier_app_cli/_bundle/`. Both layouts are therefore possible at
# runtime, and _find_app_cli_bundle_root() resolves whichever is present.
_APP_CLI_PACKAGE_DIR = Path(__file__).parent.parent
_APP_CLI_BEHAVIOR_RELPATH = "behaviors/cli-expertise.yaml"


def _find_app_cli_bundle_root() -> Path | None:
"""Locate the app-cli bundle root for this install.

Two supported layouts, checked in order:

1. ``<package>/_bundle/`` -- installed wheel (force-included by
pyproject.toml). Checked first: when present it is authoritative.
2. ``<package>/..`` -- the repo root in a dev checkout / editable install,
where ``behaviors/`` sits beside ``amplifier_app_cli/``.

Probing for the behavior file itself (not just the directory) means a
half-populated tree is treated as missing rather than silently yielding
an unloadable URI.

Returns:
Bundle root directory, or None if neither layout is present.
"""
for candidate in (_APP_CLI_PACKAGE_DIR / "_bundle", _APP_CLI_PACKAGE_DIR.parent):
if (candidate / _APP_CLI_BEHAVIOR_RELPATH).is_file():
return candidate
return None


def _build_app_cli_behaviors() -> list[str]:
"""Return the CLI self-expertise behavior URI for composition.

This wires up ``app-cli:cli-expert`` -- the expert consultant on the CLI
application itself (provider pinning, slash commands, sessions, context
loading, output formats, spawn precedence) -- plus a thin always-on
awareness pointer telling the root session to delegate CLI questions
rather than answer them from memory.

Two deliberate choices, both load-bearing:

1. **Sourced from disk, never a git URI.** The path is computed from this
package's own location, exactly as ``_ensure_default_skills_dirs()``
does for packaged skills. A CLI expert pinned at ``@main`` could
document flags the installed CLI does not have; resolving in-package
makes that version skew structurally impossible.

2. **Only the behavior, never the root ``bundle.md``.** ``Bundle.compose()``
replaces the instruction whenever the composed bundle has a non-empty
markdown body (foundation ``_dataclass.py``: ``if other.instruction:
result.instruction = other.instruction``). ``bundle.md`` has a body;
the behavior YAML does not. Composing the root bundle here would
silently clobber the user's system prompt.

The ``file://`` scheme is required -- ``parse_uri()`` only extracts the
``#subdirectory=`` fragment for ``file://`` URIs. A bare absolute path
with a fragment is parsed as a single literal path and fails to resolve.

Returns:
Single-element list with the behavior URI.

Raises:
RuntimeError: If the bundle overlay is missing from this install.
This is deliberately fatal rather than a warning-and-skip. The
behavior composition loop in
``lib/bundle_loader/prepare.py`` catches per-behavior load
failures and continues, so a bad URI returned from here would be
swallowed and the expert would silently vanish -- exactly the
failure mode that is hardest to notice and worst to ship. A
missing overlay means the wheel was built without the
``force-include`` block in pyproject.toml, which is a packaging
regression that should surface on the first run, not in a bug
report six weeks later.
"""
bundle_root = _find_app_cli_bundle_root()
if bundle_root is None:
searched = " and ".join(
str(candidate / _APP_CLI_BEHAVIOR_RELPATH)
for candidate in (
_APP_CLI_PACKAGE_DIR / "_bundle",
_APP_CLI_PACKAGE_DIR.parent,
)
)
raise RuntimeError(
"amplifier-app-cli is missing its bundle overlay "
f"({_APP_CLI_BEHAVIOR_RELPATH}). Searched: {searched}. "
"This install cannot provide the app-cli:cli-expert agent. "
"If this is a built wheel, the [tool.hatch.build.targets.wheel."
"force-include] block in pyproject.toml is missing or wrong; "
"if this is a source checkout, the repo-root behaviors/ "
"directory is absent."
)

return [f"file://{bundle_root}#subdirectory={_APP_CLI_BEHAVIOR_RELPATH}"]


def _build_notification_behaviors(flags: NotificationFlags) -> list[str]:
"""Build list of notification behavior URIs based on resolved flags.

Expand Down
29 changes: 29 additions & 0 deletions behaviors/cli-expertise.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
bundle:
name: behavior-cli-expertise
version: 0.1.0
description: |
Adds an expert consultant on the Amplifier CLI application itself —
provider pinning, slash commands, sessions, context loading, output
formats, and spawn precedence.

agents:
include:
- app-cli:cli-expert

# Thin awareness pointer ONLY.
#
# The heavy reference docs (docs/PROVIDER_PINNING.md, docs/CONTEXT_LOADING.md,
# docs/INTERACTIVE_MODE.md, docs/GOAL_COMMAND.md, docs/OUTPUT_FORMATS.md,
# docs/SPAWN_PRECEDENCE.md) are @-mentioned in the cli-expert AGENT BODY, so
# they load only when that agent is spawned (context-sink pattern).
#
# The file below is a routing pointer, not documentation: it tells the root
# session that this domain exists and to delegate. It must stay well under
# the 1,000-token behavior context.include ceiling that foundation's
# validate-bundle-repo context-sink-compliance check enforces.
#
# This behavior is composed onto EVERY CLI session, so every token here is
# paid on every turn of every session. Do not grow it.
context:
include:
- app-cli:context/cli-awareness.md
79 changes: 79 additions & 0 deletions bundle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
bundle:
name: app-cli
version: 0.1.0
description: >
Expert consultant for the Amplifier CLI application itself — provider
pinning, slash commands, sessions, context loading, output formats,
and spawn precedence.

# Include this repo's own behavior by default, so loading the bundle directly
# gets the same capability the CLI auto-composes. (The CLI composes the
# BEHAVIOR yaml, not this file — see behaviors/cli-expertise.yaml.)
includes:
- bundle: app-cli:behaviors/cli-expertise
---

# Amplifier CLI Bundle

A bundle **overlaid on the existing `amplifier-app-cli` repo** — `behaviors/`,
`agents/`, and `context/` sit at the repo root as siblings of the
`amplifier_app_cli/` Python package and of `docs/`, matching every other repo
in the ecosystem (`amplifier`, `amplifier-core`, `amplifier-foundation`).

## Why the expert lives in this repo

A CLI expert's authority is only as good as its version match with the
installed CLI. A separately-versioned bundle pinned at `@main` can document
`/provider` behavior the installed CLI does not have, or miss behavior it
does. Shipping here makes that skew structurally impossible: the expert that
answers your question is the one that shipped in your wheel.

`docs/` being a natural sibling is the payoff — `agents/cli-expert.md`
@-mentions the repo's real, canonical docs. There is no copy to drift.

## How it reaches an installed user

Sibling repos are *cloned* into `~/.amplifier/cache/`, so their repo-root
bundle dirs are on disk at runtime. **This repo is not** — it is installed
with `uv tool install`, which ships only the wheel.

So `pyproject.toml` force-includes these dirs into the wheel under
`amplifier_app_cli/_bundle/`:

```
[tool.hatch.build.targets.wheel.force-include]
"bundle.md" = "amplifier_app_cli/_bundle/bundle.md"
"behaviors" = "amplifier_app_cli/_bundle/behaviors"
"agents" = "amplifier_app_cli/_bundle/agents"
"context" = "amplifier_app_cli/_bundle/context"
"docs" = "amplifier_app_cli/_bundle/docs"
```

The repo root stays the single source of truth; the wheel carries a copy.
`_build_app_cli_behaviors()` in `amplifier_app_cli/runtime/config.py` resolves
whichever layout is present — `_bundle/` when installed, repo root in a dev
checkout — and **raises** if neither is found, so a packaging regression is
loud rather than a silently missing expert.

The target is `_bundle/` *inside* the package deliberately: force-including
to a top-level `amplifier_app_cli/agents` would create a directory with no
`__init__.py` that shadows the real package namespace.

## Structure

```
amplifier-app-cli/
├── bundle.md # this file — namespace: app-cli
├── behaviors/cli-expertise.yaml # the composable capability
├── agents/cli-expert.md # context sink: @-mentions docs/
├── context/cli-awareness.md # thin always-on pointer
├── docs/ # the repo's existing canonical docs
└── amplifier_app_cli/ # the Python package
```

## Scope

This bundle answers "how does the Amplifier CLI work?" It deliberately does
**not** promote features or surface tips — that is a separate concern and
belongs in a separate bundle.
Loading
Loading