cyber-uni/cyber-agentkit
An agent-harness-agnostic toolkit: the fundamental features agent tools need, working the same on every harness. Detect the running harness, check plugin dependencies, resolve layered reference documents, and lease git worktrees.
cyber-agentkit
1.0.0
Major Changes
- 0cba7aa: Bump to 1.0.0 release
Minor Changes
-
8055a97: Add the plugin dependency domain.
declaredPluginDependenciesandreadPluginDependenciesread thedependenciesa Claude Codeplugin.jsondeclares.checkPluginDependencies(harness, { pluginRoot })reports each asenabled,installed,disabled,missing, orunknownusinginstalledPluginsandenabledPlugins, and returns install steps: Claude Code's own commands, or manual steps on every harness without a dependency field, with a note that nothing is resolved for you.The package now ships a
plugin-dependenciesreference, generated from the same facts, that thereferenceskill loads. -
8f9e83a: Add reference interfaces. An
<id>.interfacereference declares a contract in itsinterface:frontmatter: cardinality, version, accepted versions, and the implementation's top-level sections in order. Every section is optional, and an implementation may hold sections the interface does not list. A reference implements one interface withimplements: <id>@<version>.reference implementations <id> [--accept 1,2]lists the implementations a consumer can load, with each one's pin, description, and unsupported sections;--traceadds the ones left out, with why. The library exportsreferenceImplementations.reference check [name...]checks implementations, composed asshowcomposes them, and interface documents, and exits 1 on any failure. Itscomposecheck fails a document whose composing raised a warning. The library exportscheckReferences.showwarns when a document fails its interface check.reference create <id>.<key> --implements <id>starts an implementation from the interface's sections, each stubbed**Unsupported.**, withmerge: replace.- An interface document is never composed: a higher contribution of it, and an
extendsormergeon it, is ignored with a warning. - The
referenceskill loads the implementations of an interface, and creates and checks implementations.
-
5650ac4:
reference list,search, andcheckfind skills' defaults (<skill>/references/<name>.default.md) in the skill folders the detected harness reads: its project and user folders, its machine-wide admin folders, and each enabled plugin's skills, on Claude Code, Cursor, Codex, Copilot CLI, OpenCode, and Gemini CLI. A skill is known by itsSKILL.mdname, and symlinked skill folders are followed, so skills pnpm ornpx skillslinked are found.list --tracegives a row per skill holding a default, noting that thedefaultstep reaches it when that skill loads the name;searchandchecktake each default as its skill loads it, naming the skill asloadedBy. On another harness, or with none detected, the answer'sdefaultsfield says why no default is listed. The library exportsharnessSkillFolders,pluginSkillFolders,adminSkillFolders,skillsIn, andskillName. -
968bb1e: The
referenceskill follows the stack design. Load passes the calling skill's folder as--default, so a skill's defaults now live atreferences/<name>.default.mdand sit below every customization; it reads a default by itself only when the command cannot run, and no longer readsreferences/<name>.mdorgovernances/. On an ambiguous name with a user present, it lists every option, asks for a pick, and writes it withreference select. An invalid name is reported as a fault for the calling skill's author. A new Select mode chooses what a name builds on, and Update writes customizations that patch, instead ofmerge-sectionsoverrides. The load line reads "with thereferenceskill ofcyber-agentkit". -
f467991: Rebuild reference resolution around a stack. Breaking.
Contributions compose bottom first: the plugins and the calling skill's default (the stack), then user, then project, then managed. Each applies over everything below it with one of four operations, written as frontmatter
merge, on a step ofextends, or on one section as<!-- merge: <operation> -->:patch, the default: keeps what is below and puts each section's text in place of the text it matches by heading path. A file with nomergeused to befirst-winsand replace everything below; it now patches. Writemerge: replaceto keep the old behavior.combine: keeps what is below and adds each section's text after the text it matches. Lower text now comes first, and where combined text conflicts, the later (higher) text wins; the document says so once at the top. It used to put the higher layer first and let the first one win.replace: drops everything below.remove: drops everything below. With nothing above it, the name ismissing.
merge-sectionsandfirst-winsare gone (an unknownmergeis read aspatch, with a warning), and so isoverrides:. Frontmatterextendslists what a contribution builds on, bottom first: plugins by their manifest name, anddefault. The highest writtenextendsin the managed, project, or user tier builds the stack; otherwise the plugins' ownextendsorder them, and plugins nothing orders make the nameambiguous. A qualified<plugin>/<name>builds that plugin's own stack.- New
reference select <name> <option>... [--scope user] [--clear]writes theextendsthat settles an ambiguous name or picks a stack. - A skill ships its default as
<skill>/references/<name>.default.md;show --default <skill folder>(andwhere --default) reads it as thedefaulttier.createanddeletetake--plugin <plugin folder>and--default <skill folder>for a plugin's or a skill's source in the repository, andcreatetakes--merge <operation>. - Output is agent-first. In
--format json,showgives each found name's content as a string, and a record only for a failure or warnings;--metadataaddsstatusandmetadata(which leaves outmergeandextends), and--traceadds the trace.listgives one row per name (--traceadds the rows per layer).searchno longer echoes the query.checkgives the failures and a pass count.implementationsgives eachpin,description, andunsupported. Empty fields are left out. - Every warning is
{code, message}; a name not found carriesreference-missing,reference-ambiguous, orreference-invalid, and an ambiguous name's choices areoptions(wasplugins). In text, failures and warnings print aserror: <code>: <message>andwarning: <code>: <message>.<reference>blocks no longer carrytier.whereon an ambiguous name exits 0. - A bad name is a status (
invalid) in its own entry instead of an error that fails the whole call, and the library never throws for one. A name ending.default, or qualified by an npm package name, is invalid. - Only
<name>.mdand<name>/README.mdanswer a name;<name>/index.mdand<name>/SKILL.mdno longer do. The library's own managed folders (/etc/buddy-agent-harness/...and equivalents) and everygovernances/folder are no longer read. A dependency joins the plugin tier only when it has a plugin manifest, named by the manifest'sname.
-
13b64c2: Rename the package from
@cyberuni/agent-harnesstocyber-agentkit. Theagent-harnesscommand is nowcyber-agentkit, and thecyber-agent-harnessagent plugin is nowcyber-agentkit, so the skill is/cyber-agentkit:reference. The package is now described as an agent-harness-agnostic toolkit. Worktree leases written by the old name are no longer recognized as this library's own.
Patch Changes
- 238796e:
skillInvocation('codex', …)now returns$<plugin>:<skill>withnamespaced: true, instead of the bare$<skill>. Codex names a plugin's skill<plugin>:<skill>, and its$mention takes the whole name. - f58bc44: Point
repository,homepage, andbugsat the repository's new home,cyber-uni/cyber-agentkit(the package now lives atpackages/cyber-agentkit), and the documentation at https://cyber-uni.github.io/cyber-agentkit/. - 057b182:
skillInvocation('opencode', …)now returns/<skill>(not namespaced by plugin) instead ofundefined. Through v1.19.3, OpenCode registers every loaded skill as a slash command, unless a built-in, config command, or MCP prompt already has the name. - d89c33b:
skillsDirectories('cursor')adds.grok/skillsand lists Cursor's folders in the order it reads them.skillsDirectories('copilot-cli')gainsrelocatedBy: whenCOPILOT_HOMEnames another folder, Copilot CLI reads$COPILOT_HOME/skillsinstead of its user folders.
0.7.1
Patch Changes
- a64c02d: Declare
sideEffectsinpackage.jsonso bundlers can drop unused modules, including the bundledyamlparser. Only thebinlauncher, the CLI bundle, and the skill scripts are marked as having side effects.
0.7.0
Minor Changes
- 4730a5a: Moves to clibuilder 12.
@clibuilder/axiis gone, andclibuilderis the only optional peer, at^12.0.0.--formatis now clibuilder's global option, so a host that mountscreateReferenceCommandfrom./commandssets the default format withcli({ format }); thetextdefault ofshow,create, anddeletestays with theagent-harnessCLI. Thereferenceskill'sscripts/reference.mjsis now compiled byuniversal-plugin plugin buildfrom thescriptsentry inplugin.json, with noimport()left to resolve at runtime. - 1fc6f75:
releasenow clears the lock of a leased worktree whose directory is gone, sogit worktree prunecan take it: aLeaserecords its repo'scommonDirat claim.acquiretakes anundoCreatecallback, called when a slot its creator made loses the lease claim, so the creator's side effects (such as a herdr workspace) do not pile up across retries. - 006ca66:
reference listtakes an optional name pattern, such asproject-tracker.capabilities.*, andlistReferencestakes the samepatternoption. It returns only the names the pattern matches exactly, with tier, plugin, and ambiguity status, with no fuzziness or ranking. - 3bb29c9: The package no longer declares runtime
dependencies, so a consumer that imports only@cyberuni/agent-harness/worktrees(or the root entry) installs nothing beyond the package itself.yamlis now bundled intodist, and theagent-harnessbin bundlesclibuilderand@clibuilder/axi.clibuilderand@clibuilder/axibecome optional peer dependencies: install them (as a host CLI already does) to import@cyberuni/agent-harness/commands, which still composes into the host's ownclibuilderinstance. - 115f91c: Add
removeWorktreeto./worktrees: remove one caller-named worktree by path, with an explicitforcethat maps togit worktree remove --force. It returns the same outcome and skip reason aspruneWorktrees. It never removes the primary checkout or a leased worktree, and never kills a process.force: truewaives the foreign, prunable, dirty, and unmerged checks but still skips a busy worktree, or one whose process probe cannot be verified, with its reason.force: 'in-use'does everythingtruedoes and also removes busy and unverified worktrees, reporting the occupants. Unlike git's--force-with-lease(a safer force),'in-use'is the stronger one.
Patch Changes
- 79d05f0: The
referenceskill is now self-contained across install channels. Its bundledscripts/reference.mjsis committed, so a git-sourced install carries it, and the skill's fallback ispnpm exec agent-harness reference, thennpxpinned to this release's exact version rather than a^range.plugin buildadds the pnpm skill name (pnpm-@cyberuni+agent-harness-reference) beside the skill's typed form in its README.
0.6.0
Minor Changes
-
f8913de: Add
acquire,release, andexplainto@cyberuni/agent-harness/worktrees.acquire({ holder, branch?, base?, available?, max? })leases an idle worktree of ours and recycles it (read-tree --reset -u <base>, thenclean -fd, which keepsnode_modules), or creates one at the next free<parent>/<repo>.worktrees/<repo>-<n>slot through an injectable creator. The lease is an exclusive-created git worktree lock, read back after the claim.release(lease)gives it back only when the lease id still matches and never recycles.explain()gives the skip reason for every worktree. A worktree with a live agent session is skipped; when the probe cannot read processes, reuse proceeds and is reported unverified unlessstrictis set. An unlocked worktree at a library slot now classifies asself. -
3f2a9d4: Add the
@cyberuni/agent-harness/worktreessubpath. It has three entry points:primaryRootfinds the primary checkout from any folder in a repository, including a linked worktree.listWorktreeslists every worktree with its branch, HEAD, detached, prunable and lock reason, plus whether its work has landed on the default branch and whether it is dirty.readDirtychecks a worktree for uncommitted changes, can ignore paths you name, and counts untracked files even when a repo hides them.
Landed detection tries, in order: ancestry, a deleted upstream, a squash merge matched by patch id, and an opt-in forge probe (
ghForgeMergedProbe). -
adc4d95: Add a process probe to
@cyberuni/agent-harness/worktreesthat finds live agent sessions inside a worktree. It never kills anything.probeProcessesreads the process table once. Itsoccupancy(root)reportsbusy, theoccupants(every live session, with no limit on how many), thelingeringprocesses, and theunlinkedones. Lingering means no live session launched the process, so a caller can reclaim it. Unlinked means the probe cannot tell.occupants(root)lists the sessions working in one worktree.- A session is recognised by its executable, so tool subprocesses such as a
vitestarted from Claude Code are not sessions. 14 harnesses are covered: Claude Code, Codex, Copilot CLI, Cursor, opencode, Kilo, Qwen Code, Crush, Gemini CLI, Goose, OpenHands, Cline, Auggie, and the Antigravity CLI. - The process source can be swapped out.
procfsProcessSourcereads Linux/proc. On any other platform the probe is unverified and reports not busy, unless you passstrict: true.
-
ffdc416: Add
classifyOwnerto@cyberuni/agent-harness/worktrees. It tells who owns a worktree:self(this library's lease),claude-code,codex,user(the primary checkout), orunknown. Each answer lists the research evidence it rests on. Only aselfworktree may be reused or removed.parseLeaseReasonreads the lease from a lock reason. -
8bcef77: Add
pruneWorktreesto@cyberuni/agent-harness/worktrees. It removes the worktrees this library owns that nothing needs any more (unleased, idle, clean, and landed), then runsgit worktree prune. It is a dry run unlessapplyis set, and returns an outcome per worktree with a skip reason. It never touches the primary checkout, a foreign or locked worktree, a leased one, or one with a live agent session; when the process probe cannot read the platform it skips unlessstrict: false. It never kills a process: lingering dev services are reported so the caller can reclaim them. -
654ac52: Add
seedWorktreeto@cyberuni/agent-harness/worktrees. It copies the gitignored files a.worktreeincludenames from the primary checkout into a new or recycled worktree, following Claude Code's semantics, and returns an inventory of what it copied and what it skipped and why. It reads the include file as data and runs no command but git; file operations go through an injectableSeedFs.
Patch Changes
- 5d67d18:
agent-harness referencenow writes its--formatoutput through@clibuilder/axiinstead of a local copy of the same contract, and no longer depends on@toon-format/toondirectly. TOON, JSON, and text output are byte-identical: axi's text renderer is the one this package carried. An unknown--formatvalue is now rejected by clibuilder before the command runs, as a usage error (exit code 2) with clibuilder's message and the command's help, where it used to exit 1 witherror: --format must be toon, json, or text.
0.5.0
Minor Changes
- dae27d3: Rename the agent plugin from
agent-harnesstocyber-agent-harness, so its skills no longer share a namespace with any other marketplace's plugin of that generic name. Claude Code's typed form is now/cyber-agent-harness:reference; uninstallagent-harnessand run/plugin install cyber-agent-harness@cyberplace. Thereferencecommand's own plugin layer is now namedcyber-agent-harness, read fromplugin.json, socyber-agent-harness/<name>selects it. The npm package, theagent-harnesscommand, and the library API are unchanged.
0.4.0
Minor Changes
- 9ca2ca0: Add
headlessInvocation()andheadlessCommand(): how to run Claude Code, Codex, Copilot CLI, Cursor, Gemini CLI, or Qwen Code on one prompt with no user present — the command, model and permission flags, output formats and where token usage and cost appear, the transcript location, and the documented exit codes. Copilot in VS Code reports no headless mode, and the harnesses whose one-shot flags are not yet verified reportunknown. - 7151efb:
skillInvocation('kilo', …)now returns/<skill>(not namespaced by plugin) instead ofundefined: Kilo Code's CLI and VS Code extension both register every loaded skill as a slash command. - 9002ef2: Add
reference delete <name>. It deletes the project (.agents/references/) or user (~/.agents/references/) copy of a reference, with--scopeand--dry-run, and reports which copy answers the name afterwards. It refuses a plugin-shipped or managed copy. - 849cff0: Add reference documents:
loadReference()and the functions behind it resolve a named Markdown document across the managed, project, user, and plugin tiers, merging each override as its frontmattermergeasks. The package also ships anagent-harness referencecommand, andcreateReferenceCommand()andcreateReferenceCommands()at@cyberuni/agent-harness/commandsfor hosting it in another clibuilder CLI. It now has runtime dependencies (yaml,clibuilder,@toon-format/toon), none of them an agent tool. - f634c3c: Ship the
referenceskill in theagent-harnessplugin, moved frombuddy-agent-harness. Type/reference(/agent-harness:referencein Claude Code) to load, create, update, delete, find, or inspect a reference, or to wire a skill to load one. It runs this package'sreferencecommand from a bundledscripts/reference.mjsthat needs nonode_modules, and falls back tonpx -y @cyberuni/agent-harnessoutside Load. - 5a3e631:
skillsDirectories()now returns Kilo Code's directories (.kilo/skills,.agents/skills,.claude/skills) instead ofundefined, adds.claude/skillsand.agents/skillsfor the Auggie CLI, and adds.agents/skillsfor Cline, at both project and user scope.
Patch Changes
- 2823c69: Document that the OpenHands CLI 1.16.0 marks only its hook commands. Its shell commands carry no
AI_AGENT=openhands, because it bundles an OpenHands SDK older than that variable. Detection is unchanged.
0.3.0
Minor Changes
- b60b4e7: Add
installedPlugins(harness): each installed plugin with the folder the harness loads it from, its version, and, for Claude Code, its install scope. It reads Claude Code'sinstalled_plugins.json, Copilot CLI'sconfig.json, and Codex's plugin cache, where it applies Codex's own active-version rule. Every other harness reportssupported: false.
0.2.0
Minor Changes
- 0f40b36: Add
skillsDirectories(harness): the project and user directories a harness reads skills from, with the evidence IDs behind them. It returnsundefinedfor Kilo Code, Qwen Code, Crush, and OpenHands, where the directories are not confirmed. - 2c66fbf:
detectHarness()now also detects Crush (CRUSH=1), OpenHands (AI_AGENT=openhands, or its hook variables), and the Auggie CLI (in hook commands only), andpluginStorage(),managedPolicyLocations(),enabledPlugins(),skillInvocation(), andsupportsPluginDependencies()answer for them.AI_AGENTcounts as evidence only with the exact valueopenhands; other values, andAGENT=crush, are still ignored. Goose, Antigravity, Rovo Dev, Kiro, Amp, Factory Droid, Devin Desktop, and Warp are not detected, because none has a verified signal.
0.1.0
Minor Changes
-
f3a9e78:
detectHarness()now detects Claude Code, Cursor, Codex, and GitHub Copilot CLI from the process environment. It reports the matchedharness, every signal it found asevidence(each with the research claim ID behind it), and thecandidatesit matched. It reportsunknownwhen no harness matches and when more than one does, as happens when one harness runs inside another. -
f44d752: Add
enabledPlugins(harness, { env, homedir, cwd, platform }). For Claude Code, Codex, and GitHub Copilot CLI it reads the settings files that record enabled plugins and resolves each plugin by scope precedence: managed, then local, then project, then user. It lists the files it read, and inunreadit names the policy sources it cannot read, such as MDM and server-managed settings. Cursor reportssupported: false, because Cursor keeps no record of enabled plugins. -
5823a1b: Add
managedPolicyLocations(harness, { platform }). It lists where each harness keeps managed policy: local files and directories, macOS managed-preferences domains, Windows registry keys, and server-side sources that cannot be read locally. Each entry names the research claim behind it. -
a78c46a:
detectHarness()now also detects OpenCode, Kilo Code, Gemini CLI, Qwen Code, GitHub Copilot in VS Code, and Cline, andpluginStorage(),managedPolicyLocations(),enabledPlugins(),skillInvocation(), andsupportsPluginDependencies()answer for them. Kilo Code still sets OpenCode'sOPENCODE=1, but it is detected askilo;AGENTandAI_AGENT, which several vendors share, are not treated as evidence.skillInvocation()now returnsundefinedfor a harness with no typed skill invocation: OpenCode, Kilo Code, Gemini CLI, and Qwen Code load skills through a model tool call. -
68fce08: Add
pluginStorage(harness, { env, homedir }). It returns a harness's user-level config directory, afterCLAUDE_CONFIG_DIR,CODEX_HOME, orCOPILOT_HOME, and where it keeps installed plugins, marketplaces, the install record, and the enabled record. -
e6165bf: Add
skillInvocation(harness, { plugin, skill }), which returns what a user types to invoke a plugin skill:/<plugin>:<skill>in Claude Code,/<skill>in Cursor and GitHub Copilot CLI, and$<skill>in Codex. AddsupportsPluginDependencies(harness), which istrueonly for Claude Code.
Patch Changes
- b0de9bb: The plugin manifests no longer point
skillsat a./skills/folder the package does not ship, and the packagefileslist no longer names acom.github.copilotfolder: Copilot CLI reads the rootplugin.json. - 9d4b8d2: A release now carries the package version into
plugin.jsonand the per-harness plugin manifests, so they no longer stay at0.0.0. - 120b0b3: The published types no longer reference
NodeJS.Platform, so a TypeScript project without@types/nodein itstypescan import the package. Theplatformoption now takes the exportedPlatformtype, a union of the valuesprocess.platformreports.