* test(ok): reproduce PRD-8343 phantom re-projection * fix(ok): make cross-scope skill moves truthful * test(ok): reproduce PRD-8343 warning-code skew * fix(ok): align imported skill warning codes * test(ok): reproduce PRD-8343 ignored install mode * fix(ok): reject unscoped install modes * chore(ok): add PRD-8343 changeset * fix(ok): route MCP cross-scope skill moves through move-scope, plumb warning codes everywhere Review follow-up for the PRD-8343 skill lifecycle PR. The MCP move tool now posts cross-level skill moves to POST /api/skill/move-scope, the same atomic endpoint the Skills Studio uses: the whole bundle moves, binary files included, the skills-lock entry transfers, and the prior editor hosts are re-projected. The endpoint accepts an optional toName so a renaming move lands directly under the new name with its SKILL.md name patched; nothing is written when that name is taken at the destination. The hand-composed PUT/PUT/DELETE path and its skippedBinaryFiles and bothScopes output fields are gone, and the tool prose goes back to describing re-projection truthfully. warningCodes now ships on PUT /api/skill, POST /api/skill/reimport and both bulk result schemas, aligned 1:1 with warnings, under SKILL_AUTHORING_WARNING_CODES (named for the shared writer that mints them). PUT /api/skill no longer returns each warning twice on create. The MCP write tool exposes warnings and warningCodes in its structured skill payload. install documents the mode-needs-add-or-convert refusal in both the description and the field text, and runs both argument-pair guards before contacting the server. Tests: two-warning ordering cases in skills-write and import, a move.test.ts covering skill dispatch, and integration tests for the MCP move (hosts, binaries, lock entry, rename collisions) and for warning codes across every entry point. The changeset names @inkeep/open-knowledge so the note reaches the docs changelog. * fix(PRD-8343): preserve skill recovery copies and close review gaps * fix(PRD-8343): report partial skill moves and align warning contracts * fix(PRD-8343): report unknown source loss and mirror bundle-file failures The source-intactness probe on the retained-copy branch called parseSkillDir without a guard, on the one branch that only runs after rmSync just threw a permission error on that same tree, so a bundle subdirectory that blocks both walks sent the request to the outer catch and replaced moveState destination-retained with partially-applied, losing the pointer to the recovery copy. Its fallback arm also checked one file and then selected the detail that asserts nothing was lost. It is now a three-state intact/lossy/unknown probe behind a try, and unknown gets its own wording that claims nothing. MCP write's combined SKILL.md-plus-bundle-files result spread the inner writeSkill text over the composed body, so on clients that hide content[] a per-file failure was invisible beside isError true. handleSkillDuplicate discarded both applySkillDelete cleanup results, reporting a clean 400 while a stray copy stayed on disk. The changeset said moveState rides every failure after the copy, which excludes nothing-written, the first code in its own list. * fix(PRD-8343): pass the source scope when checking unprojectable skill hosts Main made resolvedHosts scope-aware so global-scope hosts resolve against USER_SKILL_EDITOR_IDS. The unprojectable helper added on this branch still called it with one argument, which broke the merged tree that CI builds and turned every Open Knowledge check red. The helper only ever inspects source-side hosts, so fromScope is the scope its siblings already pass. * fix(PRD-8343): make the move-scope machine-readable fields describe what they report droppedLocations no longer mixes bundle directories into a list of install location ids. The placement-ledger term added nothing correct: knownSkillRootsFor already registers each recorded root as a pseudo-host, so the two unprojectable terms cover the same ground in install vocabulary, while the ledger term contributed bundle paths including roots that get re-projected at the destination. The rendered install nudge now carries the destination scope and says custom roots resolve against the destination base, and the field rides every failure rather than only some. A retained destination copy is now marked on disk, so the retry it invites is refused as destination-retained-blocking and tells the caller to reconcile rather than delete what may be the only surviving copy of files a partial removal deleted. Readability could never discriminate that state because the pre-removal gate guarantees a readable SKILL.md. Every move-scope failure now routes through one failMove helper backed by an exhaustive touched-disk map, so a mistyped state cannot compile and settle runs in one place. The two name-validation refusals and the three cross-scope pre-flight refusals carry a state for the first time, and the outer catch reports nothing-written when it fires before the first write instead of claiming partial damage. alignWarningCodes keeps the warning text when a peer sends codes it cannot pair, so an empty warningCodes means what its description says it means. The Skills Studio client parses droppedLocations and moveState instead of discarding them, and refreshes on the transport failure path. * fix(PRD-8343): extract move-scope identity first and report source state structurally Hoist extractActorIdentity to the first statement of handleSkillMoveScope. The failMove closure containing errorResponse was declared ahead of it, and the attribution sweep scans handler bodies textually, so a handler whose runtime ordering already satisfied precedent 24 still read as a violation. Report the post-removal source condition as a structured sourceState member (intact, lossy, unknown) beside moveState, so a caller can tell a disposable duplicate from a copy that may hold the only surviving files without matching on English. The unknown arm no longer asserts a read failure it did not observe, and the rescan error is chained into the cause instead of discarded. Give failCopiedDuplicate the policy its model already had: cache invalidation through a handler-local settle on both paths, an explicit error log level, and the frontmatter diagnostic rather than a bare error kind. Cover the 400 arm with a malformed-frontmatter source. Scope the changeset claim to the failures the handler reports, since the transport-layer refusals emitted before it runs carry no code, and document sourceState there. Keep the bundled project skill under its 20,000-byte core-body gate. * fix(PRD-8343): scope the retained-destination record and close the move-scope refusal gaps Round 6's work was written but never published, so round 7 re-verified against a HEAD that did not contain it. It lands here together with round 7's fixes. Retained destinations move from an in-directory marker to a ledger at .ok/local/skill-move-retained.json, and the 409 reads its sourceState, so an intact source now says "remove it, then retry" on both the 500 and the retry instead of contradicting itself. droppedLocations rides only the failures that actually dropped placements, unprojectable resolves against the destination scope, and alignWarningCodes keeps every warning while withholding only the codes it cannot pair. project/SKILL.md restores the two substrings validation-coverage-contract.test.ts pins verbatim, which was the cause of the red test:shard1, and restores the two facts the cross-level clause had dropped. The bytes came from four filler cuts in the Reads/Writes bullets; body is 19,994 of 20,000. extractActorIdentity gets its own recovery boundary in handleSkillMoveScope so the last refusal without a moveState now carries one, and handleSkillDuplicate's outer catch can reach settle() and reports the copy it left behind. * fix(PRD-8343): derive the cross-level move split from what the destination can host Round 8 review fixes. The intact verdict now reads the same on the server and on the two client surfaces that used to assert a deletion policy without consulting sourceState: skills-api threads sourceState through MoveSkillScopeResult and splits the retained-copy toast into a remove-and-retry arm for intact and the protective arm otherwise, gated by an exhaustive Record over SkillMoveStateCode. That toast now carries a stable id and no timer, so the one message in the flow whose content is destructive if ignored no longer auto-dismisses. The retained-destination ledger gains a three-state read, so an unreadable file is no longer indistinguishable from an absent one: the write path refuses to rewrite a ledger it could not read rather than replacing every record it holds, and the 409 grows an arm that says it cannot tell whether the occupant is a retained copy instead of advising deletion. Each record binds to the content hash of the copy it describes, so a record whose copy was replaced no longer vouches for the replacement, and it is cleared on skill delete and on hash mismatch as well as on a completed move. The store takes scope and name rather than a pre-composed key, derives its path from getLocalDir, and writes through tracedAtomicFs, now hosted in fs-traced beside the wrappers it composes. droppedLocations reports what the sweep actually removed rather than what was predicted, so a source-removal failure no longer reports an empty list for placements it has already deleted. All seven copies of the cross-level claim now derive the split from what the destination level can host, and the move success text splits its remedy three ways: an install call for placeable locations, the agents-hub equivalent for an editor that reads the hub at that level, and an explicit no-placement-exists for one that does not. A lockstep test pins the claim across every surface that states it. alignWarningCodes renders a non-string warning as text instead of dropping it, and a non-array warnings payload now yields one explicit unverified warning rather than a code-paired all-clear. write, edit, import and install share the warning contract text, and the three tools that were rendering the raw server warnings instead of the normalized ones now render the normalized ones. The duplicate handler splits its disk flag in two, so a mid-copy throw still settles and the disclosure says the copy may be incomplete rather than claiming a complete one. The two name refusals emit droppedLocations, and the new disk artifact is listed on the page that promises to list every one. * test(PRD-8343): pin droppedLocations on the two move-scope name refusals The transport test's destination-retained body carried an agents entry, a value that state cannot produce: agents resolves at both levels, so unprojectable filters it out of droppedLocations. Retargeted to lm-studio, which the state does produce, keeping the non-string coercion the test is actually about. * fix(PRD-8343): give the retention ledger a consumer and stop unreadable reading as mismatch The unreadable-ledger state added last round reached neither the move tool nor the Studio, so a caller saw moveState nothing-written glossed as a safe retry. Declare retentionLedger on move's outputSchema, forward it through the skill-target adapter, and back both copies with SKILL_RETENTION_LEDGER_CODES plus an isSkillRetentionLedgerCode guard in core so the third copy is not hand-rolled. skillContentHash returned the empty string for three different facts, so an occupant that could not be read was treated as an occupant that did not match: the record was cleared and the delete-it advice printed. readSkillContentHash now returns a two-arm result, the gate clears only on a proven mismatch, and an unverifiable occupant emits retentionLedger occupant-unverifiable with the same no-delete wording the unreadable ledger already gets. The write side treats an unhashable destination as a retention-record failure rather than persisting a record that can never match. droppedLocations carried a description written for the success arm whose remedy is harmful on a failure and whose opening clause contradicted its own third sentence. Rewrite it to split success from failure, report the sweep unfiltered on the failure arm, and widen the lockstep regex to admit "place". Also: parameterize the warnings-field contract so import stops hand-copying it, read the ledger before skill-delete clears it and on a same-scope rename collision, and split skill-duplicate's post-mkdir flag so the "inspect or remove it" detail cannot name a directory that was never created. * fix(PRD-8343): surface the unverifiable-occupant warning in the Studio skillMoveRetainedCopyToast gated on MOVE_SCOPE_RETAINED_DESTINATION, which maps nothing-written to false, so both retention-ledger states returned undefined and the human saw a bare name-collision message with none of the server's do-not-delete caution. Parse retentionLedger off the error body and branch on it before the moveState lookup, so the two cases stay separate from the genuinely safe nothing-written arm. Raise visibleToasts to 6: the retained-copy toasts now never expire, and a bulk move raises one per failed skill, so past sonner's default cap of 3 the earliest warnings stacked behind the visible three indefinitely. Name all three paths that clear a retention record in the two docs rows that promise completeness, not just the completed-move one. * fix(PRD-8343): give droppedLocations one meaning and stop advising deletion of unread occupants The success-semantics droppedLocations was reassigned above two failure exits that still emitted it, so destination-unreadable and partially-applied shipped the destination-unhostable set under a clause asserting the skill did not move. The reassignment is gone and the success response passes the value directly, so the variable holds the source-side sweep on every path failMove can reach. The tool description now reads the split off moveState rather than off success. describeRetainedOccupant returned detail undefined for a destination the server could not read, and the call site fell through to "Delete or rename it first" on a signal the delta computed one line above and never consulted. It now returns a verdict discriminant. The call site derives one conditional spread from it, and unreadableOccupant retires. The new arm distinguishes an absent directory from an unreadable one, because a skill resolved at a non-default host root also reads as not-ok and must stay an ordinary collision. readSkillContentHash reported the stringified fs exception, which embeds the absolute path, into a caller-visible detail on two endpoints. It now reports the errno code and carries the error as a cause for the log. Same for the ledger store. The unrecorded-retention note branches on whether the copy was readable, so it stops implying a copy is safe to recover from when hashing just failed. The skill-delete loss log gated on a bare key match, so reconciling a retained copy in place left a record that still matched by key and reported lost files that were recovered. It now requires a proven hash match, carries the requestId, and logs at error like its sibling. The rename collision clears a proven-stale record and renders its detail through errorTextWithDetail, which the same-scope MCP adapter previously discarded. * fix(PRD-8343): drain the retained-copy toasts and carry the failure split into the docs The retained-copy toast is the only duration Infinity toast in the app with a per-entity id and no dismisser, so a bulk move failing on N skills left N toasts mounted for the rest of the session. Raising visibleToasts widened the window without draining the stack, because sonner keeps toasts past the ceiling mounted rather than removing them. The id is now single-sourced and both moveSkillScope success arms dismiss the record's toast, so the population is bounded by the lifecycle rather than by the visible window. The visibleToasts override this branch added is reverted, since it was an app-wide knob for four unrelated persistent notices. The dom test that pins this hook's toast guidance drove moveState and sourceState but never retentionLedger, so the composition point that carries the field to a user was the one tier with no coverage. It is pinned now, and deleting the wiring line reds it. The changeset and both docs pages stated the droppedLocations re-add advice unconditionally, which is only true on a success. Each gains the failure caveat as an appended sentence. The changeset also names retentionLedger, its two codes and the core exports, so an integrator stops reading nothing-written on a 409 as an ordinary safely-retryable collision. One unrelated repair: the skill scope move dialog test mocks the skills api module totally, so adding an export made the hook throw while every test still reported passing and vitest exited 1. * fix(PRD-8343): finish the deferred skill-lifecycle backlog and the round-11 review Closes the eight pending recommendations plus the nine findings from review 5157621497, in one batch. NOT TESTED: at the user's explicit instruction nothing was executed for this batch, and both the commit and the push skip verification. Server and core: - readSkillContentHash returns a four-arm discriminated union, so a destination directory the server read successfully and found has no SKILL.md gets its own stray-occupant verdict and no longer ships retentionLedger. That code now means only "the ledger could not be read" or "the occupant could not be read". - The verdict to wire-code mapping is an exhaustive Record, so a new verdict kind cannot silently degrade a refusal into a bare nothing-written. - The retained-destination ledger read carries its cause through to both 409 sites, and the schema-mismatch reason no longer stringifies unvalidated file content. - DELETE /api/skill reads the ledger before hashing, so an ordinary delete no longer walks and hashes the whole bundle for a diagnostic that cannot fire. The delete log gained an unverifiable arm, and the success response carries a bounded warnings entry when it removed a proven retained recovery copy. - failMove takes a discriminated producer union, and the collision callsite builds a whole outcome per verdict rather than casting independent optionals. - Cross-scope moves record one bounded outcome metric per invocation and one structured outcome log on the response's own problem instance. Per-line UUID minting is gone. commitOkArtifactWrite reports flushed, unavailable or failed, and the deferred branch now says only that this move did not establish its Revert baseline, naming the destination rather than the old name. - describeFmEditError moved to its own module with all eight arms table-tested. - The four settle effects are one hoisted helper, and the three copy-then-patch name sites share applySkillDirNameSync, which writes through temp and rename. MCP and the agent contract: - CROSS_LEVEL_TRANSFER_CLAUSE carries the success/failure split, so the tool description, both input describes and the crossScope text stop telling an agent to install droppedLocations at the destination on a failure. The project SKILL.md router bullet says the same. A companion assertion pins the split across every surface that states the remedy. - The retentionLedger absence clause is scoped to the destination collision it is actually about, instead of contradicting moveState's own describe six lines up. - deleteSkill threads warnings into both the text and structuredContent, and moveSkillCrossScope decodes failures through the shared tolerant reader. Studio: - The retained-copy toast drains from the transport functions that own its id, so a delete clears it the same way the server clears the record. The caller-side obligation and its export are gone. - A bulk move now emits one truthful aggregate naming every affected skill with conservative recovery advice, and suppresses the unqualified success toast. - Both delete dialogs render successful-deletion warnings, per skill in bulk. - Move failures decode through interpretSkillMoveFailure, so a contradictory or incomplete peer result stays cautionary and can never produce remove-it advice. Sibling stores refuse to persist over a file that exists but cannot be read, rather than replacing every record it held. Reads stay fail-soft. The fs-copy observer runs the caller's predicate before consuming its one-shot latch, so an unrelated copy can no longer steal the slot. * fix(PRD-8343): give the presence marker a reader and gate the whole unverified triple The presence-exempt marker moved to content/skills-write.ts with the applyPatchToFm call it exempts, but its registered reader still scanned only api-extension.ts, so guard-marker-readers.test.mjs reported it unread and the lint job went red. Widen both halves together: the registry scans skills-write.ts, and the presence guard derives its expected count from both files. Removing the marker now fails the guard again, which is what makes it load-bearing rather than decorative. The MCP cross-scope move adapter gated only sourceState on a coherent outcome, so the unverified arm still shipped moveState and retentionLedger, a field combination the tool's own output schema documents as impossible. Gate all three, and pin the withholding. * fix(PRD-8343): supply warningCodes on the relocated skill success payloads The branch made warningCodes a required member of SkillPutSuccessSchema and SkillReimportSuccessSchema. PRD-8403 relocated those handlers to src/http before that landed, so their success payloads omit it: successResponse fails its own schema validation and answers 500 with no cause and no detail. The merge typechecked because the payload object is only checked against the schema at runtime. PUT /api/skill and the reimport up-to-date path now carry it, matching the warnings expression each site already uses. SkillRevertSuccessSchema and the two template schemas do not declare warningCodes, so their payloads are unchanged. Fixes the 8 failures across api-skill-document-composition, api-skill-file-composition, api-skill-recovery-composition and api-skills-native-preservation, all of which pass on main. * test(PRD-8343): supply the required outcome in the failed-move mock MoveSkillScopeResult's failure arm declares outcome as required, and useMoveSkillScope passes it straight to skillMoveRetainedCopyToast, which reads outcome.kind. The release-the-write-flag test mocked a failure without it, so the hook threw TypeError before reaching the assertion. Its sibling at :119 already supplies outcome via interpretSkillMoveFailure; this mock now does the same. The other 51 test:dom failures on this head are in DocumentContext.dom.test.ts and reproduce on origin/main, so they are not this branch's. * fix(PRD-8343): re-apply delete, rename and duplicate onto the relocated routes The origin/main merge ported handleSkillMoveScope into skills-document-routes but took main's side for the other three handlers, which are the pre-PR versions. 119 lines of this branch's work went with them: handleSkillDelete lost its warnings member and its clearSkillMoveRetention call, handleSkillMove lost the same retention cleanup, and handleSkillDuplicate lost its collision handling. Under the re-projection behaviour this branch implements, that cleanup is load-bearing rather than cosmetic: a retention record left behind by a delete is read by the later collision path as a real retained copy whose occupant is now absent. invalidateSkillCatalog joins settleSkillCatalog as a threaded dependency rather than a local reimplementation, for the same reason as before — the real one also refreshes the content filter and schedules the ignore rebuild. * fix(PRD-8343): drop the imports the handler port left unused applySkillDirNameSync and tracedWriteFileSync lost their last callers in skills-document-routes when the three handlers came across, and biome's noUnusedImports is error-on-warnings in the lint gate. * fix(PRD-8343): recover the dropped round-12 work and stop the create double-count Recovers the in-flight work from the iteration this branch lost, rebased onto the relocated route modules, and closes the Critical the last round raised against the merge. The create branch of skill-put no longer concatenates composed and writer warnings. 82607df0b had already fixed that double-count; main's relocation reintroduced it in warnings, and the earlier warningCodes repair on this branch mirrored the concat instead of noticing, so every authoring warning and its code were counted twice on create. wr already carries the composed warnings. Bookkeeping that runs after the destructive step no longer converts a completed operation into a 500. Delete guards uninstallSkillFromHostDirs; rename guards rekeySkillLockEntry, removeSkillInstall and recordSkillInstall. Each failure logs and adds a warning to the success response, which is what the caller can act on: the content change landed, only its records did not. Also recovered: the cause field on the three .ok/local store readers that dropped it, the retained-destination classification collapsed into one exhaustive Record in core, the flat wire fields dropped from MoveSkillScopeResult's failure arm in favour of outcome alone, the batch retained-copy toast drain, the delete-time unverifiable warning arm, and the move.ts errors clause. api-skill-store-refusal.test.ts arrives with this work and is honest about what remains: 8 of its 11 cases pass. The three still red cover the cross-scope move guard, the retained-slot-unverifiable verdict, and the within-level rename collision wording. * fix(PRD-8343): close the remaining move-scope and warning-contract findings The store-throws finding is now closed at all three call sites. The cross-scope move guards its post-move bookkeeping the way delete and rename already did, so a completed move whose records could not be written answers 200 with a warning rather than reporting itself partially applied. describeRetainedOccupant no longer describes a directory it read as one it could not read. The undiscriminated `record !== null && !occupant.ok` arm now lets `no-manifest` through to its own arm first, which is what gives `retained-slot-unverifiable` a producer; both still resolve to the `occupant-unverifiable` ledger code, so the wire contract is unchanged. The collision detail no longer names an operation the caller did not invoke: a within-level rename refused on an unreadable occupant said "a cross-scope move will not overwrite it". The paired expectation in skill-mcp-move.test.ts moves with it. SkillMoveFailureOutcome's `unverified` arm now forbids the three fields the adapter already withholds on it, so the type no longer permits a combination the code excludes by hand, and moveState's describe no longer opens by promising presence on every failure two sentences before saying when it is withheld. UNREADABLE_WARNINGS_TEXT ships from core and the MCP copy re-exports it; the duplication was recorded as forced by a boundary the same file already crosses. The changeset records the two behaviour changes it was missing: the stores refusing to rewrite what they could not read, and the `warnings` member that refusal made necessary on delete, rename and move-scope. mcp.mdx's advisory- warnings section names `delete`, `move` and `install` on a skill target and says how their plain-string warnings differ from the kind-discriminated ones. api-skill-store-refusal.test.ts is 11/11. * fix(PRD-8343): close the remaining minors and considers The move-scope counter and its structured log now emit from one place, so a terminal path cannot record one without the other. The four that recorded only the counter — the actor-identity failure, the two name refusals, and the success path — carry their context through it; failMove hands in the instance, status and dropped-location count it used to log separately. The bulk delete dialog's per-skill warning rows are a list rather than spans in a flex div. Stale SKILL.md.tmp.<pid>.<ms> siblings are swept before each atomic write rather than only unlinked on a failure that returns. A crash between write and rename previously left one inside the hashed bundle, where it counts as a bundle file. All three writers in skills-write share the sweep, not just the rename path the finding named. The marker registry asserts that its presence-exempt scan set and the reader that models it name the same files. They were computed independently, so a file added to one and not the other left the marker unread with nothing failing. Not done, deliberately: - successResponse taking `schema: z.ZodType, body: unknown` as unrelated parameters is a real finding — it is what let this branch ship a body missing a required member as a runtime 500. Typing body as z.input<S> reds 41 call sites across the server, none of them this branch's. That is its own change. - skill-mcp-move.test.ts's lossy ternary still has its hash-mismatch half unfixtured. Reaching it through the HTTP surface needs a partial delete that leaves SKILL.md but removes a sibling, which depends on unlink ordering the test cannot pin; and both halves report the same sourceState, so the fixture would not distinguish them anyway. It wants a unit test of the computation. * fix(PRD-8343): give the rename collision the next step its sibling states The same-scope rename 409 dropped `detail` entirely on the ordinary collision, because describeRetainedOccupant returns undefined for exactly the plain-collision verdict. The response was a bare "already exists" with no next step, while the move-scope 409 consuming the same classifier falls back to 'Delete or rename it first; this move will not overwrite it.' The rename now uses the same fallback. * revert(PRD-8343): let an unverified outcome keep the values it decoded Narrowing SkillMoveFailureOutcome's unverified arm to forbid the three fields over-applied the review finding. The withholding it names happens in the MCP adapter, which gates emission on `coherent`; interpretSkillMoveFailure is the reader, and it deliberately keeps what the server actually said so a caller can see it while treating the triple as untrustworthy. skills-api.move-scope.dom.test.ts pins that: a body carrying `moveState: destination-retained` with no `sourceState` is incoherent, and the decoded moveState survives on the unverified outcome. Dropping it made the client discard the one diagnostic it had. moveState's describe keeps its correction — it no longer promises presence two sentences before saying when the adapter withholds. --------- GitOrigin-RevId: a076209864d4f81082b52ce51274c2777deae359
Open Knowledge Skills
Agent Skills published by Open Knowledge. Each skill teaches an agent one repeatable task, and every one of them is plain markdown you can read before you install it.
skills/ is generated. The skills there are projected from the Open Knowledge source
tree, so each skill directory's leaf name matches its SKILL.md frontmatter name.
The layout groups by role:
skills/core/holds the platform and meta skills.skills/starter-packs/<pack>/holds one folder per starter pack: the pack's orientation skill, its member skills as sibling directories, and a README explaining how they interact.
Install
Add this repository as a Claude Code plugin marketplace, then install what you want:
/plugin marketplace add inkeep/open-knowledge-skills
/plugin install open-knowledge@open-knowledge-skills
open-knowledge is the platform skill: it teaches an agent to read, search, link, and
write markdown through Open Knowledge's MCP server. The rest are optional packs.
What's published here
Install a pack by name, the same way: /plugin install <pack>@open-knowledge-skills.
Core
| Skill | What it does |
|---|---|
open-knowledge |
The runtime contract for working inside an Open Knowledge project: reading, searching, linking, and writing markdown through its MCP server. |
open-knowledge-discovery |
What Open Knowledge is, how to install it on a repository, and how to share a project with collaborators. |
open-knowledge-write-skill |
Authoring a new Agent Skill: the frontmatter contract, progressive-disclosure structure, and how to install it into your editors. |
Starter packs
Each pack ships an orientation skill that explains how to work in that project shape. Some add task skills alongside it.
| Pack | Orientation skill | Also ships |
|---|---|---|
software-lifecycle |
proposals to decisions to specs to postmortems | frame-a-proposal, write-a-spec, record-a-decision, write-a-postmortem, review-a-design |
knowledge-base |
source-grounded research: sources to research to articles | research-with-sources, consolidate-notes |
codebase-wiki |
an agent-authored, source-grounded wiki of the surrounding codebase | |
personal-crm |
a typed-entity vault of people, companies, and meetings, each with a rewritable summary and an append-only timeline | |
note-taking |
a flat notes folder plus a daily journal, for when you just want to write | |
writing-workflow |
a three-stage drafting flow: ideas to drafts to published | |
worldbuilding |
a fiction encyclopedia of characters, settings, factions, and lore | |
okf-knowledge-base |
a knowledge base conformant with Google's Open Knowledge Format from the first commit |
The task skills stand on their own. write-a-spec and record-a-decision do not need an
Open Knowledge project, or the rest of their pack, to be useful.
You can also copy any skill straight into your agent's skills folder
(.claude/skills/, .cursor/skills/, .codex/skills/, or the vendor-neutral
.agents/skills/). Open Knowledge can install and update them for you, and keeps their
version history.
Writing your own
template/SKILL.md.example is a starting point. The field that matters most is
description: it is a routing rule, not a title, and it is what both skills.sh and the
host agent match on to decide whether to load the skill at all.
Read CONTRIBUTING.md before opening a PR.
License
okf plugin…; open-knowledge-write-skill: Use when the user wants to create, author, write, or design a new Agent Skill (a SKILL.md) — for OpenKnowledge or…