@ouro.bot/cli 0.1.0-alpha.43 → 0.1.0-alpha.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.json CHANGED
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.44",
6
+ "changes": [
7
+ "Workflow skills now install into `~/.agents/skills` for Codex/OpenAI instead of duplicating installs under both `.agents` and `.codex`, which prevents duplicate advertised skills while keeping re-installs safe."
8
+ ]
9
+ },
4
10
  {
5
11
  "version": "0.1.0-alpha.43",
6
12
  "changes": [
@@ -64,6 +64,16 @@ function pathExists(target) {
64
64
  return false;
65
65
  }
66
66
  }
67
+ function isSameFile(source, target) {
68
+ try {
69
+ const sourceStats = fs.statSync(source);
70
+ const targetStats = fs.statSync(target);
71
+ return sourceStats.dev === targetStats.dev && sourceStats.ino === targetStats.ino;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
67
77
  function ensureSymlink(source, target) {
68
78
  fs.mkdirSync(path.dirname(target), { recursive: true });
69
79
  if (pathExists(target)) {
@@ -78,6 +88,25 @@ function ensureSymlink(source, target) {
78
88
  fs.symlinkSync(source, target);
79
89
  return true;
80
90
  }
91
+ function ensureHardLink(source, target) {
92
+ fs.mkdirSync(path.dirname(target), { recursive: true });
93
+ if (pathExists(target)) {
94
+ const stats = fs.lstatSync(target);
95
+ if (!stats.isSymbolicLink() && isSameFile(source, target)) {
96
+ return false;
97
+ }
98
+ fs.unlinkSync(target);
99
+ }
100
+ fs.linkSync(source, target);
101
+ return true;
102
+ }
103
+ function hasOpenAiSkillHome(homeDir) {
104
+ return pathExists(path.join(homeDir, ".codex")) || pathExists(path.join(homeDir, ".agents"));
105
+ }
106
+ function openAiSkillTargets(homeDir, source) {
107
+ const skillName = path.basename(source, ".md");
108
+ return [path.join(homeDir, ".agents", "skills", skillName, "SKILL.md")];
109
+ }
81
110
  async function installSubagentsForAvailableCli(options = {}) {
82
111
  const repoRoot = options.repoRoot ?? path.resolve(__dirname, "..", "..", "..");
83
112
  const homeDir = options.homeDir ?? os.homedir();
@@ -111,15 +140,18 @@ async function installSubagentsForAvailableCli(options = {}) {
111
140
  }
112
141
  }
113
142
  const codexPath = which("codex");
114
- if (!codexPath) {
115
- notes.push("codex CLI not found; skipping subagent install");
143
+ if (!codexPath && !hasOpenAiSkillHome(homeDir)) {
144
+ notes.push("codex CLI/config not found; skipping subagent install");
116
145
  }
117
146
  else {
118
- const codexSkillsDir = path.join(homeDir, ".codex", "skills");
119
147
  for (const source of sources) {
120
- const skillName = path.basename(source, ".md");
121
- const target = path.join(codexSkillsDir, skillName, "SKILL.md");
122
- if (ensureSymlink(source, target)) {
148
+ let installedForSkill = false;
149
+ for (const target of openAiSkillTargets(homeDir, source)) {
150
+ if (ensureHardLink(source, target)) {
151
+ installedForSkill = true;
152
+ }
153
+ }
154
+ if (installedForSkill) {
123
155
  codexInstalled += 1;
124
156
  }
125
157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.43",
3
+ "version": "0.1.0-alpha.44",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",
@@ -36,13 +36,39 @@ cp subagents/*.md ~/.claude/agents/
36
36
  ## Installing For Codex-Style Skills
37
37
 
38
38
  ```bash
39
- mkdir -p ~/.codex/skills/work-planner ~/.codex/skills/work-doer ~/.codex/skills/work-merger
40
- cp subagents/work-planner.md ~/.codex/skills/work-planner/SKILL.md
41
- cp subagents/work-doer.md ~/.codex/skills/work-doer/SKILL.md
42
- cp subagents/work-merger.md ~/.codex/skills/work-merger/SKILL.md
39
+ mkdir -p ~/.agents/skills/work-planner ~/.agents/skills/work-doer ~/.agents/skills/work-merger
40
+
41
+ # Hard-link to keep one source of truth
42
+ ln -f "$(pwd)/subagents/work-planner.md" ~/.agents/skills/work-planner/SKILL.md
43
+ ln -f "$(pwd)/subagents/work-doer.md" ~/.agents/skills/work-doer/SKILL.md
44
+ ln -f "$(pwd)/subagents/work-merger.md" ~/.agents/skills/work-merger/SKILL.md
43
45
  ```
44
46
 
45
- If you prefer symlinks or hard-links, that is fine too, but plain copies are easier to reason about and easier to repair when editors replace files.
47
+ **Important:** For Codex/OpenAI skill installs, use the generic `~/.agents/skills` root and use hard links (`ln`, not `ln -s`). Installing the same skill into both `~/.agents/skills` and `~/.codex/skills` can produce duplicate entries in Codex. Symlinked `SKILL.md` files may load but are not advertised reliably by Codex surfaces. Hard-links break when editors save by replacing the file (new inode). After editing any `subagents/*.md` file, re-run the `ln -f` command for that file to restore the link. You can verify with `stat -f '%i'` — both files should share the same inode.
48
+
49
+ Optional UI metadata:
50
+
51
+ ```bash
52
+ mkdir -p ~/.agents/skills/work-planner/agents ~/.agents/skills/work-doer/agents ~/.agents/skills/work-merger/agents
53
+ cat > ~/.agents/skills/work-planner/agents/openai.yaml << 'EOF'
54
+ interface:
55
+ display_name: "Work Planner"
56
+ short_description: "Create and gate planning/doing task docs"
57
+ default_prompt: "Use $work-planner to create or update a planning doc, then stop at NEEDS_REVIEW."
58
+ EOF
59
+ cat > ~/.agents/skills/work-doer/agents/openai.yaml << 'EOF'
60
+ interface:
61
+ display_name: "Work Doer"
62
+ short_description: "Execute approved doing docs with strict TDD"
63
+ default_prompt: "Use $work-doer to execute an approved doing doc unit by unit."
64
+ EOF
65
+ cat > ~/.agents/skills/work-merger/agents/openai.yaml << 'EOF'
66
+ interface:
67
+ display_name: "Work Merger"
68
+ short_description: "Merge feature branch into main via PR after work-doer completes"
69
+ default_prompt: "Use $work-merger to merge the current feature branch into main."
70
+ EOF
71
+ ```
46
72
 
47
73
  ## Keeping Local Skill Copies Fresh
48
74
 
@@ -51,8 +77,8 @@ After editing any `subagents/*.md` file, resync your local installed copies.
51
77
  The repo workflow usually checks this with diffs like:
52
78
 
53
79
  ```bash
54
- diff -q ~/.codex/skills/work-planner/SKILL.md subagents/work-planner.md
55
- diff -q ~/.codex/skills/work-doer/SKILL.md subagents/work-doer.md
80
+ diff -q ~/.agents/skills/work-planner/SKILL.md subagents/work-planner.md
81
+ diff -q ~/.agents/skills/work-doer/SKILL.md subagents/work-doer.md
56
82
  ```
57
83
 
58
84
  ## Restart Behavior