Skip to content

Give each built-in tool its CLI command and return it with fetched skills; fetch one skill by name; version the skill list #3540

Closed

Description

@malibio

Overview

A coding agent (Claude Code, Codex, Pi, OpenCode) fetches NodeSpace's skills with nodespace skill guidance. Built-in skills are rendered for it: a step that has to name how it is done is a rule with an agent form and a CLI form. Three things are still missing for that fetch to serve every skill and the harness plugins that will sit on it:

  1. A tool named anywhere else is not translated: in a skill a user wrote or edited, or in a built-in skill's prose outside a rule.
  2. A skill cannot be fetched by its name, only matched by a task description.
  3. The skill list has no version, so a client cannot tell that the list changed since it last read it.

Problem Statement

Tool names reach a coding agent untranslated. A user-written or user-edited skill is served as stored. If its body says "use search_nodes when you know the name", or its tool_whitelist lists create_relationship, a coding agent has no such tool and nothing tells it which nodespace command does the same thing. Skills are meant to be any instruction a user writes, and a body may say which tool to use in which case, so this is the common case for user skills, not an edge.

No fetch by name. An agent that sees "Writing a Spec" in the skill list has to describe a task and hope the match returns that skill. A plugin that lists skills needs a deterministic way to load the one the agent picked.

No way to detect a changed list. Skills change while a session is open (a teammate adds a policy, a user edits a procedure). A plugin needs one cheap call to learn whether the list it showed the agent is still current.

Proposed Solution

  • Record each built-in tool's CLI command on its registry node. Add an optional text field to tool-native holding the nodespace command that does the same thing (for example create_relationship → nodespace relationship create). A tool with no CLI equivalent leaves it unset.
  • Return tool commands with a fetched skill. For each skill a fetch returns to a coding agent, include the CLI command of every registry tool the skill lists in tool_whitelist or names in its body. This applies to built-in, user-edited and user-written skills alike. The body is not rewritten.
  • Keep the per-audience rules. A built-in step whose procedure differs between the built-in agent and the CLI (deleting, which the CLI previews and then confirms; a task's status, which the CLI sets with its own command) stays a rule with a form per audience. The command field translates a name; a rule covers a different procedure.
  • Fetch one skill by name or id, returning the same content a match returns for it: instructions, referenced schemas, tool commands, provenance.
  • Version the skill list. The list output carries a version that changes whenever a skill is added, removed or archived, or its name, description or body changes.

Documentation

  • ADR-093 §1 - the list, match and get operations and the list version; §2 - skills name tools from the registry, a tool carries its command-line form, and a step whose procedure differs keeps a form per reader
  • ADR-064 §5 (revised) - the skill file is the entry point, skill nodes own procedure, per-audience rules; extended by ADR-093 §2
  • Tool Registry - tool and tool-native, the fields a tool node carries
  • Node type sequence - mandatory for the new tool-native field
  • ADR-086 - one wire definition, generated TypeScript, closed schemas
  • Updates: components/node-types.md (the tool-native sheet), components/tool-registry.md (the new field), architecture/prompt-skill-system.md (what a fetch returns)

Architecture Impact

Implements ADR-093 §1 and §2. ADR-093 §2 extends ADR-064 §5 (revised): the per-audience rule form stays for steps whose procedure differs, and the registry command is added for tool names everywhere else. Both ADRs already say this; no further decision change is needed. The docs listed under Updates change in the same work.

Acceptance Criteria

  • tool-native declares an optional text field for the tool's CLI command, added through the node type sequence: schema, registry, wire type, typed update, regenerated TypeScript (bun run gen:types), and the tool-native sheet in node-types.md
  • Every seeded built-in tool that has a nodespace equivalent carries its command; a test fails if a built-in tool named by any seeded skill (in tool_whitelist or body) has none
  • A fetch by a coding agent returns, for each skill, the CLI command of every registry tool the skill lists in tool_whitelist or names in its body
  • The same holds for a user-written skill and a user-edited built-in skill; a test covers a user-written skill whose body names a built-in tool
  • A tool name is matched in a body at word boundaries, so update_node does not match inside update_nodes_from_markdown
  • A tool with no CLI command is left out of the returned commands, and the fetch still succeeds
  • The built-in agent's rendering of every skill is unchanged; prompt and routing golden snapshots show no diff
  • The per-audience rule forms are unchanged
  • A skill can be fetched by exact name or by id, returning the same content a match returns for that skill, inside the same provenance envelope; an unknown name fails with a message naming it
  • The no-task listing carries a version in --json output and in human output
  • The version changes when a skill is added, removed or archived, and when a skill's name, description or any part of its body changes; it does not change when unrelated nodes change
  • Two listings with no skill change between them return the same version
  • The CLI output changes are reflected in packages/skill/SKILL.md and packages/skill/references/cli.md, including when to fetch a skill by name, and bun run skill:check passes
  • SKILL.md tells the agent that the returned tool commands are how it carries out a step that names a tool
  • The live skill-fetch test covers a user-written skill that names a built-in tool: the agent runs the corresponding nodespace command
  • tool-registry.md and prompt-skill-system.md updated as listed under Documentation
  • Code passes bun run quality:fix
  • Tests pass (bun run test:changed)

Technical Specifications

Reference Files

  • packages/core/src/models/core_schemas.rs - the tool and tool-native schemas
  • packages/agent/src/skill_pipeline.rs - seed_tool_nodes (each built-in tool's node, keyed by handler), SKILL_SEEDS
  • packages/core/src/ops/skill_ops.rs - find_skills, render_skill_instructions, mentions_phrase (word-boundary matching)
  • packages/daemon/src/services/node_service.rs and packages/proto/proto/node_service.proto - the GetSkillGuidance RPC
  • packages/cli/src/commands/skill.rs - skill guidance, the provenance envelope and its printer
  • packages/agent/src/skill_rules.rs - the per-audience rule forms, which stay
  • packages/agent/tests/it/live_skill_guidance_fetch.rs - the live fetch test
  • packages/cli/examples/gen_skill_md.rs, packages/cli/tests/it/skill_md_generation.rs - the generated regions of SKILL.md and references/cli.md
  • packages/nodespace-types - the tool-native wire type

Implementation Details

  • Field names are snake_case and stored names are user-visible keys, so choose the field's name once. It describes what it holds (the tool's CLI command), not who reads it.
  • The command is the command and subcommand, not a full invocation with flags. Argument shapes stay in references/cli.md and --help (ADR-064).
  • Resolve tool nodes through the registry (type_is_a), not a literal node_type comparison. An archived tool is not offered and its command is not returned.
  • The version is derived from stored state (for example a hash over each skill's id and version, including its subtree), not kept as a counter. Nothing is written when a skill changes.
  • Whether fetch-by-name is a flag on skill guidance or its own subcommand is the implementer's choice; say which in the PR and document it in cli.md.
  • A new or changed RPC means regenerating the proto stubs.
  • Seed changes need a database reset, not a backfill.

Related Issues

Non-Goals

  • Harness plugins, ready tasks, task context and the project lookup (other parts of ADR-093)
  • Turning tool_whitelist from names into declared links to tool nodes
  • Bindings for remote tools (tool-mcp, tool-rest, tool-cli)

Activity

  1. malibio commented on Oct 4, 2026

    @malibio
    CollaboratorAuthor

    Baseline — Frontend: 315 test files passed (5690 tests)

  2. self-assigned this
    on Oct 4, 2026
  3. added a commit that references this issue on Oct 4, 2026
    762336d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions