ImgBin is a TypeScript CLI for generating image assets, importing existing images into a managed library, writing searchable metadata, searching managed libraries, creating thumbnails, and running local Claude CLI image metadata analysis.
- Node.js 20+
- Access to an image generation HTTP API for
generate - A local
claudeCLI installation forannotate/--annotate
npm install
npm run buildDuring local development you can run the CLI without building:
npm run dev -- --helpYou can bootstrap local configuration from the checked-in example:
cp .env.example .envImgBin includes a GitHub Actions based npm publishing workflow for both prerelease and stable channels, plus a GitHub Release Drafter workflow that keeps the next stable release in draft form.
- Pushes to
mainpublish a unique prerelease build to the npmdevdist-tag. - Pushes to
mainalso refresh the GitHub draft release notes through Release Drafter. - Stable releases publish only when a GitHub draft release for tag
vX.Y.Zis published and target the npmlatestdist-tag. - The stable release workflow fails if the release tag version does not exactly match
package.json.
ImgBin now mirrors the Release Drafter pattern already used in repos/hagicode-desktop.
- Merge PRs into
mainwith the appropriate release labels (major,minor,patch,feature,bug,docs, and related categories). - Let
repos/imgbin/.github/workflows/release-drafter.ymlrefresh the draft release notes in GitHub Releases. - Review the draft release in the GitHub UI.
- If the release is not ready, continue merging fixes or delete the draft release directly in GitHub.
- When ready, publish the draft release in GitHub. That
release.publishedevent triggers the stable npmlatestpublish workflow.
Release Drafter manages the draft notes only. Draft review, delete, and publish remain native GitHub Release operations; ImgBin intentionally does not add a custom draft lifecycle script on top.
Before the workflows can publish successfully:
- configure npm trusted publishing for the
HagiCode-org/imgbinGitHub repository, - ensure the publishing package owner has access to the
@hagicode/imgbinpackage on npm, and - keep GitHub Actions enabled for the repository.
The workflows are designed to publish with GitHub OIDC identity and provenance, not a long-lived NPM_TOKEN.
Keep the trusted publisher configuration pointed at the repository's single publish workflow file.
Before publishing a stable draft release, run the same checks used by CI:
npm run build
npm test
npm run pack:checkFor a stable release:
- update
package.jsonto the target stable version, - make sure the Release Drafter draft uses the matching tag such as
v0.1.0, and - publish that draft release from the GitHub UI.
The stable publish workflow checks out the published release tag and validates that it still matches package.json before running npm publish --tag latest.
- If the draft notes are empty or mis-categorized, check the merged PR labels against
repos/imgbin/.github/release-drafter.yml. - If
latestdid not publish after releasing the draft, inspectrepos/imgbin/.github/workflows/npm-publish-dev.ymlfor therelease.publishedrun. - If the workflow reports a version mismatch, compare the published release tag with
package.jsonand rerun after correcting the version source of truth. - If you need to discard a pending stable release, delete the draft release in GitHub before publishing it.
ImgBin now matches the Azure image-generation request format that was previously used in repos/site/scripts/generate-image.sh.
That means the current recommended setup is:
- configure Azure image generation for output,
- configure a local metadata-analysis model for the Claude-compatible CLI step, and
- run
imgbin generatedirectly or call it through the site wrapper.
Put this in repos/imgbin/.env:
# Azure image generation
IMGBIN_IMAGE_API_URL="https://<resource>.openai.azure.com/openai/deployments/<deployment>/images/generations?api-version=<version>"
IMGBIN_IMAGE_API_KEY="<azure-api-key>"
# Optional fallback names also supported by ImgBin
# AZURE_ENDPOINT="https://<resource>.openai.azure.com/openai/deployments/<deployment>/images/generations?api-version=<version>"
# AZURE_API_KEY="<azure-api-key>"
# Metadata analysis model for the local Claude-compatible CLI
IMGBIN_ANALYSIS_API_MODEL="glm-5"
# Optional runtime tuning
IMGBIN_DEFAULT_OUTPUT_DIR="./library"
IMGBIN_IMAGE_API_TIMEOUT_MS="60000"Notes:
IMGBIN_IMAGE_API_URL/IMGBIN_IMAGE_API_KEYare the preferred names.AZURE_ENDPOINT/AZURE_API_KEYare accepted as compatibility fallbacks.- GPT Image is used only for image generation.
- Metadata still comes from the local Claude-compatible analysis step.
IMGBIN_IMAGE_API_URL: required forgenerateand batch jobs that create new imagesIMGBIN_IMAGE_API_KEY: optional bearer token for the image APIIMGBIN_IMAGE_API_MODEL: optional model identifier stored in metadataIMGBIN_IMAGE_API_TIMEOUT_MS: optional timeout override, defaults to60000AZURE_ENDPOINT: compatibility fallback forIMGBIN_IMAGE_API_URLAZURE_API_KEY: compatibility fallback forIMGBIN_IMAGE_API_KEY
IMGBIN_ANALYSIS_CLI_PATH: optional local Claude executable path; defaults toclaudeIMGBIN_ANALYSIS_API_MODEL: preferred model identifier for ImgBin's local Claude analysisANTHROPIC_MODEL: fallback shared Claude model identifier used whenIMGBIN_ANALYSIS_API_MODELis not setIMGBIN_ANALYSIS_TIMEOUT_MS: optional timeout override for the local Claude process, defaults to60000IMGBIN_ANALYSIS_PROMPT_PATH: optional override for the bundled default prompt file
If IMGBIN_ANALYSIS_PROMPT_PATH is not set, ImgBin falls back to prompts/default-analysis-prompt.txt.
If IMGBIN_ANALYSIS_API_MODEL is empty, ImgBin falls back to ANTHROPIC_MODEL.
IMGBIN_DEFAULT_OUTPUT_DIR: optional default output root, defaults to./libraryIMGBIN_THUMBNAIL_SIZE: optional thumbnail size in pixels, defaults to512IMGBIN_THUMBNAIL_FORMAT: optional thumbnail format, defaults towebpIMGBIN_THUMBNAIL_QUALITY: optional thumbnail quality, defaults to82
imgbin generate \
--prompt "A cheerful hand-drawn hero illustration of an AI coding assistant helping a developer at a desk." \
--output ./library \
--annotateWhat happens:
- ImgBin sends an Azure-style image request,
- writes the generated file into a managed asset directory,
- runs the local Claude-compatible metadata analysis step, and
- stores structured metadata in
metadata.json.
imgbin generate \
--prompt "orange dashboard hero for docs" \
--output ./library \
--tag dashboard \
--tag hero \
--annotate \
--thumbnailimgbin generate \
--prompt-file ../docs/src/content/docs/img/product-overview/value-proposition-ai-assisted-coding/prompt.json \
--output ./library \
--annotateImgBin reads the docs prompt file, extracts userPrompt, carries over generation parameters into metadata, and records the prompt file path as prompt provenance.
If image generation already succeeded and you only want to refresh title/tags/description:
imgbin annotate ./library/2026-03/orange-dashboard-hero --overwriteThis is useful after changing IMGBIN_ANALYSIS_API_MODEL or updating the analysis prompt.
imgbin annotate ./library/2026-03/orange-dashboard-heroimgbin annotate ./incoming/launch-hero.png \
--import-to ./library \
--tag imported \
--thumbnailThis copies the source image into a new managed asset directory before writing metadata.json.
imgbin annotate ./library/2026-03/orange-dashboard-hero \
--analysis-prompt ./prompts/custom-analysis-prompt.txt \
--overwriteimgbin thumbnail ./library/2026-03/orange-dashboard-heroSearch matches can use asset title, tags, description, generated prompt text, import provenance, and managed asset paths.
imgbin search \
--library ./library \
--query "orange hero" \
--exactFor typo-tolerant retrieval, switch to fuzzy matching:
imgbin search \
--library ./library \
--query "orng herp" \
--fuzzyTo rebuild the library index before searching:
imgbin search \
--library ./library \
--query "dashboard" \
--reindexTo consume results from scripts:
imgbin search \
--library ./library \
--query "launch hero" \
--jsonImgBin stores the reusable search index at .imgbin/search-index.json under the library root. Existing libraries do not need migration; the index is created lazily on first search and refreshed automatically after generate, import, annotate, and thumbnail operations when possible.
imgbin batch --manifest ./jobs/launch.yaml --output ./libraryimgbin batch --pending-library ./libraryjobs:
- promptFile: ../docs/src/content/docs/img/product-overview/value-proposition-ai-assisted-coding/prompt.json
slug: docs-ai-assisted-coding
tags: [docs, hero]
annotate: true
thumbnail: true
- assetPath: ./incoming/marketing-card.png
importTo: ./library
tags: [marketing, imported]
thumbnail: true
- assetPath: ./library/2026-03/existing-card
overwriteRecognition: true
analysisPromptPath: ./prompts/custom-analysis-prompt.txt
- pendingLibrary: ./libraryEach asset directory stores a metadata.json file with these high-level sections:
source: whether the asset was generated by ImgBin or imported from an external filegenerated: prompt text, provider context, docs prompt provenance, and generation paramsrecognized: local Claude analysis suggestions plus prompt provenancemanual: human-maintained title, tags, or description that take precedence by defaultstatus: per-step status for generation, recognition, and thumbnail creationpaths: relative file paths for original and thumbnail assetstimestamps: creation and update timestamps
Manual fields always win over AI suggestions unless you run an explicit overwrite flow. Recognition failures keep the asset on disk and mark the asset as retryable for later batch processing.
ImgBin does not persist large image base64 blobs such as Azure b64_json into metadata.json.
The actual generated image is stored as the asset file on disk, while metadata keeps only the structured fields and lightweight provider details needed for diagnostics.
ImgBin does not call a remote Claude URL for metadata analysis. Instead, it:
- loads the bundled or overridden analysis prompt,
- passes the selected model to the local
claudeCLI, - asks Claude to inspect the local image file directly from disk, and
- parses the returned JSON into metadata fields.
That means the only required Claude-side runtime setting is a usable model name plus a working local claude command.
The built-in provider is now optimized for the Azure image-generation request format previously used by the site workflow.
{
"prompt": "orange dashboard hero for docs",
"size": "1024x1024",
"quality": "high",
"output_compression": 100,
"output_format": "png",
"n": 1
}- Azure JSON with
data[0].b64_json - Raw image bytes (
Content-Type: image/png, etc.) - JSON with
imageBase64 - JSON with
imageUrl
This repository ignores local build outputs and generated asset libraries by default:
dist/node_modules/.env*library/- temporary test output directories such as
.tmp/and.vitest-temp/
If you want to commit sample assets, place them outside ignored runtime directories and document them explicitly.
npm install
npm run test
npm run build