⚠️ Applicable boundary (finalized 2026-08-06): each agent's persistent skill space (
~/.pi/agent/skills、~/.qwen/skills、~/.claude/skills、~/.soia/skills) is now defined as thephysical installationnormative standard— symlinks produce installations with no source record and that are not reproducible across machine changes, and on that day everything was converted in full tonpx skills add --copyphysical installations and registered in the lock.This skill must no longer be used for the above persistent spaces; use it only in scenarios such as temporary verification or one-off trial installs where reproducibility is explicitly not pursued, and clean up immediately after use.
Customer-readable description
What this skill can do
Synchronize an installed or local shared skill directory to a user-selected AI tool directory. It only creates or replaces symlinks with the same name; first use --dry-run to show the impact, then write once explicit authorization already exists.
How customers use it
Provide the source directory, target id or path, and optionally a single skill name. The target is explicitly provided via --targets ; when no suitable built-in id exists, use an absolute path.
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py \
--source-dir <shared-skill-dir> \
--targets codex,claude \
--dry-run
After confirming the plan, remove --dry-run. Use --skills <name> to sync only the specified skill; by default it also includes the dependencies.hard from its frontmatter;--no-deps can turn off that behavior. Use --exclude-skills a,b to skip and remove the existing symlinks of these skills for each selected target in this run.
Dependencies and installation
claude plugin marketplace add soia-team/soia-open-skills
claude plugin install soia-meta@soia
When you only want this one skill, you can use the npx route. Note that the skill will land in the shared true source ~/.agents/skills; if a plugin is also installed, the same skill will appear as two indexes and each will drift, so it is recommended to choose one of the two:
npx skills add soia-team/soia-open-skills -g -a '*' -s soia-meta-sync-skills -y
Depends on the Python 3 standard library and a source directory containing a SKILL.md subdirectory. An optional configuration example is in assets/config.example.yml: it records the user's own default source/targets and per-target excludes, and command-line arguments take precedence. The script reads and honors persistent excludes on every sync (including the default full sync). The configuration file is placed at:
~/.config/soia-skills/soia-meta-sync-skills/config.yml
SOIA_META_SYNC_SKILLS_CONFIG_FILE=<custom-config-path>
WorkBuddy 's loading unit is role-based experts rather than plugins,npx skills add -a '*' cannot cover it, and it needs to be installed separately, see docs/install/workbuddy.md。
Private information and intermediate data
- The configuration only stores the customer-selected source/targets and per-target excludes, and does not store API keys, cookies, sessions, or other credentials.
- The sync plan is by default only printed to the terminal; the actual written redacted audit log rotates per the "output file" convention and does not record key contents.
Logs and completion receipt
完成:<dry-run 或实际同步结果>。
日志摘要:
- source: <共享技能源>
- targets: <目标目录>
- linked/removed: <数量与名称>
- skipped/failed: <原因或无>
验证:<命令退出码、软链接解析或 dry-run>
问题与下一步:<确认、缺依赖或无>
Security boundary
- First show the source, target, and the links to be created/replaced/deleted; if there is no explicit write authorization for this run, stop at the preview.
- Refuse to use the source itself as the target; do not copy directories.
- Only handle
soia-*managed names and the currently named skills; never delete unrelated third-party skills. - By default, clean up first-level
soia-*symlinks pointing to nonexistent targets; use--no-pruneto keep them.
Workflow
- Confirm
--source-dir, the target, and the skill scope; do not guess personal directories or product workspaces. - Merge the per-target excludes in the configuration with this run's
--exclude-skills, run--dry-run, and review the create/replace/remove/unlink plan for each target. - Execute the same command after obtaining authorization (without the
--dry-run)。 - Review the exit code and the symlink resolution result for each target; report only validations actually performed.
Common commands:
# 查看内置目标或共享源中的技能
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py --list-targets
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py --source-dir <shared-skill-dir> --list-skills
# 同步一个技能并包含其 hard dependencies
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py \
--source-dir <shared-skill-dir> --targets <target-id-or-path> --skills <skill-name> --dry-run
# 本次排除并摘除既有软链(不持久化)
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py \
--source-dir <shared-skill-dir> --targets codex,claude \
--exclude-skills <skill-a>,<skill-b> --dry-run
# 确认后持久化到各 target;后续默认全量同步仍会尊重这些排除
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py \
--source-dir <shared-skill-dir> --targets codex,claude \
--exclude-skills <skill-a>,<skill-b> --save-excludes
Persistent exclusion structure in the private configuration:
schema_version: 3
excludes:
codex:
- "soia-example-skill"
claude: []
Exclusion only removes symlinks with the same name; if a real file or directory with the same name exists in the target, the script keeps it and reports it in the log.
Output file
Audit logs are written to ${XDG_STATE_HOME:-~/.local/state}/soia-meta-sync-skills/, with a maximum of 20 retained. It records parameters, link changes, and summaries, and does not write key contents.
Reference
references/targets-and-confirmation.md: Built-in targets and confirmation rules.references/source-rules.md: Resolution rules for local, GitHub, and skillsmp sources.references/soia-managed-skills.md: Naming boundaries for restricted cleanup.
Validation
python3 skills/soia-meta-sync-skills/scripts/sync_soia_skills.py --list-targets
python3 -m py_compile skills/soia-meta-sync-skills/scripts/sync_soia_skills.py
Create a test skill in a temporary directory containing only SKILL.md , and run it against another temporary target --dry-run; the acceptance output includes the expected create/link plan and the target directory is not written to. Then run a non-dry-run once in an explicitly authorized test directory, and use readlink to verify that the link points to the source directory. Finally, save an exclude for one target and execute the default full synchronization; verify that the symlink for that target remains removed and that symlinks with the same name for other targets are unaffected.