Found by a blind dogfood run against v0.1.90-21-gf56aa72.
Symptom
Slug derivation drops non-ASCII characters instead of transliterating or rejecting them, so a leading accented letter silently vanishes from the app's permanent public identity.
$ civitai app create "ÜberApp Ω" --dir ./nm-uni -y
✓ Created App "ÜberApp Ω" …
$ grep blockId ./nm-uni/block.manifest.json
"blockId": "berapp"
Ü is dropped rather than becoming u/ue, so ÜberApp becomes berapp — a word that is not a truncation, a transliteration, or anything the author typed.
Why it matters
blockId is not cosmetic. Per the README the app is served at https://<blockId>.civit.ai/, and it is the identity every later command takes (app status <slug>, app metrics <slug>, app listing …). It is effectively permanent once submitted. Getting it silently wrong at create time is expensive to discover and awkward to undo.
Civitai has a large international user base, so accented and non-Latin app names are not an edge case.
Second, compounding problem: --dir never echoes the derived slug
$ civitai app create "Slug Check" --dir ./slugcheck -y
✓ Created App "Slug Check" (page-money) · ./slugcheck/ · 35 files
No line of output contains the slug. With the default directory you can infer it from the directory name; with --dir it is invisible unless you open block.manifest.json. So the one case where derivation is most likely to surprise you is the case where it is least visible.
The adjacent behaviour is already good
The cases that do error are handled well, which is what makes the silent path stand out:
$ civitai app create "123 Numbers"
Error: derived slug "123-numbers" is invalid (must start with a letter, be lowercase, hyphen-separated)
$ civitai app create "!!!"
Error: cannot derive a valid slug from "!!!" (need ≥3 chars; use lowercase letters/numbers/hyphens)
Both name the rule and the constraint. The non-ASCII path just needs to reach the same standard.
Suggested fix
Two independent changes; either alone is an improvement.
-
Echo the derived blockId in app create's success output, always — not only when it is inferable from the directory. It is one line and it is the value the author will use in every subsequent command.
-
Do not silently drop characters. Options, in rough order of preference:
- transliterate to ASCII (
Ü → u, Ω → o/omega) and show what was derived;
- or refuse, in the style of the two errors above, naming the offending characters and suggesting an explicit slug flag.
Whichever is chosen, the author should see the result before 35 files are written. If a --slug-style override does not exist, that is the natural escape hatch.
Test coverage this needs
"ÜberApp Ω" must not produce berapp — pin the actual expected slug, whatever the chosen policy is.
- A pure-ASCII name must derive exactly as it does today (control).
- The two existing error cases (
"123 Numbers", "!!!") must keep their messages and exit codes (controls).
app create --dir <somewhere> output must contain the derived slug — assert the string, since this is the half that makes the bug invisible.
Found by a blind dogfood run against
v0.1.90-21-gf56aa72.Symptom
Slug derivation drops non-ASCII characters instead of transliterating or rejecting them, so a leading accented letter silently vanishes from the app's permanent public identity.
Üis dropped rather than becomingu/ue, soÜberAppbecomesberapp— a word that is not a truncation, a transliteration, or anything the author typed.Why it matters
blockIdis not cosmetic. Per the README the app is served athttps://<blockId>.civit.ai/, and it is the identity every later command takes (app status <slug>,app metrics <slug>,app listing …). It is effectively permanent once submitted. Getting it silently wrong atcreatetime is expensive to discover and awkward to undo.Civitai has a large international user base, so accented and non-Latin app names are not an edge case.
Second, compounding problem:
--dirnever echoes the derived slugNo line of output contains the slug. With the default directory you can infer it from the directory name; with
--dirit is invisible unless you openblock.manifest.json. So the one case where derivation is most likely to surprise you is the case where it is least visible.The adjacent behaviour is already good
The cases that do error are handled well, which is what makes the silent path stand out:
Both name the rule and the constraint. The non-ASCII path just needs to reach the same standard.
Suggested fix
Two independent changes; either alone is an improvement.
Echo the derived
blockIdinapp create's success output, always — not only when it is inferable from the directory. It is one line and it is the value the author will use in every subsequent command.Do not silently drop characters. Options, in rough order of preference:
Ü→u,Ω→o/omega) and show what was derived;Whichever is chosen, the author should see the result before 35 files are written. If a
--slug-style override does not exist, that is the natural escape hatch.Test coverage this needs
"ÜberApp Ω"must not produceberapp— pin the actual expected slug, whatever the chosen policy is."123 Numbers","!!!") must keep their messages and exit codes (controls).app create --dir <somewhere>output must contain the derived slug — assert the string, since this is the half that makes the bug invisible.