genid — Short ID Generator

Overview

The genid feature generates YouTube-style random short IDs suitable for opaque identifiers in URLs, filenames, blog slugs, etc. Type genid <length> in Alfred and you get 8 candidate IDs of the requested length; hit ⌘C on any item to copy.

Key properties:

  • Cryptographically strong: backed by secrets.choice(), not random.

  • 57-character URL-safe charset: base62 minus the visually-confusing 0, 1, l, o, O. Capital I is intentionally kept.

  • Length between 6 and 32 (default 16).

  • Safe to read aloud or hand-copy without ambiguity.

Source modules

  • afwf_genpass.genid — the generator. Three public functions:

    • gen_id(length) — generate one random ID by sampling length characters from id_charset via secrets.choice().

    • gen_ids(length) — build an afwf.ScriptFilter containing n_id (8) freshly generated IDs.

    • main(query) — Alfred entry point. Parses query as an int in [id_min_length, id_max_length]; otherwise shows an error item with an autocomplete hint.

  • afwf_genpass.constants — defines id_charset (the 57-char alphabet, declared inline so the exclusions are reviewable in diff), id_min_length=6, id_default_length=16, id_max_length=32, n_id=8, and the UI strings.

  • afwf_genpass.cli — two subcommands wrap genid:

    • Command.genid(query) — Alfred Script Filter; empty query falls back to "16"; exceptions are caught and rendered as an error item that opens the rotating log file on Enter.

    • Command.genid_one(length=id_default_length) — prints exactly one ID to stdout, no Alfred JSON. Suitable for shell pipelines (e.g. slug=$(afwf-genpass genid-one --length 10)).

Alfred workflow definition

The Alfred Script Filter node for genid lives in info.plist, with keyword=genid and argumenttype=1 (optional argument). Its script field invokes:

~/.local/bin/uvx --from "afwf-genpass==X.Y.Z" afwf-genpass genid --query '{query}'
info.plist
  1<?xml version="1.0" encoding="UTF-8"?>
  2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3<plist version="1.0">
  4<dict>
  5	<key>bundleid</key>
  6	<string>MacHu-GWU.generate-secure-password</string>
  7	<key>connections</key>
  8	<dict>
  9		<key>C9643FA2-6BC2-4020-A2D4-4099AF6D58DE</key>
 10		<array/>
 11	</dict>
 12	<key>createdby</key>
 13	<string>Sanhe Hu</string>
 14	<key>description</key>
 15	<string>Generate a Secure Password made easy</string>
 16	<key>disabled</key>
 17	<false/>
 18	<key>name</key>
 19	<string>afwf_genpass</string>
 20	<key>objects</key>
 21	<array>
 22		<dict>
 23			<key>config</key>
 24			<dict>
 25				<key>alfredfiltersresults</key>
 26				<false/>
 27				<key>alfredfiltersresultsmatchmode</key>
 28				<integer>0</integer>
 29				<key>argumenttreatemptyqueryasnil</key>
 30				<false/>
 31				<key>argumenttrimmode</key>
 32				<integer>0</integer>
 33				<key>argumenttype</key>
 34				<integer>1</integer>
 35				<key>escaping</key>
 36				<integer>68</integer>
 37				<key>keyword</key>
 38				<string>genpass</string>
 39				<key>queuedelaycustom</key>
 40				<integer>3</integer>
 41				<key>queuedelayimmediatelyinitially</key>
 42				<true/>
 43				<key>queuedelaymode</key>
 44				<integer>1</integer>
 45				<key>queuemode</key>
 46				<integer>1</integer>
 47				<key>runningsubtext</key>
 48				<string>please wait ...</string>
 49				<key>script</key>
 50				<string>~/.local/bin/uvx --from "afwf-genpass==0.1.2" afwf-genpass genpass --query '{query}'
 51# ~/Documents/GitHub/afwf_genpass-project/.venv/bin/afwf-genpass genpass --query '{query}'</string>
 52				<key>scriptargtype</key>
 53				<integer>0</integer>
 54				<key>scriptfile</key>
 55				<string></string>
 56				<key>subtext</key>
 57				<string>Generate a secure password</string>
 58				<key>title</key>
 59				<string>genpass</string>
 60				<key>type</key>
 61				<integer>0</integer>
 62				<key>withspace</key>
 63				<true/>
 64			</dict>
 65			<key>type</key>
 66			<string>alfred.workflow.input.scriptfilter</string>
 67			<key>uid</key>
 68			<string>C9643FA2-6BC2-4020-A2D4-4099AF6D58DE</string>
 69			<key>version</key>
 70			<integer>3</integer>
 71		</dict>
 72		<dict>
 73			<key>config</key>
 74			<dict>
 75				<key>alfredfiltersresults</key>
 76				<false/>
 77				<key>alfredfiltersresultsmatchmode</key>
 78				<integer>0</integer>
 79				<key>argumenttreatemptyqueryasnil</key>
 80				<false/>
 81				<key>argumenttrimmode</key>
 82				<integer>0</integer>
 83				<key>argumenttype</key>
 84				<integer>1</integer>
 85				<key>escaping</key>
 86				<integer>68</integer>
 87				<key>keyword</key>
 88				<string>genid</string>
 89				<key>queuedelaycustom</key>
 90				<integer>3</integer>
 91				<key>queuedelayimmediatelyinitially</key>
 92				<true/>
 93				<key>queuedelaymode</key>
 94				<integer>1</integer>
 95				<key>queuemode</key>
 96				<integer>1</integer>
 97				<key>runningsubtext</key>
 98				<string>please wait ...</string>
 99				<key>script</key>
