free-names: generating and checking as one command - #30
Merged
Conversation
…nnot be aliased `generate-names "..." | domainfree` has been the documented pairing since both existed, and it is the right shape in a shell. It is the wrong shape for a pit alias: an alias appends what you typed to the end of its expansion, so `/names "a desktop app"` against `generate-names -n 100 | domainfree` puts the description after `domainfree` rather than in front of the generator. The only workarounds store a shell function in a config file, which is the thing this repository exists to avoid — a command on PATH works from every caller with nothing sourced first. So the composition became a command and the alias stayed thin: `/names` → `free-names`. Not `/free-names`, because no alias may share a name with a command; a shell function beats PATH and the two would drift apart. Neither half changes. Vocabulary still comes from one small API call and is expanded locally, availability is still read from RDAP rather than inferred from DNS, and an indeterminate lookup is still never reported as available — the mistake in this command that costs somebody money. The default count is 100 where `generate-names` alone defaults to 1000. The generator prints a line per candidate; this one asks a rate-limited registry about every line it printed, so a thousand turns a ten-second command into a multi-minute one. `-n` is there for when a hundred is not enough. Composed in-process rather than by shelling out, so the join is testable without a key or a network: `generate` and `check` are injectable, and the tests cover only how the halves meet — every candidate is checked, the list of free names agrees with the counts beside it, an unknown never appears as available, and an empty generation does not make a pointless registry trip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XGe9mWC6FvUjT6p1HCVjba
ThreatCrush Security Scan15 finding(s) HIGH/CRITICAL: 5 | MEDIUM: 1 | LOW: 9
Snippets are redacted; ThreatCrush never prints matched credential material. |
This was referenced Aug 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
free-namesand the/namespit alias.Why a command and not just an alias
generate-names "..." | domainfreeis the right shape in a shell and the wrong one in a pit alias. An alias appends what you typed to the end of its expansion, so/names "a desktop app"bound togenerate-names -n 100 | domainfreeputs the description afterdomainfree.Every workaround stores a shell function in a config file — the thing this repo exists to avoid, and something
registry.tsalready has a test against. So the composition became a command, and the alias stayed thin./namesrather than/free-namesbecause no alias may share a name with a command; a shell function beatsPATHand the two would drift apart. Both existing guards inregistry.test.tsstill pass unmodified.What it does
Neither half changes: vocabulary from one small API call expanded locally, availability from RDAP rather than DNS, and an indeterminate lookup never reported as available — the mistake here that costs somebody money.
Default count is 100, not 1000. The generator prints a line per candidate; this asks a rate-limited registry about each one, so a thousand turns a ten-second command into a multi-minute one.
Composed in-process rather than by shelling out, so
generateandcheckare injectable and the join is testable without a key or a network.Verification
Version bumped to 0.13.0 in this commit (new command → minor).
🤖 Generated with Claude Code
https://claude.ai/code/session_01XGe9mWC6FvUjT6p1HCVjba