Skip to content

free-names: generating and checking as one command - #30

Merged
ralyodio merged 1 commit into
masterfrom
worktree-free-names
Aug 29, 2026
Merged

free-names: generating and checking as one command#30
ralyodio merged 1 commit into
masterfrom
worktree-free-names

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Adds free-names and the /names pit alias.

Why a command and not just an alias

generate-names "..." | domainfree is 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 to generate-names -n 100 | domainfree puts the description after domainfree.

Every workaround stores a shell function in a config file — the thing this repo exists to avoid, and something registry.ts already has a test against. So the composition became a command, and the alias stayed thin.

/names rather than /free-names because no alias may share a name with a command; a shell function beats PATH and the two would drift apart. Both existing guards in registry.test.ts still pass unmodified.

What it does

$ free-names "a desktop app that syncs files over rsync with partial and archive" -n 12
archivesteady.com
blockrobust.com
bytequeued.com
mirrorednode.com
partialmirror.com
targetcopied.com
12 generated · openai/gpt-5.6-sol · 12 checked · 6 available · 6 taken

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 generate and check are injectable and the join is testable without a key or a network.

Verification

  • 8 new tests covering only how the halves meet: every candidate checked, list agrees with the counts, an unknown never appears as available, an empty generation makes no registry trip
  • Full suite 499 passed, including the two unmodified alias guards
  • Live run against the real API and RDAP, shown above

Version bumped to 0.13.0 in this commit (new command → minor).

🤖 Generated with Claude Code

https://claude.ai/code/session_01XGe9mWC6FvUjT6p1HCVjba

…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
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

15 finding(s)

HIGH/CRITICAL: 5 | MEDIUM: 1 | LOW: 9

Severity Rule Location
HIGH sh-remote-script-execution root-ubuntu.sh:134
HIGH sh-remote-script-execution root-ubuntu.sh:2597
HIGH sh-remote-script-execution root-ubuntu.sh:2601
HIGH sh-remote-script-execution root-ubuntu.sh:2654
HIGH sh-remote-script-execution root-ubuntu.sh:3683
MEDIUM redos-nested-quantifier src/domain-free.ts:56
LOW secret-generic-credential src/credentials.ts:36
LOW insecure-temp-file test/blog.test.ts:73
LOW insecure-temp-file test/blog.test.ts:74
LOW insecure-temp-file test/credentials.test.ts:43
LOW insecure-temp-file test/credentials.test.ts:44
LOW secret-generic-api-key test/credentials.test.ts:208
LOW insecure-temp-file test/download.test.ts:99
LOW insecure-temp-file test/download.test.ts:100
LOW secret-generic-credential test/shorten.test.ts:36

Snippets are redacted; ThreatCrush never prints matched credential material.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant