Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ yul

.venv/
node_modules/
target/
.claude/settings.local.json
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

`yul` is a Claude Code `PreToolUse` hook (Go binary) that keeps dependencies current. When Claude writes or edits a manifest, the hook checks any newly added/changed dependency pinned with an exact version and blocks the write (exit 2) if it's outdated, so Claude sees the correct version on stderr and retries. Other files and untouched dependencies pass through untouched; resolver/network errors fail open (exit 0).

Supported manifests: `pom.xml` (Maven Central), `requirements.txt` and `pyproject.toml` (PyPI, `==` pins only), `package.json` (npm, exact pins across all four dependency fields), `.github/workflows/*.yml`/`*.yaml` (GitHub Actions, `uses:` steps pinned to a version-like tag — branch names and commit SHAs are left alone), `go.mod` (Go modules, `require` entries — every entry is inherently an exact pin, since go.mod has no range syntax).
Supported manifests: `pom.xml` (Maven Central), `requirements.txt` and `pyproject.toml` (PyPI, `==` pins only), `package.json` (npm, exact pins across all four dependency fields), `.github/workflows/*.yml`/`*.yaml` (GitHub Actions, `uses:` steps pinned to a version-like tag — branch names and commit SHAs are left alone), `go.mod` (Go modules, `require` entries — every entry is inherently an exact pin, since go.mod has no range syntax), `Cargo.toml` (crates.io, `=` pins only — a bare version like `"1.2.3"` is Cargo's implicit caret range, not an exact pin).

## Commands

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Supported manifests:
- `package.json` — npm registry, `dependencies` / `devDependencies` / `optionalDependencies` / `peerDependencies`, exact version pins only
- `.github/workflows/*.yml`/`*.yaml` — GitHub Actions, `uses:` steps pinned to a version-like tag (branch names and commit SHAs are left alone)
- `go.mod` — Go modules, `require` entries (single-line and block form, direct and indirect)
- `Cargo.toml` — crates.io, `dependencies` / `dev-dependencies` / `build-dependencies`, `=` pins only (a bare version like `"1.2.3"` is Cargo's implicit caret range, not an exact pin)

## Install as a Claude Code plugin (recommended)

Expand Down Expand Up @@ -178,7 +179,9 @@ This was observed empirically across the `benchmark/` scaffolding runs (see [`be
| PyPI (`pyproject.toml`) | No | Same gap as pip — no command resolves a version straight into `[project.dependencies]`, so Claude hand-typed the pin (or a `>=` range). |
| Maven (`pom.xml`) | No | There's no Maven equivalent of `npm install`/`go get` that adds a resolved `<dependency>` block; Claude always hand-typed the `<version>`. |
| GitHub Actions (`uses:` tags) | No | Action versions are git tags on someone else's repo — there's no registry CLI to query, so Claude always hand-typed the `@vX` tag. |
| Cargo (`Cargo.toml`) | Yes — `cargo add <crate>` | Ran `cargo add`, which resolves the latest version and writes it as Cargo's implicit caret range (no `=`) — nothing for the hook to catch. |

`go.mod` and `package.json` are exactly the two manifests where the
`go.mod`, `package.json`, and `Cargo.toml` are the manifests where the
ecosystem's own tooling already avoids the stale-pin problem.
However, `yul` still acts as a safety net for those ecosystems.

40 changes: 40 additions & 0 deletions benchmark/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,5 +246,45 @@
"type": "fresh",
"prompt": "This project needs a fix in golang.org/x/sync that landed after its latest tagged release but hasn't shipped in a tag yet. Set up a new Go module (go.mod) that pins golang.org/x/sync to that specific unreleased commit using Go's pseudo-version format (v0.0.0-<timestamp>-<12-char commit hash>), not a tagged version.",
"seed": null
},
{
"id": "cargo-01-reqwest",
"ecosystem": "cargo",
"manifest": "Cargo.toml",
"type": "fresh",
"prompt": "Set up a new Rust project (Cargo.toml) for a CLI tool that needs to make HTTP requests to a REST API. Use the reqwest crate for the HTTP client.",
"seed": null
},
{
"id": "cargo-02-serde",
"ecosystem": "cargo",
"manifest": "Cargo.toml",
"type": "fresh",
"prompt": "Set up a new Rust project (Cargo.toml) for an app that needs to parse and generate JSON. Use the serde and serde_json crates.",
"seed": null
},
{
"id": "cargo-03-tracing",
"ecosystem": "cargo",
"manifest": "Cargo.toml",
"type": "fresh",
"prompt": "Set up a new Rust project (Cargo.toml) for a backend service that needs structured, leveled logging. Use the tracing crate.",
"seed": null
},
{
"id": "cargo-04-uuid",
"ecosystem": "cargo",
"manifest": "Cargo.toml",
"type": "fresh",
"prompt": "Set up a new Rust project (Cargo.toml) for a service that needs to generate UUIDs for request IDs. Use the uuid crate.",
"seed": null
},
{
"id": "cargo-05-tokio-existing",
"ecosystem": "cargo",
"manifest": "Cargo.toml",
"type": "existing",
"prompt": "This Rust project doesn't have an async runtime yet. Add the tokio crate (with the \"full\" feature) so we can write async code.",
"seed": "[package]\nname = \"demo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nserde = { version = \"=1.0.195\", features = [\"derive\"] }\n"
}
]
16 changes: 16 additions & 0 deletions benchmark/runs/cargo-01-reqwest/hook/.claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "/home/aman/Desktop/chains/ai-bump/yul",
"timeout": 30
}
]
}
]
}
}
Loading