Skip to content

Add hunk skill install to teach agents how to drive Hunk - #1093

Open
benvinegar wants to merge 5 commits into
mainfrom
claude/sweet-clarke-v65if1
Open

Add hunk skill install to teach agents how to drive Hunk#1093
benvinegar wants to merge 5 commits into
mainfrom
claude/sweet-clarke-v65if1

Conversation

@benvinegar

Copy link
Copy Markdown
Member

Adds hunk skill install --agent <name> command to install pointer skills into coding agents' skill directories. This replaces the manual workflow of locating and loading skill files.

Summary

The installed pointer skill is deliberately minimal: it carries only the bundled skill's name and description in frontmatter, then directs the agent to run hunk skill show for the full instructions. This keeps the installed Hunk binary as the single owner of skill text, ensuring pointer skills never go stale across Hunk upgrades.

Key changes

  • New agentSkills.ts module defines agent host configurations (Claude Code, Codex, opencode, Cursor, Amp, GitHub Copilot, and the shared .agents/skills convention), resolves user-supplied agent names and aliases, and implements the install command logic
  • Pointer skill rendering extracts frontmatter (name and description) from bundled skills and wraps them in a stub that defers to hunk skill show for the real instructions
  • Multi-agent support with deduplication: --agent can repeat; when multiple agents share a skills directory (e.g., Codex, Amp, and the generic host all read .agents/skills), the pointer is written once
  • Scope control via --project flag to write under the current directory instead of the home directory
  • Force flag to replace hand-written skills that Hunk did not generate
  • CLI integration adds hunk skill show (prints bundled skill text) and hunk skill install subcommands; updated help text and documentation
  • Comprehensive tests covering host resolution, path planning, frontmatter parsing, pointer rendering, and the full install workflow with conflict detection

Implementation details

  • Agent host contexts resolve $XDG_CONFIG_HOME, $HOME, and agent-specific environment variables (e.g., $CLAUDE_CONFIG_DIR) to locate skills directories
  • Pointer files carry a regeneration marker (<!-- generated by \hunk skill install` -->`) so reinstalls can distinguish Hunk-generated files from hand-written ones
  • Install checks all targets before writing any, so a refusal leaves no half-installed set behind
  • Bundled skill documents are read once at install time; the pointer carries only the extracted frontmatter, keeping the installed CLI as the authoritative source

https://claude.ai/code/session_018PqAUQp8FqVcDxcMHXV3ci

`hunk skill install --agent <name>` writes a thin pointer SKILL.md into a
coding agent's skills directory (Claude Code, Codex, opencode, Cursor, Amp,
GitHub Copilot, or the shared `.agents/skills` convention). The pointer
carries only the bundled skill's name and description and tells the agent
to run the new `hunk skill show`, so the installed Hunk binary stays the
single owner of the skill text and upgrades never leave a stale copy behind.

- `--agent` repeats for several hosts; shared directories are written once.
- `--project` targets the current directory instead of the home directory.
- Hunk rewrites its own earlier pointer but refuses a hand-written SKILL.md
  unless `--force` is passed, and checks every target before writing any.
- Docs, README, agent workflow guide, and the generated CLI reference now
  lead with the install command.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PqAUQp8FqVcDxcMHXV3ci
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hunk-web Ready Ready Preview Sep 11, 2026 7:01pm UTC

Request Review

`check:pack` requires packages/hunk/README.md to match the root README,
which now leads the agent section with `hunk skill install`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PqAUQp8FqVcDxcMHXV3ci
@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds hunk skill install and hunk skill show, wires installation through headless startup, defines host-specific user and project skill directories, generates lightweight pointer skills, and updates tests and documentation.

  • Resolves repeated agent selections and deduplicates shared target directories.
  • Preserves non-Hunk skill files unless --force is supplied.
  • Keeps full skill instructions in the installed Hunk binary.
  • The project-scoped filesystem write needs symlink containment protection before merge.

Confidence Score: 3/5

This PR is not safe to merge until project-scoped installs reject symlink escapes and the explicit repository requirements are satisfied.

A malicious checkout can redirect the new project-scoped write outside the repository because the implementation follows symlinked targets and ancestors; the new module also violates applicable filename and environment-access requirements.

Files Needing Attention: packages/hunk/src/core/install/agentSkills.ts, packages/hunk/src/core/install/agentSkills.test.ts

Security Review

Project-scoped installation follows symlinks supplied by the current checkout, allowing a malicious repository to redirect the generated pointer write outside the repository. The target and its ancestors should be checked with lstat and canonical containment verification before any write.

