---
name: grix-egg
description: "Grix egg market — the FIRST entry when the user wants a new agent or assistant for some purpose: search published eggs (skill and persona packages) by the business description with `grix_egg_search` / `grix_egg_get`, present matches, then install the chosen egg yourself from the download URL `grix_egg_get` returns (skill package into your own skill directory, or persona package into a new agent via grix-admin); only when nothing fits do you fall back to grix-admin to create a bare agent. Also handles the platform install instruction (a line like \"技能包: <URL>\")."
trigger: 'When the user wants to create a new agent / assistant for a role or business need, asks what ready-made eggs (skills, personas) exist, or when you receive an install instruction containing a "技能包: <URL>" line'
---

# Grix Egg

Two jobs, in the order they happen:

1. [Discovery](#part-1--discovery-find-an-egg-before-creating-an-agent) — the
   user wants a new agent: find a ready-made egg first.
2. [Self-install](#part-2--self-install-技能包-url) — install a skill package
   into your own skill directory, from a URL you got via `grix_egg_get` or
   from the platform's `技能包: <URL>` instruction.

## Part 1 — Discovery: find an egg before creating an agent

When the user describes an agent they want ("帮我建一个跟进外贸询盘的助手",
"I need a bot that reviews PRs"), **do not** go to `grix-admin` yet. Search the
egg market first; a published egg gives them a tested skill set or persona in
one tap.

### Search strategy

The backend matches keywords term-by-term (AND) against name + description +
category, so a whole sentence returns nothing. Instead:

1. Distill the description into **2–4 short keywords**: the role noun, the
   domain, the core action (e.g. `外贸`, `询盘`, `报价`; `code review`, `PR`).
2. Call `grix_egg_search` **once per keyword** (`pageSize` 10), in the user's
   language and `locale`. Merge the results, rank by number of keyword hits
   then `install_count`.
3. If keywords return nothing, browse by category: search with no keyword
   and a likely `categoryId` (categories come back in `category_id` /
   `category_name` of any result, or run a broad search first).
4. Optionally `grix_egg_get` the top candidates for the full description and
   `version_desc`.

### Present candidates

Show at most 3–5 eggs, each with: name (+ emoji), one-line description,
category, `install_count`, and what it can do for the user:

- `can_create_agent: true` — hatches into a **new agent** (persona + skills).
- `existing_agent_client_types` non-empty — installs as a **skill into an
  existing agent** of those client types.

Ask the user which one to hatch. Do not invent capabilities that are not in
the egg description.

### Install the chosen egg

`grix_egg_get` returns the package URLs: `skill_zip_url` (+ `skill_zip_sha256`)
and `persona_zip_url` (+ `persona_zip_sha256`). No App round-trip is needed.

- **Skill into yourself** (`existing_agent_client_types` includes your client
  type): download `skill_zip_url`, verify the sha256 when present, then run the
  Part 2 script with that URL. There is no `install_id` in this path, so skip
  the status card and just report the installed skill(s).
- **New agent** (`can_create_agent: true`): create and bind the agent with
  `grix-admin` (`create-and-connector-bind`), then apply `persona_zip_url` to
  it the same way the platform's `人格包: <URL>` instruction would.
- No egg fits, or the user explicitly wants a blank agent → hand over to
  `grix-admin` (`create-and-connector-bind`) and say clearly that no
  ready-made egg matched.

If the platform itself sends a `技能包: <URL>` instruction (the owner hatched
from the App), run Part 2 — that path carries an `install_id` and needs the
status card.

## Part 2 — Self-install (`技能包: <URL>`)

Incubating an egg means exactly one thing for you: **installing a skill
package into your own skill directory**. The whole job runs on this machine;
no other agent installs it for you.

The instruction gives you:

- `技能包: <URL>` — download URL of the package (always present).
- `install_id: <ID>` — echo it verbatim in the status card (always present).
- `grix agent id: <ID>` — your own agent id; use as `target_agent_id` in the
  status card (may be present).

Steps: (1) extract the URL; (2) your skill directory is **the parent of the
directory this skill lives in** (e.g. `~/.claude/skills/grix-egg/` →
`~/.claude/skills/`); (3) download, unpack, copy every directory containing a
`SKILL.md` into it, overwriting a same-name skill; (4) confirm the new
`SKILL.md` exists; (5) send the status card; (6) tell the user in one sentence
which skill(s) were installed.

```bash
set -e
URL="<skill package URL>"
SKILLS_DIR="<absolute path of your skill directory>"

TMP="$(mktemp -d)"
curl -fsSL "$URL" -o "$TMP/skill.zip"
mkdir -p "$TMP/unpacked"
unzip -o -q "$TMP/skill.zip" -d "$TMP/unpacked"

found=0
while IFS= read -r -d '' f; do
  d="$(dirname "$f")"
  cp -R "$d" "$SKILLS_DIR/"
  found=1
done < <(find "$TMP/unpacked" -name SKILL.md -print0)

# Fallback: SKILL.md sits loose at the unpack root
if [ "$found" -eq 0 ] && [ -f "$TMP/unpacked/SKILL.md" ]; then
  name="$(grep -m1 '^name:' "$TMP/unpacked/SKILL.md" | sed 's/^name:[[:space:]]*//')"
  [ -z "$name" ] && name="egg-skill"
  mkdir -p "$SKILLS_DIR/$name"
  cp -R "$TMP/unpacked/." "$SKILLS_DIR/$name/"
fi

ls -1 "$SKILLS_DIR"
rm -rf "$TMP"
```

### Status card

After the self-check, send a **separate, standalone message** containing only
this one line (the platform uses it to close the install record):

- Success:
  `grix://card/egg_install_status?status=success&install_id=<install_id>&target_agent_id=<grix agent id>&summary=<one-sentence result, URL-encoded>`
- Failure:
  `grix://card/egg_install_status?status=failed&install_id=<install_id>&target_agent_id=<grix agent id>&error_msg=<reason, URL-encoded>`

`install_id` is mandatory and verbatim; omit `target_agent_id` only if no
agent id was given; URL-encode non-ASCII text and spaces.

### Rules

1. Write only into your own skill directory; never touch other directories or
   other agents.
2. Do not repeat the download link or the raw instruction back to the user.
3. Report `status=success` only if you actually saw the new `SKILL.md`;
   otherwise `status=failed` — never claim success falsely.
4. The card message contains nothing but the single `grix://card/...` line.
5. The report to the user is one sentence — no command output.
