@circlesac/oneup
Advanced tools
| const https = require("https"); | ||
| const fs = require("fs"); | ||
| const path = require("path"); | ||
| const { execSync } = require("child_process"); | ||
| const { version } = require("../package.json"); | ||
| const REPO = "circlesac/oneup"; | ||
| const PLATFORMS = { | ||
| "darwin-x64": { artifact: "oneup-x86_64-apple-darwin", ext: ".tar.gz" }, | ||
| "darwin-arm64": { artifact: "oneup-aarch64-apple-darwin", ext: ".tar.gz" }, | ||
| "linux-x64": { artifact: "oneup-x86_64-unknown-linux-gnu", ext: ".tar.gz" }, | ||
| "linux-arm64": { artifact: "oneup-aarch64-unknown-linux-gnu", ext: ".tar.gz" }, | ||
| "win32-x64": { artifact: "oneup-x86_64-pc-windows-msvc", ext: ".zip" }, | ||
| }; | ||
| async function download(url) { | ||
| return new Promise((resolve, reject) => { | ||
| https.get(url, (res) => { | ||
| if (res.statusCode === 302 || res.statusCode === 301) { | ||
| download(res.headers.location).then(resolve).catch(reject); | ||
| return; | ||
| } | ||
| if (res.statusCode !== 200) { | ||
| reject(new Error(`HTTP ${res.statusCode}`)); | ||
| return; | ||
| } | ||
| const chunks = []; | ||
| res.on("data", (chunk) => chunks.push(chunk)); | ||
| res.on("end", () => resolve(Buffer.concat(chunks))); | ||
| res.on("error", reject); | ||
| }); | ||
| }); | ||
| } | ||
| async function main() { | ||
| const platform = `${process.platform}-${process.arch}`; | ||
| const info = PLATFORMS[platform]; | ||
| if (!info) { | ||
| console.error(`Unsupported platform: ${platform}`); | ||
| console.error(`Supported: ${Object.keys(PLATFORMS).join(", ")}`); | ||
| process.exit(1); | ||
| } | ||
| const { artifact, ext } = info; | ||
| const url = `https://github.com/${REPO}/releases/download/v${version}/${artifact}${ext}`; | ||
| console.log(`Downloading ${artifact}...`); | ||
| try { | ||
| const data = await download(url); | ||
| const nativeDir = path.join(__dirname, "native"); | ||
| if (!fs.existsSync(nativeDir)) { | ||
| fs.mkdirSync(nativeDir, { recursive: true }); | ||
| } | ||
| const tmpFile = path.join(nativeDir, `tmp${ext}`); | ||
| fs.writeFileSync(tmpFile, data); | ||
| if (ext === ".zip") { | ||
| // Windows: use PowerShell to extract zip | ||
| execSync( | ||
| `powershell -Command "Expand-Archive -Force '${tmpFile}' '${nativeDir}'"`, | ||
| { cwd: nativeDir } | ||
| ); | ||
| } else { | ||
| // Unix: use tar | ||
| execSync(`tar xzf "${tmpFile}"`, { cwd: nativeDir }); | ||
| } | ||
| fs.unlinkSync(tmpFile); | ||
| // Make executable (Unix only) | ||
| if (process.platform !== "win32") { | ||
| const binPath = path.join(nativeDir, "oneup"); | ||
| fs.chmodSync(binPath, 0o755); | ||
| } | ||
| console.log(`Installed oneup v${version}`); | ||
| } catch (err) { | ||
| console.error(`Failed to install: ${err.message}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| module.exports = main(); |
| #!/bin/sh | ||
| set -e | ||
| REPO="circlesac/oneup" | ||
| INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" | ||
| OS=$(uname -s | tr '[:upper:]' '[:lower:]') | ||
| ARCH=$(uname -m) | ||
| case "$OS-$ARCH" in | ||
| darwin-arm64) TARGET="aarch64-apple-darwin" ;; | ||
| darwin-x86_64) TARGET="x86_64-apple-darwin" ;; | ||
| linux-aarch64) TARGET="aarch64-unknown-linux-gnu" ;; | ||
| linux-x86_64) TARGET="x86_64-unknown-linux-gnu" ;; | ||
| *) echo "Unsupported platform: $OS-$ARCH"; exit 1 ;; | ||
| esac | ||
| VERSION=$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" | grep '"tag_name"' | cut -d'"' -f4) | ||
| URL="https://github.com/$REPO/releases/download/$VERSION/oneup-$TARGET.tar.gz" | ||
| echo "Installing oneup $VERSION..." | ||
| curl -fsSL "$URL" | tar xz -C "$INSTALL_DIR" | ||
| chmod +x "$INSTALL_DIR/oneup" | ||
| echo "Installed to $INSTALL_DIR/oneup" |
+14
| # oneup | ||
| CalVer-based version management for npm packages and Rust crates. | ||
| ## Claude Code Plugin | ||
| ```bash | ||
| /plugin marketplace add circlesac/oneup | ||
| /plugin install oneup | ||
| ``` | ||
| ## License | ||
| MIT |
| --- | ||
| name: oneup | ||
| description: CalVer-based version management with oneup — use when working with versioning, releases, or CI/CD workflows that use oneup | ||
| --- | ||
| # oneup — CalVer Version Management | ||
| oneup calculates the next CalVer version from the registry and writes it to target files. Projects stay versionless in git — oneup fills in the version at release time. | ||
| Install: `npm install -g @circlesac/oneup` or `brew install circlesac/tap/oneup` or `cargo install oneup` | ||
| ## Philosophy | ||
| Versions don't belong in git. They're a release artifact, not source code. | ||
| - `package.json`: omit the `"version"` field entirely (npm allows versionless packages) | ||
| - `Cargo.toml`: use `version = "0.0.0"` (`cargo publish` requires the field to exist — oneup fills it before publish) | ||
| During release, oneup calculates the next version from the registry, writes it to target files, and prints it. Publishing and tagging happen separately in CI. | ||
| ## CLI Reference | ||
| ``` | ||
| oneup version [OPTIONS] | ||
| ``` | ||
| | Option | Description | | ||
| |--------|-------------| | ||
| | `--target <PATH>` | Target file(s) to update — repeatable. Auto-detected if omitted (looks for package.json and Cargo.toml) | | ||
| | `--registry <URL>` | Registry URL override (auto-detected from .npmrc or crates.io) | | ||
| | `--format <FMT>` | Version format using CalVer tokens. Default: `YY.MM.MICRO` | | ||
| | `--dry-run` | Show what would happen without making changes | | ||
| | `--verbose` | Print detailed debug output | | ||
| ## CalVer Format | ||
| Tokens: `YYYY` (full year), `YY` (short year), `MM` (month 1-12), `DD` (day 1-31), `MICRO` (auto-incrementing counter) | ||
| Rules: | ||
| - Separator must be `.` (dot only) | ||
| - MICRO must be last if present | ||
| - At least one date component required | ||
| - Auto-pads to 3 components for semver compatibility (e.g. `YY.MM` → `26.2.0`) | ||
| Common formats: | ||
| - `YY.MM.MICRO` → 26.2.5 (default — year.month.patch) | ||
| - `YYYY.MM.DD.MICRO` → 2026.2.17.0 | ||
| - `YY.MM` → 26.2.0 (monthly, no counter) | ||
| ## How Version Bumping Works | ||
| With MICRO: queries the registry for versions matching today's date prefix, finds the highest MICRO, increments by 1 (starts at 0 if none exist). | ||
| Without MICRO: uses today's date as the version. If it already exists in the registry, no change. | ||
| oneup prints the new version to stdout on success. | ||
| ## CI Usage | ||
| In a release workflow, oneup writes the version, then you publish and tag: | ||
| ```bash | ||
| VERSION=$(npx --yes @circlesac/oneup version | tail -1) | ||
| npm publish | ||
| git tag "v$VERSION" && git push origin "v$VERSION" | ||
| ``` | ||
| `tail -1` is needed because `npx` may print installation messages before the version output. oneup always prints the version as the last line of stdout. | ||
| No commits needed — the tag points at the source commit. |
+11
-3
| { | ||
| "author": "", | ||
| "bin": { | ||
@@ -10,2 +9,6 @@ "oneup": "bin/oneup" | ||
| "description": "CalVer-based version management", | ||
| "files": [ | ||
| "bin", | ||
| "skills" | ||
| ], | ||
| "homepage": "https://github.com/circlesac/oneup#readme", | ||
@@ -20,2 +23,7 @@ "keywords": [ | ||
| "name": "@circlesac/oneup", | ||
| "pi": { | ||
| "skills": [ | ||
| "./skills" | ||
| ] | ||
| }, | ||
| "repository": { | ||
@@ -26,5 +34,5 @@ "type": "git", | ||
| "scripts": { | ||
| "postinstall": "node install.js" | ||
| "postinstall": "node bin/install.js" | ||
| }, | ||
| "version": "26.2.5" | ||
| "version": "26.2.6" | ||
| } |
-87
| const https = require("https"); | ||
| const fs = require("fs"); | ||
| const path = require("path"); | ||
| const { execSync } = require("child_process"); | ||
| const { version } = require("./package.json"); | ||
| const REPO = "circlesac/oneup"; | ||
| const PLATFORMS = { | ||
| "darwin-x64": { artifact: "oneup-x86_64-apple-darwin", ext: ".tar.gz" }, | ||
| "darwin-arm64": { artifact: "oneup-aarch64-apple-darwin", ext: ".tar.gz" }, | ||
| "linux-x64": { artifact: "oneup-x86_64-unknown-linux-gnu", ext: ".tar.gz" }, | ||
| "linux-arm64": { artifact: "oneup-aarch64-unknown-linux-gnu", ext: ".tar.gz" }, | ||
| "win32-x64": { artifact: "oneup-x86_64-pc-windows-msvc", ext: ".zip" }, | ||
| }; | ||
| async function download(url) { | ||
| return new Promise((resolve, reject) => { | ||
| https.get(url, (res) => { | ||
| if (res.statusCode === 302 || res.statusCode === 301) { | ||
| download(res.headers.location).then(resolve).catch(reject); | ||
| return; | ||
| } | ||
| if (res.statusCode !== 200) { | ||
| reject(new Error(`HTTP ${res.statusCode}`)); | ||
| return; | ||
| } | ||
| const chunks = []; | ||
| res.on("data", (chunk) => chunks.push(chunk)); | ||
| res.on("end", () => resolve(Buffer.concat(chunks))); | ||
| res.on("error", reject); | ||
| }); | ||
| }); | ||
| } | ||
| async function main() { | ||
| const platform = `${process.platform}-${process.arch}`; | ||
| const info = PLATFORMS[platform]; | ||
| if (!info) { | ||
| console.error(`Unsupported platform: ${platform}`); | ||
| console.error(`Supported: ${Object.keys(PLATFORMS).join(", ")}`); | ||
| process.exit(1); | ||
| } | ||
| const { artifact, ext } = info; | ||
| const url = `https://github.com/${REPO}/releases/download/v${version}/${artifact}${ext}`; | ||
| console.log(`Downloading ${artifact}...`); | ||
| try { | ||
| const data = await download(url); | ||
| const nativeDir = path.join(__dirname, "bin", "native"); | ||
| if (!fs.existsSync(nativeDir)) { | ||
| fs.mkdirSync(nativeDir, { recursive: true }); | ||
| } | ||
| const tmpFile = path.join(nativeDir, `tmp${ext}`); | ||
| fs.writeFileSync(tmpFile, data); | ||
| if (ext === ".zip") { | ||
| // Windows: use PowerShell to extract zip | ||
| execSync( | ||
| `powershell -Command "Expand-Archive -Force '${tmpFile}' '${nativeDir}'"`, | ||
| { cwd: nativeDir } | ||
| ); | ||
| } else { | ||
| // Unix: use tar | ||
| execSync(`tar xzf "${tmpFile}"`, { cwd: nativeDir }); | ||
| } | ||
| fs.unlinkSync(tmpFile); | ||
| // Make executable (Unix only) | ||
| if (process.platform !== "win32") { | ||
| const binPath = path.join(nativeDir, "oneup"); | ||
| fs.chmodSync(binPath, 0o755); | ||
| } | ||
| console.log(`Installed oneup v${version}`); | ||
| } catch (err) { | ||
| console.error(`Failed to install: ${err.message}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| module.exports = main(); |
Sorry, the diff of this file is not supported yet
Install scripts
Supply chain riskInstall scripts are run when the package is installed or built. Malicious packages often use scripts that run automatically to execute payloads or fetch additional code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed or built. Malicious packages often use scripts that run automatically to execute payloads or fetch additional code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
7368
103.37%6
100%0
-100%15
Infinity%