Skip to content

Add a Yaak CLI skill for coding agents - #535

Merged
gschier merged 14 commits into
mainfrom
claude/trusting-heyrovsky-04f4d7
Aug 14, 2026
Merged

Add a Yaak CLI skill for coding agents#535
gschier merged 14 commits into
mainfrom
claude/trusting-heyrovsky-04f4d7

Conversation

@gschier

@gschier gschier commented Aug 14, 2026

Copy link
Copy Markdown
Member

Ships a use-yaak skill inside the CLI, installed with yaak agent install, and makes the CLI self-describing enough that the skill does not need to carry facts.

The skill

A single 135-line SKILL.md. It covers what Yaak is, the resource model, the core workflows (import a spec, make the host swappable per environment, chain a response into the next request, run a folder or workspace, run a suite in CI), and how to read send output. It deliberately lists no fields, body types, auth strategies, or template functions, because the user's CLI version and installed plugins decide what exists. It says outright that the CLI wins when the two disagree.

It is embedded with include_dir and written to ~/.agents/skills plus any detected tool directory (.claude, .cursor, .codex, .opencode), so it never creates a config dir for a tool the user does not have. A hash manifest means reinstalls keep files the user edited, upgrades drop files no longer shipped, and agent remove deletes only what it wrote. --force and --agent <name> are available.

CLI discoverability

The skill can stay thin only because the CLI answers these itself:

  • yaak template-function list [filter] and yaak template-function show <name> report what loaded plugins actually provide, mirroring how request schema http already merges in plugin auth strategies. Worth noting the scale: on a machine with a faker plugin installed this returns 274 functions, 47 of them not from faker. Any hardcoded list was going to be wrong.
  • yaak folder schema now exists, so folder payloads are discoverable like every other model. This needed JsonSchema derived on Folder.
  • The request schema now documents bodyType and body shapes, and states that choosing a body type does not add a Content-Type header.
  • Fixed the URL path parameter hint, which said to omit the leading colon. apply_path_placeholders returns early unless the name starts with :, so following the old hint left /pets/:petId literal in the path and appended ?petId=42, failing silently.

The Content-Type behavior documented in the schema is tracked separately as a possible product change; if that lands, the wording here is what needs updating.