Important Files Changed

Filename Overview
packages/hunk/src/core/install/agentSkills.ts Implements host resolution, pointer rendering, conflict checks, and installation, but project writes can escape through symlinks and two repository rules are violated.
packages/hunk/src/app/cli.ts Adds parsing, validation, help, and reference metadata for the new install and show subcommands.
packages/hunk/src/app/startup.ts Routes parsed skill installations into a headless startup plan.
packages/hunk/src/main.tsx Executes the new installation plan and forwards command output to stdout.
packages/hunk/src/core/install/agentSkills.test.ts Covers host resolution, target planning, frontmatter rendering, deduplication, and conflict handling, but not real-filesystem symlink behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[hunk skill install] --> B[Parse agents, skill, scope, and force]
  B --> C[Read bundled skill frontmatter]
  C --> D[Resolve host skill directories]
  D --> E[Deduplicate target paths]
  E --> F[Precheck existing SKILL.md files]
  F -->|Conflict without force| G[Abort before writes]
  F -->|Allowed| H[Create target directories]
  H --> I[Write pointer SKILL.md]
  I --> J[Agent loads pointer]
  J --> K[hunk skill show]
  K --> L[Full bundled instructions]
Loading
Prompt To Fix All With AI
### Issue 1
packages/hunk/src/core/install/agentSkills.ts:273-275
**Project Writes Follow Symlinks**

When `--project` is run in a checkout containing a symlinked `SKILL.md` or parent directory, `mkdirSync` and `writeFileSync` follow that repository-controlled link without checking that the resolved path remains in the checkout. This can overwrite or create a user-writable file outside the repository. Reject symlinked targets and ancestors before writing, as the existing workspace write guard does.

**How this was verified:** The target is rooted at the current checkout, while the final `mkdirSync` and `writeFileSync` calls perform no `lstat` or canonical-path containment check and therefore follow repository-provided links.

### Issue 2
packages/hunk/src/core/install/agentSkills.ts:1
**New Files Violate Naming**

The new `agentSkills.ts` source and `agentSkills.test.ts` test use camel-cased filenames. The repository directive requires dash-case for `.ts` and `.tsx` files, so these must be renamed to `agent-skills.ts` and `agent-skills.test.ts` and their imports updated before merging.

### Issue 3
packages/hunk/src/core/install/agentSkills.ts:288
**Package Reads Environment Directly**

This package-level command falls back directly to `process.env`. The repository directive prohibits direct `process.env` access and requires validated environment values to be passed from the application, so the command should receive them through its existing IO boundary before merging.

### Issue 4
packages/hunk/src/core/install/agentSkills.ts:302
**Marker Can Misidentify Ownership**

The unrestricted substring check treats any file containing the public HTML marker as Hunk-generated. A hand-written or modified skill that quotes this marker will therefore be silently overwritten without `--force`, contrary to the documented promise to preserve hand-written skills. Validate the complete generated-file structure or use stronger ownership metadata to avoid losing user content.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(cli): add `hunk skill install --age..." | Re-trigger Greptile

Comment thread packages/hunk/src/core/install/agentSkills.ts
Comment thread packages/hunk/src/core/install/agentSkills.ts
Comment thread packages/hunk/src/core/install/agentSkills.ts
Comment thread packages/hunk/src/core/install/agentSkills.ts Outdated
…shape

`hunk skill install --project` writes under repository content, so a
checkout could redirect `.claude/skills` (or the SKILL.md itself) through
a symlink into the user's home. Walk each component below the repository
root with lstat and refuse the first link, stopping at the first missing
component; user-scoped installs stay unchecked because those directories
are the user's own and are often symlinked into dotfiles on purpose.

Ownership of an existing SKILL.md now requires the exact generated shape
(frontmatter, blank line, marker) rather than the marker appearing
anywhere, so a hand-written skill that quotes it is not overwritten
without --force.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PqAUQp8FqVcDxcMHXV3ci
The skills CLI scans a repository's root `skills/` and `.agents/skills/`
but not `packages/hunk/skills/`, so `npx skills add modem-dev/hunk`
offered only the maintainer-only release and video skills. Generate the
same pointer stub `hunk skill install` writes into `.agents/skills/<name>/`
for each bundled skill, and mark the maintainer skills `metadata.internal`
so the CLI hides them. A test keeps the checked-in pointers in sync with
the renderer; `bun run generate:skill` regenerates them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PqAUQp8FqVcDxcMHXV3ci
…65if1

# Conflicts:
#	packages/hunk/src/app/cli.ts
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.

2 participants