100				<string>~/.local/bin/uvx --from "afwf-genpass==0.1.2" afwf-genpass genid --query '{query}'
101# ~/Documents/GitHub/afwf_genpass-project/.venv/bin/afwf-genpass genid --query '{query}'</string>
102				<key>scriptargtype</key>
103				<integer>0</integer>
104				<key>scriptfile</key>
105				<string></string>
106				<key>subtext</key>
107				<string>Generate Random ID</string>
108				<key>title</key>
109				<string>genid</string>
110				<key>type</key>
111				<integer>0</integer>
112				<key>withspace</key>
113				<true/>
114			</dict>
115			<key>type</key>
116			<string>alfred.workflow.input.scriptfilter</string>
117			<key>uid</key>
118			<string>D5C6FAF4-8EC7-4F6E-842A-50587EDA22A9</string>
119			<key>version</key>
120			<integer>3</integer>
121		</dict>
122		<dict>
123			<key>config</key>
124			<dict>
125				<key>alfredfiltersresults</key>
126				<false/>
127				<key>alfredfiltersresultsmatchmode</key>
128				<integer>0</integer>
129				<key>argumenttreatemptyqueryasnil</key>
130				<false/>
131				<key>argumenttrimmode</key>
132				<integer>0</integer>
133				<key>argumenttype</key>
134				<integer>2</integer>
135				<key>escaping</key>
136				<integer>68</integer>
137				<key>keyword</key>
138				<string>genuuid4</string>
139				<key>queuedelaycustom</key>
140				<integer>3</integer>
141				<key>queuedelayimmediatelyinitially</key>
142				<true/>
143				<key>queuedelaymode</key>
144				<integer>1</integer>
145				<key>queuemode</key>
146				<integer>1</integer>
147				<key>runningsubtext</key>
148				<string>please wait ...</string>
149				<key>script</key>
150				<string>~/.local/bin/uvx --from "afwf-genpass==0.1.2" afwf-genpass genuuid4
151# ~/Documents/GitHub/afwf_genpass-project/.venv/bin/afwf-genpass genuuid4</string>
152				<key>scriptargtype</key>
153				<integer>0</integer>
154				<key>scriptfile</key>
155				<string></string>
156				<key>subtext</key>
157				<string>Generate Random UUID 4</string>
158				<key>title</key>
159				<string>genuuid4</string>
160				<key>type</key>
161				<integer>0</integer>
162				<key>withspace</key>
163				<false/>
164			</dict>
165			<key>type</key>
166			<string>alfred.workflow.input.scriptfilter</string>
167			<key>uid</key>
168			<string>7CF84DAD-33A9-408A-8DA3-107AF4FCC927</string>
169			<key>version</key>
170			<integer>3</integer>
171		</dict>
172	</array>
173	<key>readme</key>
174	<string>This workflow can generate secure password that:
175
176- length is between 8, 32 (you can define it)
177- has at least one lowercase letter
178- has at least one upper letter
179- has at least one digital letter
180- has at least one special character
181- avoid characters like ``1lIoO0`` that is hard to distinguish
182
183Dependencies:
184
185- OS Intel / Arm
186- Python3.7+</string>
187	<key>uidata</key>
188	<dict>
189		<key>7CF84DAD-33A9-408A-8DA3-107AF4FCC927</key>
190		<dict>
191			<key>xpos</key>
192			<real>40</real>
193			<key>ypos</key>
194			<real>240</real>
195		</dict>
196		<key>C9643FA2-6BC2-4020-A2D4-4099AF6D58DE</key>
197		<dict>
198			<key>xpos</key>
199			<real>40</real>
200			<key>ypos</key>
201			<real>30</real>
202		</dict>
203		<key>D5C6FAF4-8EC7-4F6E-842A-50587EDA22A9</key>
204		<dict>
205			<key>xpos</key>
206			<real>40</real>
207			<key>ypos</key>
208			<real>135</real>
209		</dict>
210	</dict>
211	<key>userconfigurationconfig</key>
212	<array/>
213	<key>variablesdontexport</key>
214	<array/>
215	<key>version</key>
216	<string>0.1.1</string>
217	<key>webaddress</key>
218	<string>https://github.com/MacHu-GWU/afwf_genpass-project</string>
219</dict>
220</plist>

Tests

  • tests.test_genid — covers the generator, the ScriptFilter builder, and every branch of main() (valid length, boundary lengths, empty/whitespace query, non-numeric query, out-of-range length). Also asserts that the output charset never contains banned characters.

  • tests.test_cli — the TestGenid and TestOneVariants classes exercise the CLI wrappers, including the genid_one stdout variant.