[Fix] Drop the Codex plugin manifest, document Codex install via .agents/skills

`.codex-plugin/plugin.json` never worked. `codex plugin marketplace add` on
this repo discovered zero plugins, because Codex reads a marketplace listing
at `.agents/plugins/marketplace.json` (which this repo does not have) and
requires each plugin root to be a subdirectory carrying its own real skills/
tree — `.`, `./` and `../../` as the plugin path all fail.

Both cheap workarounds install zero skills while still printing
"Added plugin", so the manifest was strictly worse than none:
  - `codex-plugin/skills` as a symlink to `../skills` — not dereferenced
  - `"skills": ["../skills/..."]` in plugin.json — not followed out of the root

The only working shape is a second, real copy of every skill, which is the
drift this repo just finished removing.

Codex discovers skills from `.agents/skills` (per repo) and `~/.agents/skills`
(user-wide) with no manifest at all — verified via `codex debug prompt-input`,
which shows the skill reaching the model. That is the cross-editor convention
Cursor also reads, so one README section covers both.

- remove `.codex-plugin/plugin.json`
- drop CODEX_PLUGIN from validate_skills.py checks 2 and 3, and record in the
  module docstring why there is deliberately no Codex manifest
- README: add a Codex manual-install section using `.agents/skills`
- CHANGELOG: correct the 0.4.1 entry (never tagged, so amended in place)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
raybobo
2026-07-31 17:59:52 +08:00
parent 7879ed9bec
commit 01255eed37
4 changed files with 36 additions and 74 deletions
-39
View File
@@ -1,39 +0,0 @@
{
"name": "meshy-3d-agent",
"version": "0.4.1",
"description": "Generate 3D models, textures, and images, rig and animate characters, and prepare models for 3D printing with the Meshy AI API.",
"author": {
"name": "Meshy",
"url": "https://github.com/meshy-dev"
},
"homepage": "https://www.meshy.ai",
"repository": "https://github.com/meshy-dev/meshy-3d-agent",
"license": "MIT",
"keywords": [
"meshy",
"3d-generation",
"text-to-3d",
"image-to-3d",
"3d-printing",
"rigging",
"animation"
],
"skills": [
"./skills/meshy-3d-generation",
"./skills/meshy-3d-printing",
"./skills/meshy-openclaw"
],
"interface": {
"displayName": "Meshy 3D Agent",
"shortDescription": "Generate and 3D-print 3D models with the Meshy AI API.",
"longDescription": "Text-to-3D, image-to-3D, texturing, rigging, animation, and a full 3D printing pipeline (slicer detection, multicolor, Creative Lab) via the Meshy AI API.",
"developerName": "Meshy",
"category": "Developer Tools",
"websiteURL": "https://www.meshy.ai",
"defaultPrompt": [
"Generate a 3D model of a medieval castle with Meshy",
"Turn this photo into a textured 3D model",
"3D-print my Meshy model in multicolor"
]
}
}
+3 -2
View File
@@ -10,8 +10,9 @@
### Added
- **Plugin manifests for the three official install channels.** `.claude-plugin/plugin.json` + `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json`, and `.codex-plugin/plugin.json`. Each marketplace entry pins an exclusive `skills` path so any single skill directory can be installed on its own. `.gitignore` previously ignored `.claude-plugin/`, which would have made the manifests uncommittable.
- **`validate-skills` CI (`scripts/validate_skills.py`), five checks on every PR and push to `main`:** ① frontmatter `name` matches the directory, `metadata.version` is semver, and `description` carries both a trigger phrase and a routing boundary; ② version stays in sync across all manifests, every `SKILL.md`, and the top CHANGELOG entry; ③ the marketplace and Codex skill lists cover exactly the `skills/` directory set; ④ references are bidirectional — every relative link resolves and every non-`SKILL.md` markdown file is reachable from `SKILL.md`; ⑤ no `..` path segments, so each skill directory stays independently installable. Check ④ is what would have caught the broken-install-link bug above.
- **Plugin manifests for Claude Code and Cursor.** `.claude-plugin/plugin.json` + `.claude-plugin/marketplace.json` and `.cursor-plugin/plugin.json`. Each marketplace entry pins an exclusive `skills` path so any single skill directory can be installed on its own. `.gitignore` previously ignored `.claude-plugin/`, which would have made the manifests uncommittable. Verified by installing all three skills through `claude plugin marketplace add` / `claude plugin install`: each plugin exposes exactly its own skill.
- **Codex install documented via `.agents/skills`.** Codex discovers skills from `.agents/skills` (per repo) and `~/.agents/skills` (user-wide) — the cross-editor convention Cursor also reads — so the directory install in the README covers it. A `.codex-plugin/plugin.json` was written and then removed: Codex's plugin marketplace only accepts a plugin root in a subdirectory carrying its own real `skills/` tree, and both cheap workarounds (a `skills` symlink, or a `"../skills"` path in the manifest) install **zero** skills while still reporting success. Shipping that manifest would have meant either committing a second copy of every skill or leaving users with a plugin that reports "installed" and does nothing.
- **`validate-skills` CI (`scripts/validate_skills.py`), five checks on every PR and push to `main`:** ① frontmatter `name` matches the directory, `metadata.version` is semver, and `description` carries both a trigger phrase and a routing boundary; ② version stays in sync across both manifests, every `SKILL.md`, and the top CHANGELOG entry; ③ the marketplace and Codex skill lists cover exactly the `skills/` directory set; ④ references are bidirectional — every relative link resolves and every non-`SKILL.md` markdown file is reachable from `SKILL.md`; ⑤ no `..` path segments, so each skill directory stays independently installable. Check ④ is what would have caught the broken-install-link bug above.
## [0.4.0] - 2026-06-24
+19
View File
@@ -174,6 +174,25 @@ cp skills/meshy-3d-printing/SKILL.md skills/meshy-3d-printing/reference.md .clau
</details>
<details>
<summary>Codex</summary>
Codex reads skills from `.agents/skills` — per repository, or from `~/.agents/skills` to make them available everywhere.
```bash
# Core (required)
mkdir -p .agents/skills/meshy-3d-generation
cp skills/meshy-3d-generation/SKILL.md skills/meshy-3d-generation/reference.md .agents/skills/meshy-3d-generation/
# 3D Printing (optional)
mkdir -p .agents/skills/meshy-3d-printing
cp skills/meshy-3d-printing/SKILL.md skills/meshy-3d-printing/reference.md .agents/skills/meshy-3d-printing/
```
`.agents/skills` is the cross-editor convention, so Cursor picks these up as well.
</details>
## Skill vs MCP Server
| Feature | Agent Skill (this repo) | [MCP Server](https://github.com/meshy-dev/meshy-mcp-server) |
+14 -33
View File
@@ -6,14 +6,20 @@ Five checks:
metadata.version, and a non-empty description containing both a trigger
phrase ("use when ...") and a routing boundary ("... instead", "not for ...").
2. Version sync: .claude-plugin/plugin.json, .cursor-plugin/plugin.json,
.codex-plugin/plugin.json, every SKILL.md metadata.version, and the top
CHANGELOG.md entry must all agree. Optional version fields in
.claude-plugin/marketplace.json (top level or per entry) must agree too.
3. Manifest coverage: all four manifests exist, parse, and carry a non-empty
every SKILL.md metadata.version, and the top CHANGELOG.md entry must all
agree. Optional version fields in .claude-plugin/marketplace.json (top
level or per entry) must agree too.
3. Manifest coverage: all three manifests exist, parse, and carry a non-empty
"name"; .claude-plugin/marketplace.json must list every skills/<dir>
across its entries' skills arrays; the explicit skills list in
.codex-plugin/plugin.json (and in the claude / cursor plugin.json, if
present) must cover the same set.
across its entries' skills arrays; an explicit skills list in the claude /
cursor plugin.json (if present) must cover the same set.
There is deliberately no .codex-plugin/plugin.json: Codex's plugin
marketplace only accepts a plugin root in a subdirectory carrying its own
real skills/ tree (a symlink or a "../skills" manifest path both install
with zero skills and still report success), which would mean committing a
second copy of every skill. Codex reads .agents/skills instead, so the
README's directory install covers it without a manifest.
4. Reference bidirectionality: every relative markdown link in a skill's
SKILL.md must resolve to an existing file inside the skill directory,
and every non-SKILL markdown file in the skill directory (reference.md,
@@ -45,8 +51,7 @@ CHANGELOG = ROOT / "CHANGELOG.md"
CLAUDE_PLUGIN = ROOT / ".claude-plugin" / "plugin.json"
MARKETPLACE = ROOT / ".claude-plugin" / "marketplace.json"
CURSOR_PLUGIN = ROOT / ".cursor-plugin" / "plugin.json"
CODEX_PLUGIN = ROOT / ".codex-plugin" / "plugin.json"
MANIFEST_PATHS = [CLAUDE_PLUGIN, MARKETPLACE, CURSOR_PLUGIN, CODEX_PLUGIN]
MANIFEST_PATHS = [CLAUDE_PLUGIN, MARKETPLACE, CURSOR_PLUGIN]
SEMVER_RE = re.compile(r"^\d+\.\d+\.\d+$")
FRONTMATTER_RE = re.compile(r"\A---\s*\n(.*?)\n---\s*\n", re.DOTALL)
@@ -310,30 +315,6 @@ def check_manifest_coverage(manifests: dict, load_errors: list[str]) -> list[str
f"skills/ contains {sorted(actual)}"
)
codex = manifests.get(CODEX_PLUGIN)
if codex is not None:
if "skills" not in codex:
errors.append(
f"{rel(CODEX_PLUGIN)}: explicit skills list missing (required so "
f"Codex exposes every skill directory)"
)
else:
covered = expand_skills_field(
codex["skills"], rel(CODEX_PLUGIN), actual, errors
)
if covered != actual:
errors.append(
f"{rel(CODEX_PLUGIN)}: skills covers {sorted(covered)} but "
f"skills/ contains {sorted(actual)}"
)
items = codex["skills"] if isinstance(codex["skills"], list) else [codex["skills"]]
for item in items:
if isinstance(item, str) and not item.startswith("./"):
errors.append(
f"{rel(CODEX_PLUGIN)}: skills entry '{item}' must start "
f"with './' (Codex manifest rule)"
)
# If the claude/cursor root plugin.json ever gains an explicit skills
# list, it must cover every skill directory too (auto-discovery does the
# right thing when the field is absent).