Skip to content

feat(init): install skills into .meta/skills and link them into agent folders - #38

Merged
gold-silver-copper merged 5 commits into
mainfrom
harmony-2714-meta-skills-dir
Oct 24, 2026
Merged

gold-silver-copper merged 5 commits into
mainfrom
harmony-2714-meta-skills-dir

Conversation

@gold-silver-copper

@gold-silver-copper gold-silver-copper commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

meta init claude now installs its skills the way atc and git-kb do: real folders in a folder meta owns, linked into each agent's skills folder, so Codex and other agents get them too, not only Claude.

Layout

Before (#36):

.claude/skills/meta-git/SKILL.md          real folder, Claude only

After:

.meta/skills/meta-git/SKILL.md            real folder, commit it
.claude/skills/meta-git -> ../../.meta/skills/meta-git
.agents/skills/meta-git -> ../../.meta/skills/meta-git     (Codex and others)

.cursor/skills, .opencode/skills, .pi/skills, .omp/skills and .grok/skills also get links, but only when that agent's folder (.cursor/ etc.) already exists. The folder names are atc's agent registry (atc/crates/atc-cli/src/init/agents.rs); this is atc's --all-agents rule. Rules and hooks stay in .claude/ as before.

Ownership and upgrades

Each entry at a link path is read without following links (symlink_metadata):

Found default --update / --force
nothing link link
meta's link (exact relative target) kept kept
a marked copy (SKILL.md + .meta-skill-copy), anywhere kept, reported skipped its known files removed, rmdir, then linked
real folder holding only a SKILL.md identical to the shipped text, in .claude/skills/ only (#36 layout; no release shipped it, and its text is today's) kept, reported skipped same
plain file holding exactly ../../.meta/skills/<name> (git's checkout of the link with core.symlinks=false) kept, reported skipped removed, then linked or copied
anything else: a link elsewhere, a folder with other files, a file left alone, reported "not created by meta" same

No symlink is ever followed or removed. Rule files and settings.json get the same guard: when .claude/, .claude/rules/, a rule file or .claude/settings.json is a symlink, it is skipped and reported. Every folder on the way is checked too, without following links: a symlink anywhere in .meta/skills/<name>/SKILL.md stops the install with an error, and an agent skills folder reached through a symlink (e.g. .agents/skills -> ../.other/skills) is skipped and reported. git-kb's reject_symlinked_path does the same. Flat pre-#36 .claude/skills/meta-*.md files are removed with --update/--force only when they are regular files (not links) whose first line is the heading of a skill meta shipped. Every release's flat files start with one of seven known headings, such as # Meta Git Skill. Anything else at those names is reported and kept. .meta/skills/<name>/SKILL.md keeps the old rule: skipped if it exists, rewritten with --update/--force.

Windows

atc tries symlink_dir and copies on PermissionDenied/Unsupported. git-kb never tries a link on Windows and copies with no marker. Windows reports a missing symlink privilege as ERROR_PRIVILEGE_NOT_HELD, which Rust maps to an uncategorized error, not PermissionDenied, so atc's check misses it. meta tries the link and falls back to a copy on any link error. The copy holds .meta/skills/<name>/SKILL.md, copied rather than taken from the binary's built-in text, so a kept or newer committed skill is what agents see, plus a .meta-skill-copy marker. That marker is how later runs know the copy is meta's, and --update replaces a marked copy with a link once links work. Clones made with core.symlinks=false get the committed links as placeholder files, and --update replaces them, as shown in the table. A test forces link creation to fail (install_skills_with takes the link function) and checks the copies. Tests use assert_linked, which accepts a marked copy only on Windows, so the suite works on Windows with or without link rights.

Legacy .meta config file

A repo whose config is the legacy .meta file can't also have the .meta/ folder. meta init claude (with any flags) now refuses before writing anything:

This repo's meta config is the legacy `.meta` file, so meta can't create its `.meta/` folder for skills.
Rename the config and rerun: `git mv .meta .meta.json` (same content), or convert it to `.meta.yaml`.

The meta-repo warning check now uses find_meta_config_in, which accepts only files. Before, a .meta/ folder counted as a config there.

The plugin installer's workspace finder (registry.rs) still treats a .meta/ folder as a workspace marker for .meta/plugins/. That is intended (tests/plugin_install.bats covers it) and it never reads the folder as config, so it is unchanged.

For a shared crate later

install_skills(root, tool, skills, agent_dirs, overwrite, verbose) takes the tool name (.<tool>/skills, .<tool>-skill-copy), the skill bundle and the agent folder table as inputs. Nothing in it is meta-specific apart from the copy marker's text. The flat-file cleanup and the legacy .meta check stay outside it.

Tests

New unit tests: links for Claude and Codex, other agent folders only when they exist, legacy .meta refusal for every flag combination, --update over #36 folders (kept without it), marked copies replaced by links, foreign folders and files left alone under --update and --force, foreign links neither followed nor removed, single-file folders outside .claude/skills/ kept, git placeholders replaced, copies made from .meta/skills/ when links fail, and symlinked agent or .meta/skills/ folders never written through (Unix). cargo test for init: all passed; clippy -D warnings clean.

Merge order

Part of [tasks/harmony-2714]: meta keeps its agent skills in a local .meta/ folder. Four PRs, same branch name harmony-2714-meta-skills-dir, so each repo's CI builds against the others:

  1. test(config): a .meta directory is never read as config meta_core#9, fix(mcp): meta_get_config ignores a .meta directory meta_mcp#8, feat(init): install skills into .meta/skills and link them into agent folders #38: independent of each other, any order.
  2. feat(skills): keep meta's skills in .meta/skills, linked for Claude and Codex meta#105 last, after meta_cli#38: its tests/init.bats checks the new layout against meta_cli main. Then sync meta_cli into gitkb/meta as usual.

After a meta release, re-run meta init claude --update in harmony to move its committed .claude/skills/meta-*.md files to .meta/skills/ with links.

… folders

meta init claude now writes each skill to .meta/skills/<name>/SKILL.md
and links it into .claude/skills/ and .agents/skills/ (Codex and other
agents), as atc and git-kb do with .atc/skills/ and .kb/skills/. Other
agent folders from atc's registry (.cursor, .opencode, .pi, .omp, .grok)
get links when the agent's folder exists.

--update turns both older layouts into links: flat .claude/skills/*.md
files and real .claude/skills/<name>/ folders holding only SKILL.md.
Anything else at a link path (another tool's link, a folder with more
files, a file) is reported and left alone; no symlink is followed or
removed. Where a symlink can't be made (Windows without Developer Mode),
the skill folder is copied with a .meta-skill-copy marker, and a later
--update replaces it with a link.

A repo whose config is the legacy .meta file can't have the .meta/
folder: init refuses before writing anything and suggests
git mv .meta .meta.json. The meta-repo check now uses
find_meta_config_in, so a .meta/ folder is not taken for config.

install_skills takes the tool name, skill bundle and agent folder list
as inputs so it can move into a shared crate later.

Implements [[tasks/harmony-2714]]
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: d86f0108-02d9-4049-97a3-4a07a30588e9
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

…claude

Review fixes:
- A symlink anywhere in .meta/skills/<name>/SKILL.md stops the install,
  and an agent skills folder reached through a symlink is skipped, so
  no other tool's files are written or removed through a link.
- A real folder holding only SKILL.md counts as meta's only in
  .claude/skills/, where older releases wrote it.
- A plain file holding exactly meta's link target (git's checkout of a
  link with core.symlinks=false) is replaced, so --update repairs such
  Windows clones.
- The copy fallback copies .meta/skills/<name>/SKILL.md, not the
  embedded text, so a kept or newer committed skill is what agents see.

Implements [[tasks/harmony-2714]]
- A real .claude/skills/<name>/ folder holding only SKILL.md is meta's
  only when that SKILL.md is the shipped text (no release shipped the
  #36 layout, and its text is today's), so another tool's same-named
  skill is kept even with --force.
- Rule files are not written through a symlinked .claude/, .claude/rules/
  or rule file; they are reported as skipped.

Implements [[tasks/harmony-2714]]
--update and --force removed any regular .claude/skills/meta-<name>.md.
Now only files whose first line is the heading of a skill meta shipped
(every release's flat files start with one of seven known headings) are
removed; anything else is reported and kept. Also create .claude/rules/
after the skills step, so a refused install leaves no half-made .claude/.

Implements [[tasks/harmony-2714]]
@gold-silver-copper
gold-silver-copper merged commit b4026ca into main Oct 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant