From 244abdf98346d8eddb5b87fc08b54df433202801 Mon Sep 17 00:00:00 2001 From: bntvllnt <32437578+bntvllnt@users.noreply.github.com> Date: Sun, 27 Sep 2026 19:49:40 +0200 Subject: [PATCH] feat: use the vllnt logo as the Claude plugin icon (0.1.0-canary.4) Claude-Session: https://claude.ai/code/session_01QibzbuYP9NMPNKJdURfxfE --- CHANGELOG.md | 4 ++++ README.md | 2 +- VERSION | 2 +- assets/claude-icon.svg | 10 ---------- assets/vllnt-logo.png | Bin 0 -> 21408 bytes plugins/claude/.claude-plugin/icon.svg | 11 +---------- plugins/claude/.claude-plugin/plugin.json | 2 +- plugins/claude/SOURCE.json | 4 ++-- plugins/codex/SOURCE.json | 2 +- plugins/codex/plugin.json | 2 +- plugins/cursor/.cursor-plugin/plugin.json | 2 +- plugins/cursor/SOURCE.json | 2 +- scripts/sync.py | 19 +++++++++++++++++-- tests/test_sync.py | 9 +++++++++ 14 files changed, 40 insertions(+), 31 deletions(-) delete mode 100644 assets/claude-icon.svg create mode 100644 assets/vllnt-logo.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e1b322..7207dd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 0.1.0-canary.4 + +- Use the vllnt logo as the Claude plugin icon: `assets/vllnt-logo.png` is wrapped by the generator into `.claude-plugin/icon.svg`. + - Remove distribution version numbers from the README so routine version bumps need no README edits; `VERSION` and this changelog remain the version records. - Record the `v0.1.0-canary.3` GitHub prerelease. diff --git a/README.md b/README.md index 81ea789..d89b144 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Then start a new chat and invoke a namespaced skill such as `/vstack:plan-work`. | `upstream.lock.json` | Trusted upstream repository and immutable commit | | `VERSION` | Shared distribution version | | `scripts/sync.py` | Standard-library generator and read-only drift check | -| `assets/claude-icon.svg` | Claude plugin icon, copied into the Claude package as `.claude-plugin/icon.svg` | +| `assets/vllnt-logo.png` | vllnt logo; the generator wraps it as the Claude package's `.claude-plugin/icon.svg` | | `plugins/claude/` | Generated Claude Code native plugin | | `plugins/codex/` | Generated portable Agent Plugin for Codex | | `plugins/cursor/` | Generated Cursor native plugin and principles rule | diff --git a/VERSION b/VERSION index 6cf7a46..cc9a41d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0-canary.3 +0.1.0-canary.4 diff --git a/assets/claude-icon.svg b/assets/claude-icon.svg deleted file mode 100644 index 1f4882c..0000000 --- a/assets/claude-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/vllnt-logo.png b/assets/vllnt-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..10b7149ac2eca1c97c8c58f9200d8cd92b74b117 GIT binary patch literal 21408 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�|7>f2dxAMGv%zFOA3eZmF#D@Lac`1|zGng^sb%ckwoI;T&2(PqIqJYP8 z0Yfy7j*40>U^fs@YCHs&5Ua2O6j>wCY3SM6$DxmYPLKevxfiBV%koig%E`%DsQ6S` za2^4}`wdzCgoTBL6UG%tyRC+XSeGH#aCi<#@kel=HR8CPcG79fKoUMVf1y=ZGqHKt z=`!T7vhTd$#2HIVN9O>1MxO2!r3|eH#*wcCFMZ3hayv5deqi~lBn&2NSb!Ls6={4Q zc?6s|pGXNH?BD6y$wV$En=L3TJzy)f_6W9$!pCEbNld(0P;Q5276(R3A!xB*-vLga zg*(XsM-QKq6XsTopd1ike6v{)O#t?*uWM*%xS`w*^VxB5(=kA}*1W^+91WGVGHo2t zDQB%_Zwc1XwFYkn$Vh4g8$mj@97Yk0A&$4Y3&0QEWJc z--uB0?*Zi~4sHZ9)BruBbN708d)ULp#l?N&P*$cwU4RQ!+raagtajmc>J*Kdb*}Eg zBK-5(!UvaiAFV7Z!Ld7lPx2G0TIGUM)ntLvR?u`wjhM>tXF~%Y6~#2NOoM}!L5c?N zq+8@DsOBeEJUz9qzIsJ}<;jy6l>7I^QEnmsj*5+P)e8;fN(1Wu{`dbMx8(w!zj=9C Zmpp-H{YrWQo@0q3A|Uyu@U^zr{{fu8zXt#S literal 0 HcmV?d00001 diff --git a/plugins/claude/.claude-plugin/icon.svg b/plugins/claude/.claude-plugin/icon.svg index 1f4882c..e112555 100644 --- a/plugins/claude/.claude-plugin/icon.svg +++ b/plugins/claude/.claude-plugin/icon.svg @@ -1,10 +1 @@ - - - - - - - - - - + diff --git a/plugins/claude/.claude-plugin/plugin.json b/plugins/claude/.claude-plugin/plugin.json index 204a497..8564a6a 100644 --- a/plugins/claude/.claude-plugin/plugin.json +++ b/plugins/claude/.claude-plugin/plugin.json @@ -13,5 +13,5 @@ "license": "MIT", "name": "vstack", "repository": "https://github.com/vllnt/stack", - "version": "0.1.0-canary.3" + "version": "0.1.0-canary.4" } diff --git a/plugins/claude/SOURCE.json b/plugins/claude/SOURCE.json index 7cf958e..29fb7a8 100644 --- a/plugins/claude/SOURCE.json +++ b/plugins/claude/SOURCE.json @@ -1,7 +1,7 @@ { "files": { - ".claude-plugin/icon.svg": "dc3b420724330eed1296c63c5c6d3290fa031d0eceb39180a2258f6992c76108", - ".claude-plugin/plugin.json": "ff44d6e276f70392c84dcfa3cf86f33ce5001ab864781dae8adbadbc90102689", + ".claude-plugin/icon.svg": "0b4b639f6df841b4904ec0cd9f6d38131c6373ce4a52a1e7fe6452a37598d7f1", + ".claude-plugin/plugin.json": "4808262e4a7a3e327124bfd2b6e23590f33502b981cfcc4e893be02674ab4a53", "LICENSE": "24ba061a4603738ddd5105ef4abc198eeded5ac7efce23b360561816f4dd6559", "skills/build-landing-page/README.md": "46a280eadac8962180cf3f0c42eb0e845a3b0156a644569182d932881e1d51f8", "skills/build-landing-page/SKILL.md": "b08e4963d6149f3647b28a0d9dccdc8793812abab95a1d081d93699e142de0f0", diff --git a/plugins/codex/SOURCE.json b/plugins/codex/SOURCE.json index ce064ad..f10d7d2 100644 --- a/plugins/codex/SOURCE.json +++ b/plugins/codex/SOURCE.json @@ -1,7 +1,7 @@ { "files": { "LICENSE": "24ba061a4603738ddd5105ef4abc198eeded5ac7efce23b360561816f4dd6559", - "plugin.json": "aea0fdbea75ce7f02be70116bf560bcffc31258b6def32b79d302f2aee307dd4", + "plugin.json": "789b793f660535ffddadde5268e5d776ea9a76db6b4809014eb71537d877f235", "skills/build-landing-page/README.md": "46a280eadac8962180cf3f0c42eb0e845a3b0156a644569182d932881e1d51f8", "skills/build-landing-page/SKILL.md": "b08e4963d6149f3647b28a0d9dccdc8793812abab95a1d081d93699e142de0f0", "skills/build-landing-page/references/copywriting-formulas.md": "6d19f6166e1badcfdda0af4f8b303160e94ee6e6149321157e12849654cc013e", diff --git a/plugins/codex/plugin.json b/plugins/codex/plugin.json index 9569b5b..ab43f83 100644 --- a/plugins/codex/plugin.json +++ b/plugins/codex/plugin.json @@ -6,5 +6,5 @@ "description": "Evidence-led engineering workflows to plan, build, review, and ship software with AI agents. Part of the vllnt universe: open, sovereign tools for freedom by design (vllnt.com).", "license": "MIT", "name": "vstack", - "version": "0.1.0-canary.3" + "version": "0.1.0-canary.4" } diff --git a/plugins/cursor/.cursor-plugin/plugin.json b/plugins/cursor/.cursor-plugin/plugin.json index d93bf60..8dcbac1 100644 --- a/plugins/cursor/.cursor-plugin/plugin.json +++ b/plugins/cursor/.cursor-plugin/plugin.json @@ -5,5 +5,5 @@ "description": "Evidence-led engineering workflows to plan, build, review, and ship software with AI agents. Part of the vllnt universe: open, sovereign tools for freedom by design (vllnt.com).", "license": "MIT", "name": "vstack", - "version": "0.1.0-canary.3" + "version": "0.1.0-canary.4" } diff --git a/plugins/cursor/SOURCE.json b/plugins/cursor/SOURCE.json index b2c3d24..2c247bb 100644 --- a/plugins/cursor/SOURCE.json +++ b/plugins/cursor/SOURCE.json @@ -1,6 +1,6 @@ { "files": { - ".cursor-plugin/plugin.json": "3fbf8954a01a9f6a73fec13119d07eaa08e465fb3ac59c27cf711685cdd860f3", + ".cursor-plugin/plugin.json": "b4325fd2a33221ef271b6b92d621c9c62052b6bd6f468b567d47401fe35ee2ea", "LICENSE": "24ba061a4603738ddd5105ef4abc198eeded5ac7efce23b360561816f4dd6559", "rules/vstack-principles.mdc": "5234bc0506e0a328d6163cd83785d2f37dd1fc23ef84287d71e03b92459e064a", "skills/build-landing-page/README.md": "46a280eadac8962180cf3f0c42eb0e845a3b0156a644569182d932881e1d51f8", diff --git a/scripts/sync.py b/scripts/sync.py index 6320550..dd6dac1 100644 --- a/scripts/sync.py +++ b/scripts/sync.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse +import base64 import gzip import hashlib import io @@ -12,6 +13,7 @@ import re import selectors import shutil +import struct import subprocess import tarfile import tempfile @@ -24,7 +26,7 @@ HOMEPAGE = "https://vllnt.com" DESCRIPTION = ("Evidence-led engineering workflows to plan, build, review, and ship software with AI agents. " "Part of the vllnt universe: open, sovereign tools for freedom by design (vllnt.com).") -CLAUDE_ICON = ROOT / "assets" / "claude-icon.svg" +CLAUDE_ICON = ROOT / "assets" / "vllnt-logo.png" HOSTS = ("claude", "codex", "cursor") PRINCIPLES = tuple(f"vllnt-{name}-principles" for name in ("thinking", "orchestration", "collaboration")) MAX_ARCHIVE = 32 * 1024 * 1024 @@ -217,6 +219,19 @@ def payload(files: dict[str, bytes]) -> tuple[dict[str, bytes], bytes]: return skills, rule.encode() +def icon_svg(png: bytes) -> bytes: + """Wrap a square PNG in the SVG file Claude's plugin directory looks for.""" + if png[:8] != b"\x89PNG\r\n\x1a\n": + raise Invalid("Claude icon must be a PNG") + width, height = struct.unpack(">II", png[16:24]) + if width != height or width < 128: + raise Invalid("Claude icon must be square and at least 128px") + data = base64.b64encode(png).decode() + return (f'\n').encode() + + def build(files: dict[str, bytes], lock: dict, version: str) -> dict[str, bytes]: if not re.fullmatch(r"\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?", version): raise Invalid("VERSION must contain a semantic version") @@ -235,7 +250,7 @@ def build(files: dict[str, bytes], lock: dict, version: str) -> dict[str, bytes] "cursor": ".cursor-plugin/plugin.json"}[host] package = {**skills, "LICENSE": files["LICENSE"], manifest_path: encoded(manifest)} if host == "claude": - package[".claude-plugin/icon.svg"] = CLAUDE_ICON.read_bytes() + package[".claude-plugin/icon.svg"] = icon_svg(CLAUDE_ICON.read_bytes()) if host == "cursor": package["rules/vstack-principles.mdc"] = rule package["SOURCE.json"] = encoded({"upstream": lock, "files": { diff --git a/tests/test_sync.py b/tests/test_sync.py index 081f8b3..0f36d2c 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -4,6 +4,7 @@ import io import json from pathlib import Path +import struct import subprocess import tarfile import tempfile @@ -54,6 +55,7 @@ def test_deterministic_standalone_packages_and_provenance(self): self.assertEqual("rules/vstack-principles.mdc" in package, host == "cursor") self.assertEqual(package["LICENSE"], files["LICENSE"]) self.assertEqual(".claude-plugin/icon.svg" in package, host == "claude") + self.assertIn(b"data:image/png;base64,", first["plugins/claude/.claude-plugin/icon.svg"]) claude = json.loads(first[".claude-plugin/marketplace.json"]) codex = json.loads(first[".agents/plugins/marketplace.json"]) cursor = json.loads(first[".cursor-plugin/marketplace.json"]) @@ -70,6 +72,13 @@ def test_deterministic_standalone_packages_and_provenance(self): self.assertNotIn("repository", manifests["codex"]) self.assertNotIn("repository", manifests["cursor"]) + def test_claude_icon_requires_square_png(self): + png = lambda w, h: b"\x89PNG\r\n\x1a\n" + b"\0\0\0\rIHDR" + struct.pack(">II", w, h) + self.assertIn(b'viewBox="0 0 256 256"', sync.icon_svg(png(256, 256))) + for bad in (png(256, 128), png(64, 64), b"" + bytes(32)): + with self.assertRaises(sync.Invalid): + sync.icon_svg(bad) + def test_added_and_removed_workflows(self): files = source() files["workflows/another-task/SKILL.md"] = skill("another-task")