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
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mstack",
"version": "0.4.0",
"version": "0.4.1",
"description": "Portable engineering skills for Codex, Claude Code, OpenCode, and pi.",
"author": {
"name": "3metaJun"
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## 0.4.1 - 2026-09-12

### Upgrade notes

Run `npx @3metajun/mstack@0.4.1 --harness all --migrate --replace --dry-run`
to inspect the migration, then repeat without `--dry-run`. Recognized legacy
copies are backed up outside skill discovery roots. Unrecognized local
copies stop migration before writes. SSH migration must run locally on the
target machine.

### Fixes

- Share one canonical skill copy across Codex, OpenCode and pi. Claude keeps
its adapter and derives skill names from directories, so OpenCode skips its
duplicate copy without changing global settings.
- Migrate legacy copies, archived backups and interrupted stages with retained
originals and rollback. Validate physical path aliases before writing.
- Keep agent definitions in native directories and shared tools beside their
skills. Deduplicate compatible explicit and remote targets.
- Reuse target resolution in the installer and smoke checks so OpenCode and pi
checks inspect the shared installation.

## 0.4.0 - 2026-09-12

This release adds a shared project workflow for teams using pstack and mstack
Expand Down
65 changes: 55 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ npx @3metajun/mstack --harness all \

The installer preserves an existing skill directory. Use `--dry-run` to inspect
the plan. Use `--replace` to move existing directories into a timestamped
`.harness-skills-backups/` directory under the replaced target's parent. Skill
backups therefore stay inside that Harness's `skills/` directory, and custom
artifact backups stay beside the artifact target. mstack retains backups until
you inspect and remove them.
`.harness-skills-backups/` directory outside the skill root. Backups, staged
skills and failed replacements must stay outside discovery roots because
OpenCode also scans hidden subdirectories. Artifact backups stay beside the
artifact target. The installer prints each backup path and retains its contents.

## Install optional artifacts

Expand All @@ -61,9 +61,9 @@ The available installable artifacts are:

| Artifact | Default destination |
| --- | --- |
| `agents` | Codex: `$CODEX_HOME/agents/` as TOML; other harnesses: `agents/` beside `skills/` as Markdown |
| `meta-mode-tools` | `tools/meta-mode/` beside `skills/` |
| `guide` | `docs/guide/` beside `skills/` |
| `agents` | Codex: `$CODEX_HOME/agents/` as TOML; other harnesses: their native `agents/` directory as Markdown |
| `meta-mode-tools` | `tools/meta-mode/` beside the resolved skill root; shared consumers use `~/.agents/tools/meta-mode/` |
| `guide` | `docs/guide/` beside the resolved skill root |

Codex skills default to `~/.agents/skills/`, while Codex agents default to
`~/.codex/agents/`. An unset or empty `CODEX_HOME` uses `~/.codex`.
Expand Down Expand Up @@ -115,11 +115,56 @@ The default directories are defined in
| --- | --- | --- |
| Codex | `~/.agents/skills/` | `HARNESS_SKILLS_CODEX_DIR` |
| Claude Code | `~/.claude/skills/` | `HARNESS_SKILLS_CLAUDE_DIR` |
| OpenCode | `~/.config/opencode/skills/` | `HARNESS_SKILLS_OPENCODE_DIR` |
| pi | `~/.pi/agent/skills/` | `HARNESS_SKILLS_PI_DIR` |
| OpenCode | `~/.agents/skills/` | `HARNESS_SKILLS_OPENCODE_DIR` |
| pi | `~/.agents/skills/` | `HARNESS_SKILLS_PI_DIR` |

Codex, OpenCode and pi share one physical copy per skill by default. Updating
through any of these Harnesses updates that shared copy. Claude gets its own
adapter output without a frontmatter `name`: Claude uses the directory name,
while OpenCode skips that copy. No global Harness settings are changed.

OpenCode and pi agent artifacts retain their native configuration roots.
`CLAUDE_CONFIG_DIR`, `XDG_CONFIG_HOME` and `PI_CODING_AGENT_DIR` still resolve
native roots and legacy migration locations; the latter two no longer move
the default shared skills. Use `HARNESS_SKILLS_*_DIR` for explicit skill paths.

Set an override to install into a mounted Fleet directory or another local
path. The path must be absolute or start with `~/`.
path. The path must be absolute or start with `~/`. Explicit overrides and
named environment targets are not rewritten. Equal targets are combined only
when their selected skill adapters agree; Claude and canonical output cannot
share a target. Keep explicit copies out of overlapping discovery paths.

### Migrate an existing installation

Run the new installer locally on the machine that owns the skills:

```bash
npx @3metajun/mstack --harness all --migrate --replace --dry-run
npx @3metajun/mstack --harness all --migrate --replace
```

Migration moves recognized legacy OpenCode and pi copies into backups outside
skill discovery. It also moves old installer backup trees and recognized
staging leftovers out of discovery.
A partial shared update checks the same selected names in all native roots,
including Harnesses not named on the command line. Existing Claude copies
that need only directory-based identity are adapted from their installed
contents, preserving supporting files and body edits. Directly selected skills
are replaced from the package, with their original contents backed up.

Ownership comes from an mstack install receipt or known released `SKILL.md`
content from versions 0.2.0 through 0.4.0. An unrecognized same-name legacy copy
stops migration before writes; inspect and relocate that copy before retrying.
Unselected active skills and unrelated skill names remain in place. Re-running
the migration is safe, and a later failed write rolls back earlier migrations.

Without `--migrate`, the installer reports legacy copies that would remain
active. Automatic migration requires a default shared local target. For SSH or
mounted custom layouts, run migration on the target machine with its native
paths; SSH `--migrate` is rejected before connecting. SSH dry-run validates
configured destinations but does not inspect the remote filesystem.

### Custom and remote targets

```powershell
$env:HARNESS_SKILLS_OPENCODE_DIR = 'C:\path\to\fleet\opencode\skills'
Expand Down
1 change: 1 addition & 0 deletions adapters/claude.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"directoryName": true,
"removeFrontmatter": {
"show-me-your-work": ["metadata"]
},
Expand Down
22 changes: 20 additions & 2 deletions docs/harness-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ to the official documentation used for each entry.
| --- | --- | --- | --- |
| Codex | `~/.agents/skills/` | `.agents/skills/` | Agent Skills fields; Codex-specific `agents/openai.yaml` lives beside each skill |
| Claude Code | `~/.claude/skills/` | `.claude/skills/` | `name`, `description`, `license`, `compatibility`, `metadata`, and Claude invocation fields |
| OpenCode | `~/.config/opencode/skills/` | `.opencode/skills/` | `license`, `compatibility`, and `metadata` |
| pi | `~/.pi/agent/skills/` | `.pi/skills/` | `license`, `compatibility`, `metadata`, `allowed-tools`, and `disable-model-invocation` |
| OpenCode | `~/.agents/skills/`, `~/.config/opencode/skills/`, `~/.claude/skills/` | `.opencode/skills/` | `license`, `compatibility`, and `metadata` |
| pi | `~/.agents/skills/`, `~/.pi/agent/skills/` | `.pi/skills/` | `license`, `compatibility`, `metadata`, `allowed-tools`, and `disable-model-invocation` |

Sources:

Expand All @@ -25,6 +25,24 @@ can read. Claude Code accepts `metadata` but does not act on its contents, so
the `compatibility` field instead. OpenCode and pi retain `metadata` because
their official references support it.

mstack installs one canonical copy in `~/.agents/skills/` for Codex, OpenCode
and pi. Claude output omits frontmatter `name`; Claude's documented fallback
uses the directory name, so `/meta-mode` keeps its name. OpenCode requires an
explicit name before registration and skips the Claude copy. This behavior
was checked with OpenCode 1.18.30 using a named Claude control skill and an
unnamed Claude copy alongside the canonical shared skill. Claude Code 2.1.267
also returned the directory-derived command name during an isolated
stream-JSON initialization without a user prompt or model request. Recheck this adapter
if OpenCode adds a directory-name fallback for external skills.

pi 0.85.1 keeps the first same-name skill and reports a collision for later
independent copies. A stale native pi copy can therefore hide a shared update.
The installer migration removes recognized redundant copies from discovery;
see [migration instructions](../README.md#migrate-an-existing-installation).
It also keeps backups outside skill roots so recursive scanners do not load
archived versions. Project wrappers use their separate generator and are not
migrated by the user-level installer.

## Shared project verification wrappers

Project verification has one canonical contract at
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@3metajun/mstack",
"version": "0.4.0",
"version": "0.4.1",
"description": "Portable engineering skills for Codex, Claude Code, OpenCode, and pi.",
"repository": {
"type": "git",
Expand All @@ -25,7 +25,7 @@
"install-skills": "node scripts/install.mjs",
"optimize-context": "node scripts/optimize-context.mjs",
"reconcile-context": "node scripts/reconcile-context.mjs",
"test": "node scripts/validate.mjs && node scripts/skill-baseline.mjs --check && node --test scripts/install.test.mjs scripts/context.test.mjs scripts/model-config.test.mjs scripts/audit-context.test.mjs scripts/worktree-audit.test.mjs scripts/sync-upstream.test.mjs scripts/runtime.test.mjs scripts/environment.test.mjs scripts/skill-integrity.test.mjs scripts/skill-baseline.test.mjs scripts/version-integrity.test.mjs scripts/agent-format.test.mjs scripts/history.test.mjs scripts/harness-policy.test.mjs scripts/harness-project.test.mjs scripts/check-upstream-adaptations.test.mjs"
"test": "node scripts/validate.mjs && node scripts/skill-baseline.mjs --check && node --test scripts/install.test.mjs scripts/install-migration.test.mjs scripts/migration-integration.test.mjs scripts/skill-discovery.test.mjs scripts/harness-targets.test.mjs scripts/remote-discovery.test.mjs scripts/context.test.mjs scripts/model-config.test.mjs scripts/audit-context.test.mjs scripts/worktree-audit.test.mjs scripts/sync-upstream.test.mjs scripts/runtime.test.mjs scripts/environment.test.mjs scripts/skill-integrity.test.mjs scripts/skill-baseline.test.mjs scripts/version-integrity.test.mjs scripts/agent-format.test.mjs scripts/history.test.mjs scripts/harness-policy.test.mjs scripts/harness-project.test.mjs scripts/check-upstream-adaptations.test.mjs"
},
"bin": {
"mstack": "scripts/install.mjs",
Expand Down
8 changes: 4 additions & 4 deletions profiles/environments.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"targets": {
"codex": "/home/dev/.agents/skills",
"claude": "/home/dev/.claude/skills",
"opencode": "/home/dev/.config/opencode/skills",
"pi": "/home/dev/.pi/agent/skills"
"opencode": "/home/dev/.agents/skills",
"pi": "/home/dev/.agents/skills"
},
"artifacts": {
"agents": {
Expand All @@ -43,8 +43,8 @@
"meta-mode-tools": {
"codex": "/home/dev/.agents/tools/meta-mode",
"claude": "/home/dev/.claude/tools/meta-mode",
"opencode": "/home/dev/.config/opencode/tools/meta-mode",
"pi": "/home/dev/.pi/agent/tools/meta-mode"
"opencode": "/home/dev/.agents/tools/meta-mode",
"pi": "/home/dev/.agents/tools/meta-mode"
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions profiles/harnesses.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"opencode": {
"directoryVariable": "HARNESS_SKILLS_OPENCODE_DIR",
"sharedSkills": true,
"configVariable": "XDG_CONFIG_HOME",
"configFallback": ".config",
"prefix": ["opencode"],
Expand All @@ -36,6 +37,7 @@
},
"pi": {
"directoryVariable": "HARNESS_SKILLS_PI_DIR",
"sharedSkills": true,
"configVariable": "PI_CODING_AGENT_DIR",
"configFallback": ".pi/agent",
"suffix": ["skills"],
Expand Down
Loading