Tags: profullstack/cli-tools
Tags
dev2: deploy-app.sh rolls back on any failure after the swap starts (… …0.51.1) (#122) Under set -e, a failed `compose up` or `compose down` exited the script before its health check and rollback ran, so a deploy that had already removed the old container could leave the site down. The rollback path also rebuilt the old revision, which fails the same way when the build is what broke. Now the images the running containers came from are recorded (and pinned as <name>:rollback) before anything is touched, and an ERR trap plus the health check failure both re-tag them and `compose up --no-build`. A failed build exits before the snapshot with the running stack untouched. The subnet grep no longer kills the script when a compose file has no subnet. test/dev2-deploy-app.test.ts drives the script against a fake docker: build failure, failed up, unhealthy image, healthy deploy. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
alchemy: Alchemy's CLI as a command, installed on first use (0.51.0) (#… …121) A launcher for @alchemy/cli in the openmcp shape: everything is passed through, the first run installs into ~/.local/share/cli-tools/vendor/alchemy, --self-update and --self-where are ours. A global copy that is not this wrapper (moshcode install alchemy makes one) is used as it is. That copy is exec'd by its PATH name, not its realpath: under mise the global bin is a shim symlinked to the mise binary, and exec'ing the realpath ran `mise --json ...`. firstOnPath is exported from registry.ts for it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
gh-pulse: a lock that names no pid is stale, not pid 0 (0.49.1) (#114) An empty run.lock read as Number('') = 0, and kill(0, 0) signals our own process group, so it always looked alive: every daily run since 2026-09-24 refused with 'another gh-pulse run is in progress (pid 0)'. The holder is now parsed strictly (positive integer or nothing), isAlive refuses pid <= 0, and the lock is written to a temp file and renamed so a run killed mid-write cannot leave an empty one behind. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
mail send --html: a multipart/alternative message from the CLI (0.48.… …0) (#94) The library already carried an HTML part through SMTP, Resend and the Forward Email defang; only bin/mail.ts had no way to set it. --html P reads a file into that part and the text from --body, --file or stdin stays the plain part. With --html and no --body or --file, piped stdin is still the text; only when nothing is piped does the text fall back to the HTML with its tags stripped, instead of refusing a terminal. The body logic moves into an exported bodiesFrom with an injectable stdin, which the new tests drive. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Document the tea knobs, release 0.47.0 (#93) The header's Environment list is the only place a reader looks for these, and #92 shipped CLI_TOOLS_SKIP_TEA and TEA_CLI_VERSION without adding them to it. A list that omits two of its own knobs is worse than no list: it reads as complete. Bumps to 0.47.0 so the tea install reaches boxes as a release like everything else here. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
icon hq: the optional HQ style, full-colour icons at the OpenEmoji ba… …r (0.45.0) (#84) * icon hq: the optional HQ style, full-colour icons at the OpenEmoji bar UI icons are drawn by gpt-image-2 as edits pinned to their own simple line glyph (first reference: keep silhouette and meaning) and three OpenEmoji masters (the look), with a colour-by-meaning rule so the set spans the spectrum. Stops on credit exhaustion, backs off on 429, never redraws a master. Brands take the owner's colour (Simple Icons hex, or a cited brand page for the nine Font Awesome logos), never a model. Writes hq/png, hq/webp/{64,128}, hq/svg for brands, and an hq block per icon plus styles and hq top-level in openicon.json; icon build preserves it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * icon hq: colour is set per icon, not left to the model; outlines become solid bodies Left to the model the set drifted to one hue (orange with warm references, blue with cool ones). Each category now has its own colour and meaning overrides it (green add/check, coral red delete/error, gold star/key/warning, steel lock). Outlined shapes are filled as solid glass instead of traced as hollow tubes. Style references: laptop, gem, light bulb. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * icon hq: describe form-control keys whose names mislead the model (radio-off drew a radio set) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * icon: 0.45.0 for the HQ style Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Emoji command (#83) * emoji: every standard emoji, drawn by an image model as one set (0.41.0) `emoji generate` draws all 3,963 fully-qualified sequences in Unicode's emoji-test.txt with gpt-image-2 under one art direction. Six anchors are drawn first and every later glyph is an edit that sees them, so the set does not drift; skin-tone variants are edits of their base that change the skin only. Resumable: a master that exists is never redrawn. `emoji build` derives the rest offline: PNGs at 16-512, posterised SVGs (vtracer), CBDT and sbix colour fonts (nanoemoji, via uv), CSS, a preview page and an OpenEmoji manifest (logicsrc.com/openemoji). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * emoji: list every emoji in the manifest, CLDR keywords, webp previews, incremental build The manifest now carries all 3,963 entries; only drawn ones have files, so a catalog can show the whole set while it is being drawn. Keywords come from CLDR annotations (base + derived, matched without FE0F). build writes webp/64 and webp/128 and skips glyphs whose outputs are newer than the master. prompts.jsonl is appended per glyph so a killed run keeps it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * emoji: art direction forbids look-alikes of film, game and brand characters The first People & Body run drew a genie, fairy and merperson close to well-known film designs; the set is CC BY, so every design must be its own. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * emoji export: bundles for 22 networks, verified limits, stickers where emoji are not supported emoji export writes per-network packs sized, encoded and named to each network's documented rules (checked against official docs and source, 2026-09-24): Slack, Discord, Stoat, Mastodon (tootctl tarball), Misskey (meta.json zip), Pleroma/Akkoma (pack.json), Mattermost, Zulip, Rocket.Chat, Teams, Matrix, Telegram emoji and stickers, Signal and WhatsApp (.wastickers) sticker packs, Twitch, YouTube, Reddit, Kick, and X / Bluesky / Threads-Instagram-Facebook-LinkedIn as images to post, with X opening on flags. platforms.json carries the same table for the catalog. Manifest entries gain their oe_ shortcode. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * emoji export: palette PNGs (4x smaller), archives as release assets Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gh-pulse: quiet cron, a clamped spinner, a rescan that rescans (0.36.… …1) (#73) Follow-ups from a review of the busy indicator. The daily run handed its per-ten progress counts to the plain logger when stderr was not a terminal, so every cron.log grew ~70 lines it never had; the counts now ride the spinner only on a terminal and cron prints exactly what it printed before. The command-line spinner clamps its row to the terminal width (an overlong row walked down the screen a row per tick) and stops exactly once (the range path could stop it twice and print the last line twice). In the TUI, `r` finally forces a rescan (force was dropped at the ShowOptions boundary and the hour-fresh cache came back), a "still scanning" notice no longer outlives the scan, and the loading range button uses the ascii frames on a terminal without Unicode, like the spinner line does. Claude-Session: https://claude.ai/code/session_011gfb1vcQH5rf82HfbJvf1Z Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
gh-pulse: throttle the hour (0.36.0) (#72) A run died this morning with GitHub 403, rate limit exceeded, ten repos into the events step, and the spinner kept ticking after the error because the queue went on draining in the background. Four range scans and a daily run in one hour had spent the whole 5,000-call budget the token shares with gh and everything else, and the client's answer to a 403 was to wait at most two minutes, four times, then throw. The GitHub client is now the only place the hour is spent, and it behaves. GH_PULSE_RESERVE calls (default 500) are never spent: down to the reserve, or rate limited anyway, a scan pauses until the hour resets, on one shared pause for every in-flight request, for as long as the headers say, and then carries on. Four requests in flight and 100ms between starts keep it out of the secondary limits; retry-after is honoured. Every reply is cached by ETag under <data>/cache and offered back with If-None-Match, and GitHub does not charge for a 304, so an unchanged page is free; since= is asked from the top of the hour so the URL repeats and a rescan hits the cache, with the exact cutoff applied to the items. Once a task has failed nothing queued behind it starts, and show exits the process when the screen closes, so a crash or a quit no longer spends the rest of the hour in the background. One daily run at a time, through <data>/run.lock. The budget is read off the first real reply's headers, not /rate_limit, which reported a fresh hour for this token while real replies carried 4,695 left. Each scan logs what it has to spend and closes with what was charged, what came from cache and what is left. Measured live on one repo for the last hour: a cold scan charged 20 calls, the warm rescan 0, with 26 answered from cache. Claude-Session: https://claude.ai/code/session_012nnVu9u7HeHEVRoCwKcQM3 Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
PreviousNext