…all`

Teaches agents to drive the CLI: workspaces, environments, requests,
sending, response chaining, and importing. SKILL.md stays lean with
four references loaded on demand.

The skill is embedded in the binary and written to ~/.agents/skills plus
any detected tool directory, so it ships with the CLI and refreshes on
update. Reinstalls keep files edited locally unless --force.

Also fixes the `request schema http` hint for URL path parameters, which
said to omit the leading colon. Names without the colon are sent as query
string parameters instead, leaving the placeholder literal in the path.
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds a CLI-managed use-yaak coding-agent skill and expands CLI discoverability for folders, responses, request schemas, and plugin-provided template functions.

  • Adds agent skill installation, removal, version stamping, and freshness hints.
  • Adds response inspection and deletion commands.
  • Adds folder schema and template-function discovery commands.
  • Improves HTTP request schema guidance and verbose response output ordering.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates-cli/yaak-cli/src/commands/agent.rs Implements target discovery, version-stamped atomic skill installation, managed-directory removal, and help freshness reporting.
crates-cli/yaak-cli/skills/use-yaak/SKILL.md Provides CLI-driven guidance for coding agents without hardcoding version-dependent request fields or plugin capabilities.
crates-cli/yaak-cli/src/commands/request.rs Improves request schema guidance, rejects non-HTTP payloads, and serializes verbose event output before the response body.
crates-cli/yaak-cli/src/commands/response.rs Adds stored-response listing, inspection, body output, and scoped deletion.
crates-cli/yaak-cli/src/commands/template_function.rs Adds runtime discovery and inspection of template functions supplied by installed plugins.
crates-cli/yaak-cli/src/main.rs Registers the new commands and dynamically appends agent-skill status to root help.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[yaak agent install] --> B[Resolve detected agent targets]
  B --> C[Write embedded SKILL.md atomically]
  C --> D[Stamp current CLI version]
  D --> E[Prune entries not shipped]
  E --> F[Agent reads installed skill]
  F --> G[Skill queries CLI schemas and plugin functions]
Loading

Reviews (14): Last reviewed commit: "Correct the install comment and record t..." | Re-trigger Greptile

Comment thread crates-cli/yaak-cli/src/commands/agent.rs
Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
Two problems found in review, both from deleting without checking what we
actually wrote:

`agent remove` called remove_dir_all on the whole tree, discarding files
the user had edited or added. Install goes out of its way to preserve
those, so uninstall throwing them away was inconsistent and lossy. It now
deletes only tracked files whose contents still match the manifest,
prunes empty directories, and reports anything it kept.

`agent install` never reconciled against the previous manifest, so a file
an older CLI shipped but a newer one drops would linger and could feed an
agent stale guidance. Unshipped files are now removed when unmodified,
and left alone (and untracked) when the user has edited them.
Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
Authentication was only covered in references/requests.md, so an agent
that never opened it had no reason to know the schema enumerates every
installed strategy, including plugin-contributed ones. OAuth 2.0 was not
mentioned in the always-loaded file at all.

SKILL.md now shows how to list the strategies and dump one's shape, and
calls out that the variant title is a display label rather than the
authenticationType value ("NTLM Auth" is `windows`, "AWS Signature" is
`awsv4`). Auth is in the frontmatter description too, so the skill
triggers on requests to add auth to a request.

requests.md gains a worked OAuth 2.0 payload, verified against the schema
and round-tripped through the model.
The skill had grown into a reference manual: body type tables, auth
strategy lists, a template function table, field-by-field OAuth 2.0
config. All of it goes stale, because the user's CLI version and their
installed plugins decide what actually exists. On this machine a faker
plugin contributes 274 template functions; the skill listed eleven, and
got some names wrong.

The CLI should carry that knowledge, so:

- `yaak template-function list [filter]` and `template-function show
  <name>` report what the loaded plugins actually provide, the same way
  `request schema http` already merges in plugin auth strategies.
- `yaak folder schema` now exists, so folder payloads are discoverable
  like every other model. Required deriving JsonSchema on Folder.
- The request schema documents `bodyType` and `body` shapes, and states
  that setting a body type does not add a Content-Type header.

The skill drops to a single 135-line SKILL.md that teaches the model,
the workflows, and how to interrogate the CLI, and says outright that
the CLI wins when the two disagree.
Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
Stored responses were unreachable from the CLI even though the model
layer has had list/get/delete all along. After a send, an agent could
only see the body it just streamed: no status, no timing, no history.
`yaak response list|show|body|delete` closes that. `show` and `body`
accept a request ID as shorthand for its most recent response, which is
the common case, and `show` returns status, reason, timing, headers, the
final URL, and any transport error as JSON.

`request create` also accepted payloads for request types it cannot
create. A gRPC-shaped payload deserialized into an HttpRequest with the
unknown fields dropped, so the gRPC method name landed in `method`,
`service` vanished, and the result looked like a successful create. It
now rejects a non-`http_request` `model`, and any field that is not part
of the HTTP request schema, pointing at the app instead. `request update`
had the same silent-drop behavior and gets the same check.

The skill now points at `response show` rather than teaching agents to
grep verbose send output for the status line.
`response delete` had to run its own list first just to report how many
it removed, which duplicated the query the helper already does. Both
helpers now return the count instead.

`cmd_delete_all_http_responses` was returning the helper's value
directly, so it keeps its `()` result explicitly and the frontend
contract is unchanged.
Three ownership-loss paths found in review, all variations on discarding
the manifest while the file it describes is still on disk.

`remove` deleted the manifest unconditionally. When it deliberately kept
a file the user had edited, the next install saw an untracked file and
overwrote those edits without --force, undoing the preservation that
removal had just performed. It now writes back a manifest covering
everything still present, and only deletes it when the directory is
actually empty.

The same applied to files it could not delete: the record vanished, the
file stayed, and removal still reported success. Those are now retained,
reported, and retried by a later run.

Upgrade cleanup had the mirror problem, dropping stale entries from the
new manifest even when deletion failed, orphaning a file we know we
wrote. It keeps tracking those so a later install can retry.

A failed manifest write during removal is now a warning rather than an
abort, since the previous manifest still lists every retained file and
other targets should still be processed.
Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
The skill directory is a CLI-managed artifact, so install now replaces it
wholesale and remove deletes it. Drops the manifest file, the content
hashing, and --force.

Preserving edits was worse than losing them. An edited file was skipped
by every future install, so it stayed frozen forever against a CLI that
keeps changing, which defeats the reason for embedding the skill in the
binary at all. Replacing wholesale also drops files an older version
shipped, with no reconciliation logic needed.

This removes the three ownership-loss paths raised in review rather than
patching them, since all of them came from keeping that bookkeeping file
in sync with what was on disk.

SKILL.md now says it is managed and points anywhere else for custom
guidance.
Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
An upgraded CLI silently leaves the installed skill behind: nothing
errors, the skill just stops mentioning what the CLI can now do. Nothing
told the user to refresh it, and the skill's own instruction covered only
the opposite (and impossible) direction of the CLI being older than the
skill it wrote.

Install now stamps the CLI version into the skill directory, and root
`--help` gains an "Agent tooling" section comparing it against the
running version, naming the tool directories that are behind. It stays
silent when no skill is installed, so it does not nag users who have no
agent tooling. The skill tells agents to check it once per session.

This covers every install path rather than only npm, since the CLI also
ships with app releases.

Also corrects the skill's advice about `-v`: body chunks and event lines
are written by separate tasks, so their order is not deterministic and
the body can run onto the status line. Verified across repeated runs. It
now says to use `response show` rather than parsing verbose output.
With -v, the event printer and the body writer were two independent
tasks writing to stdout, so their output raced. Across repeated runs of
the same request the body would sometimes land mid-headers and run onto
the status line, which made even `grep '^< HTTP'` miss it, and truncated
what looked like the response metadata.

Verbose now buffers the body and writes it once the event stream is
done, so output is always the connection lines, the headers, then the
body. Without -v nothing else writes to stdout, so the body still
streams as it arrives.

Verified over ten consecutive runs, and with a 200KB body through both
paths.
`write_skill` deleted the existing skill directory before writing its
replacement, so any error part way through left the user with no skill
at all. An upgrade that failed was worse than not upgrading.

It now builds the new copy in a staging directory beside the old one and
swaps it in with a rename. Staging shares the parent directory so the
rename stays on one filesystem. If the swap itself fails after the old
copy has been moved aside, the old copy is renamed back.

Verified: with the skills directory read-only, an upgrade fails with a
clear error and exit 1, and the previously installed skill is still
present and byte-for-byte intact, with no staging directories left
behind.
greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 14, 2026
Drops the staging directory added in the previous commit. `rename` cannot
replace a non-empty directory, so the destination has to be vacated
regardless; moving the old copy aside and writing in its place needs one
rename instead of two and no third directory.

The recovery behaviour is unchanged: on any write failure the partial
directory is removed and the old copy is renamed back.

All three failure paths are now covered by testing rather than
inspection. A write failure injected mid-install (SKILL.md written,
.yaak-version failing) removes the partial directory and restores the
previous copy intact, with no leftovers.
@greptile-apps
greptile-apps Bot dismissed their stale review August 14, 2026 12:36

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

Comment thread crates-cli/yaak-cli/src/commands/agent.rs Outdated
Carrying the version in a second file meant the install had to replace a
directory, which cannot be done atomically: rename refuses a non-empty
destination, so the old copy had to be moved aside and put back by hand
on failure. That was recoverable from errors but not from a crash, and
it leaked an orphaned .old- directory that nothing ever reclaimed.

The version now lives in a comment in SKILL.md, so the skill is a single
file again and each file can be written through a temp file and renamed
into place. Renaming over an existing file is atomic, so a reader sees
either the old skill or the new one, never a partial write, and a crash
cannot leave anything behind but a temp file that the next install
prunes.

Anything the current version does not ship is pruned after writing,
which also migrates installs that still have the old .yaak-version file.

Verified: 40 reinstalls while a reader loops on SKILL.md produced no
partial, empty, or missing reads.
greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 14, 2026
The doc comment still described the remove-and-rewrite approach, which
is no longer what happens. It now matches the code, and states the
constraint the code cannot show: writes are atomic per file, so a second
skill file would let a reader catch a mix of old and new. Replacing the
directory as a unit is not possible, so that case would need a symlink
swap between versioned directories.
@greptile-apps
greptile-apps Bot dismissed their stale review August 14, 2026 12:59

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

@gschier
gschier merged commit e032c4c into main Aug 14, 2026
6 checks passed
@gschier
gschier deleted the claude/trusting-heyrovsky-04f4d7 branch August 14, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant