flow init: install SKILL.md to Codex / Cursor / Gemini skill dirs#45
flow init: install SKILL.md to Codex / Cursor / Gemini skill dirs#45vishnukv-facets wants to merge 3 commits into
Conversation
…w init `flow init`, `flow skill install`, `flow skill update`, `flow skill uninstall`, and `maybeAutoUpgradeSkill` now operate over a list of per-agent install targets instead of the single hard-coded `~/.claude/skills/flow/`. Claude stays always-on; Codex, Cursor, and Gemini are auto-discovered by checking whether their `~/.<agent>/` parent dir exists. SessionStart hook installation stays Claude-only. Why: the installed flow skill already documents Codex behavior, but the binary only writes to ~/.claude/. Filling Codex/Cursor/Gemini skill dirs is the minimum change required for those agents to discover and load the flow skill — no `flow do` runtime changes, no DB schema work, no agent dispatch. Auto-discover means we never pollute home dirs for agents the user doesn't have installed. Implementation: - `skillTargetCandidates` enumerates the four known agents (Claude, Codex, Cursor, Gemini); `skillTargets()` filters to those whose parent dir is present. - Per-agent VERSION sidecars at `~/.<agent>/skills/flow/VERSION` let auto-upgrade refresh each agent independently. - Install is batch-or-nothing: if any target SKILL.md already exists, plain `install` refuses without `--force` — one mental model, no partially-installed states. - Uninstall iterates the candidate list (not the live target set) so we still clean up if an agent's home dir was removed between install and uninstall. Tests: 8 new tests in skill_test.go cover discovery, multi-target install, absent-agent skipping, batch-or-nothing refusal, update overwrite, uninstall sweep, and auto-upgrade refresh. Closes #43 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… to Codex limit Gemini CLI scans both `~/.gemini/skills/` and the shared `~/.agents/skills/` root, so installing into both double-loads the skill. Redirect Gemini's install target to `~/.agents/skills/flow/` only. Presence detection still keys on `~/.gemini/` — we only install to the shared root when the user actually has Gemini installed. Implementation: - skillTarget gains separate `presenceSubdir` (existence check) and `installSubdir` (where SKILL.md goes). For every agent except Gemini these are the same. Gemini's install lands at `.agents/`. - New `resolvedSkillTarget` carries absolute paths after $HOME is resolved so call sites don't recompute. - Uninstall iterates candidates using the install path, so the Gemini cleanup happens under `~/.agents/skills/flow/` not `~/.gemini/`. Codex frontmatter limit: a paired change in this commit trims the embedded SKILL.md's `description:` block to fit Codex's 1024-byte limit. `TestSkillFrontmatterDescriptionFitsCodexLimit` pins the invariant — both the trim and the test are needed for Codex to load the skill at all. Tests: - TestGeminiInstallsToAgentsRoot: presence-only Gemini lands at ~/.agents/, never under ~/.gemini/skills/. - TestSkillInstallWritesAllAgentTargets updated to assert Gemini install path = ~/.agents/skills/flow/SKILL.md and the negative property that ~/.gemini/skills/ stays empty. - TestSkillInstallSkipsAbsentAgents: ~/.agents is NOT auto-created when Gemini isn't present. - Update/Uninstall/AutoUpgrade tests use the right install dirs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
One design pushback before going deeper — the agent-detection logic and the auto-upgrade behavior compose into a papercut worth fixing in this PR. Current behavior:
Combined effect: if a user runs Proposal: drop detection entirely. Install all four locations always, on both Why this is fine:
The one real cost is pre-creating
Net trade: install + auto-upgrade are seamless, the discovery code disappears, and the post-install-agent gap closes. Worth flipping before merge IMO — happy to discuss if there's a constraint I'm missing. |
…nstall opt-out maybeAutoUpgradeSkill used to treat a missing SKILL.md as "user opted out" and never reinstall — fine when Claude was the only target, but under multi-agent it meant installing Codex (or any other CLI) after flow init left ~/.codex/skills/flow/ empty until the user manually ran flow skill install --force. Anshul flagged this on PR #45. Treat missing SKILL.md as "needs install" instead. The legitimate opt-out case is now expressed by a ~/.flow/.skill-uninstalled marker that flow skill uninstall drops on success and flow skill install / flow init clear. A fresh-binary safety gate (flowEngagementDetected) keeps the first run of an unconfigured binary from silently creating SKILL.md before the user runs flow init. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Good catch — gap is real and worth fixing. Pushed 1ac5a44. Took the diagnosis but not the full prescription. Going wider on the trigger (treat missing SKILL.md as "install it"), keeping presence-based discovery for the targets. Reasoning: pre-creating What changed in
Net effect: install Codex three weeks after Tests: 4 new ( |
Summary
flow init/flow skill install/flow skill update/flow skill uninstall/maybeAutoUpgradeSkillnow operate over a list of per-agent install targets instead of the single hard-coded~/.claude/skills/flow/. Claude stays always-on; Codex, Cursor, and Gemini are auto-discovered when their parent home dirs exist on disk.Gemini specifically installs to
~/.agents/skills/flow/(not~/.gemini/skills/) because Gemini CLI scans both the shared~/.agents/skills/root and its per-agent dir — writing to both would double-load the skill.Why
The shipped SKILL.md already documents Codex behavior, but the binary only writes to
~/.claude/. Other agents support the same SKILL.md format via their ownskills/dirs and the shared~/.agents/skills/root. Filling those dirs is the minimum change required for those IDEs to discover and load the flow skill — noflow doruntime changes, no DB schema work, no agent-dispatch logic.Implementation
skillTargetseparatespresenceSubdir(existence check) frominstallSubdir(where SKILL.md goes). Identical for Claude/Codex/Cursor; Gemini's presence dir is~/.gemini/but install dir is~/.agents/.skillTargets()discovers live targets at runtime. Claude is always included (preserves legacy behavior); others are auto-discovered. We never eagerly create~/.<agent>/for agents the user doesn't have.VERSIONsidecars (~/.<install-dir>/skills/flow/VERSION) so each agent upgrades independently.installrefuses without--force. One mental model, no partial-install states.installSessionStartHookstays Claude-only — other agents have their own hook mechanisms (or none), out of scope here.description:frontmatter block so Codex will actually load the skill.TestSkillFrontmatterDescriptionFitsCodexLimitpins the invariant.What's intentionally out of scope
flow do --agent <codex|opencode|...>runtime dispatch — partially built on unmergedfacets/codex-supportbranch, separate work.session_providerDB column.SessionStart.~/.opencode/layout (node bin tree) doesn't match the global-skills-dir pattern; revisit if opencode adopts one.Test plan
make testpasses (all packages, including 10 new tests ininternal/app/skill_test.go):TestSkillTargetsClaudeAlwaysPresent— Claude always in the listTestSkillTargetsDiscoversInstalledAgents— Codex/Cursor/Gemini auto-discovered when their presence dirs existTestSkillInstallWritesAllAgentTargets— install lands in all 4 dirs; Gemini lands at~/.agents/, not~/.gemini/skills/TestSkillInstallSkipsAbsentAgents—~/.cursor,~/.gemini,~/.agentsNOT auto-created when their presence dirs are missingTestGeminiInstallsToAgentsRoot— Gemini redirect in isolationTestSkillInstallRefusesIfAnyTargetExists— batch-or-nothing safetyTestSkillUpdateOverwritesAllAgents—updaterefreshes everywhereTestSkillUninstallRemovesAllAgents— uninstall sweeps all agentsTestMaybeAutoUpgradeRefreshesAllAgents— version mismatch refreshes every targetTestSkillFrontmatterDescriptionFitsCodexLimit— Codex 1024-byte description limit\$HOME:~/.agents/)~/.codex/present → install to Claude + Codex;~/.cursor,~/.gemini,~/.agentsNOT created~/.gemini/present → install to Claude +~/.agents/;~/.gemini/skills/stays emptyCloses #43
🤖 Generated with Claude Code