feat(integrations): add Streamlit UI wrapper for the humanizer skill#102
Closed
Rich627 wants to merge 6 commits into
Closed
feat(integrations): add Streamlit UI wrapper for the humanizer skill#102Rich627 wants to merge 6 commits into
Rich627 wants to merge 6 commits into
Conversation
Paste text → click Humanize → get the final rewritten prose back. The wrapper shells out to the local `claude` CLI with a prompt that invokes the humanizer skill but suppresses its usual draft / audit / summary output, leaving only the rewritten text for copy-paste workflows. Two ways to run: - Local: ./run.sh (venv + streamlit) - Docker: docker compose up --build (mounts ~/.claude for skill + auth) No API key required — uses the host's existing Claude Code login. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
README now explains: - exactly when the `claude` subprocess starts/stops (per-click one-shot) - OAuth (`claude /login`) vs ANTHROPIC_API_KEY, including the macOS Docker keychain caveat and how to work around it - what guarantees the output stays free of draft/audit/summary noise app.py adds a `_clean_output()` pass that strips leaked preambles and trailing "Summary of changes" blocks, and replaces the streamed view with a copy-friendly textarea once generation finishes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Output now renders via st.code (wrap_lines=True) so it has a native copy-to-clipboard icon in the top-right corner. - Add a visible "Running humanizer skill…" status message + spinner so users know work is in progress instead of only seeing the tiny Stop button in the Streamlit header. - Streaming response is preserved — text appears live as it arrives, then gets replaced by the copy-ready code block on completion. - README's Lifecycle section now spells out exactly how to stop: Ctrl+C for local, docker compose down / stop / kill for container, and notes that closing the browser tab alone doesn't stop Streamlit or the subprocess (which will self-terminate within seconds anyway). - Bump streamlit minimum to 1.56 (wrap_lines support + general latest). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bundles the code-review + security-review fixes with a couple of usability nits reported during testing. Correctness: - Tighten `_TRAILING_RE` so it only strips the humanizer skill's actual trailer blocks (bolded "Summary of changes" / "Changes made" / "What makes … AI …" / "Draft rewrite" / "Now make it not …", with or without a leading `---` separator). Previous pattern ate any paragraph whose first word was "Notes" / "Summary" / "Changes" — a real problem for a humanizer whose job is preserving user prose. - Add `--no-session-persistence` to the `claude -p` call so no session file is written to disk, guaranteeing each click is fully stateless with zero possibility of one run's context leaking into the next. Resource hygiene: - Register atexit exactly once via `@st.cache_resource` instead of per click. Previous code appended a new atexit hook to every Humanize press for the life of the Streamlit process. Docker hardening: - Dockerfile now creates an unprivileged `app` user (uid 1000), chowns /app, and runs Streamlit + claude CLI as that user. Previously ran as root, so a dependency bug could write host files as uid 0 via the ~/.claude mount. - docker-compose.yml binds the published port to 127.0.0.1 only so the unauthenticated UI isn't exposed to the LAN by default, and adjusts the mount target + HOME to the new non-root home. UX: - Status message no longer wraps "claude -p" in backticks (rendered as tiny inline code and broke mid-sentence in the info block). Plain English now. - README: new Security considerations section covering the port bind, the ~/.claude mount trust boundary, the non-root user, and the single-user scope. Lifecycle section mentions --no-session-persistence explicitly so users don't worry about state leaking between clicks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The `claude -p` text mode doesn't actually deliver token-by-token streaming through the PIPE in a way Streamlit's write_stream can render incrementally, so the "streaming" UX was a lie. Swap in a plain `proc.communicate()` inside st.spinner, render once on completion via st.code (which still has the native copy button). Also update README — lifecycle table + Output section no longer claim text "streams in live". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The app supports both OAuth login and ANTHROPIC_API_KEY paths, so phrasing the caption as "No API key required" understates the API-key path and can mislead users who already have a key set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner
|
Appreciate the effort on this. Closing because a Streamlit + Docker web UI is a maintenance commitment separate from the skill prompt itself, and out of scope for this repo. It'd make a great standalone project that depends on the skill. |
duathron
added a commit
to duathron/humanizer-ext
that referenced
this pull request
May 27, 2026
5 OQs from the seed-catalogue extraction answered + appended to docs/de-seed-catalogue.md as a binding decisions log for Task 5 + Task 6: - OQ1: build DE blader#7 via Opus + Wikipedia-AI-Cleanup-Editor manual curation - OQ2: include all 3 DE-only patterns (blader#102 Konjunktiv II, blader#103 Anglizismen, blader#104 Nominalstil) - OQ3: exclude all 6 Wikipedia-context-only entries from patterns/de.md - OQ4: include EN-PARALLEL blader#8 with DE forms (gilt als / dient als / etc.); verify in Task 5 mining - OQ5: defer universal pattern DE-token extensions to Task 6 follow-up Numbering reshuffle: blader#100 + blader#101 reserved for prose-applicable DE-only patterns surfaced during Task 5; blader#102 + blader#103 + blader#104 firm assignments per OQ2. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
duathron
added a commit
to duathron/humanizer-ext
that referenced
this pull request
May 28, 2026
…ources (Phase 2 Task 4) All $0 sources per maintainer /goal 'minimize Phase 2 Task 4 budget'. Source A (Wikipedia DE AI-Cleanup tagged articles, 30 docs, CC-BY-SA-3.0): Real-world DE prose flagged by humans as AI-suspected via the Vorlage:KI-generiert template. Fetched via embeddedin API (50+ tagged articles available; sampled 30 with fixed seed 42). Mix of substantial AI tells and borderline cases — human-verified suspect baseline. Examples: Sara Noxx, Digitales Schlafmonitoring, Synthetische Daten, Verband evangelischer Pfarrerinnen und Pfarrer, Moonton, Hybridtechnik. Source B (Claude CLI subscription generation, 90 docs, MIT): 6 domains × 5 topics × 3 models (sonnet/haiku/opus) = 90 samples via `claude -p` subscription ($0). DE prompt templates ask for stereotypical AI-style content. Cross-model variation for intra-Anthropic idiolect diversity. ANTHROPIC_API_KEY stripped from subprocess env per _shared.run_skill convention. Source C (Opus main-thread inline synthesis, 12 docs, MIT): 2 samples per domain × 6 domains. Engineered to exercise specific DE tells: blader#7 AI vocabulary, blader#102 Konjunktiv II stacking, blader#103 Anglizismen-Leakage, blader#104 Nominalstil-Inflation, plus EN-parallels blader#22/blader#10/blader#15/blader#16/blader#23/blader#24/ blader#32/blader#36/blader#37. Act as calibration anchors for per-pattern eval testing. Total: 132 docs / 728 KB. Comfortably exceeds plan target of 75-100. Sufficient signal volume for Task 5 mine_patterns.py LLR scoring against the 46-doc human corpus (340 KB). AI/human ratio 2.1× by docs, 2.1× by KB. All redistributable license (CC-BY-SA-3.0 for Wikipedia, MIT for Anthropic- generated + Opus inline). No fair-use research-only content needed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
duathron
added a commit
to duathron/humanizer-ext
that referenced
this pull request
May 28, 2026
…up consensus Mined the DE corpus (132 AI / 46 human docs) via mine_patterns.py LLR scoring. Top 100 candidates routed through 3-voice writer persona panel (Academic + Marketing Copywriter + Journalist) for ✓/✗/◐ vote per ngram. Consolidated keep-list at docs/de-mined-patterns.md (saved this commit): Strong consensus (unanimous ✓) — into patterns/de.md Task 6: blader#7 DE AI Vocabulary additions: darüber hinaus, zusammenfassend, ganzheitliche, vorliegenden, der vorliegenden, umfassende (cluster only), darstellt blader#100 (NEW reserved DE-only): Anchor: 'im Rahmen der vorliegenden [Arbeit/Studie/Untersuchung]' DE academic-frame boilerplate — no EN equivalent, highest LLR among DE-only candidates (rank blader#32, LLR 31.97, 31:0 ratio) blader#101 (NEW reserved DE-only): Anchor: '[es/zusammenfassend] lässt sich [sagen/feststellen/festhalten]' DE impersonal-reflexive AI hedge — no EN equivalent, multiple high-LLR forms (lässt sich rank blader#5 LLR 93.73; zusammenfassend lässt sich sagen rank blader#29 LLR 33.00) blader#12 DE meta-commentary extensions: zusammenfassend, wichtig zu (beachten/betonen), full blader#101 family Cluster-only (◐ ADJUST) — flag with threshold logic: zentrale Rolle, umfassende, implementierung (non-tech), überzeugt (unanchored) Skip (artifacts + common DE): hedging (metadata), queens (Wikipedia bleed), substantivketten / übergänge (Source C body refs), dass / es / sich / ich / meine / bin / mich (common DE function words / first-person genre artifact) Mining-script bug noted for v3.6.0: YAML frontmatter strip catches headers but Opus inline synthesis demonstrably references metadata terms in body (tells_targeted leaks via prose). Workaround: drop tells_targeted from synthesis frontmatter next pass. OQ assignments updated: blader#100 reassigned from 'first prose-applicable DE-only Wiki pattern surfaced during mining' (per maintainer doc) to the academic-frame boilerplate discovered as highest-LLR DE-only signal blader#101 reassigned to impersonal-reflexive Nominalstil sub-pattern blader#102/blader#103/blader#104 remain Konjunktiv II / Anglizismen / Nominalstil per maintainer OQ2 decision (still open for Task 6 implementation) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
duathron
added a commit
to duathron/humanizer-ext
that referenced
this pull request
May 28, 2026
878-line German pattern pack mirroring patterns/en.md structure + extending with 5 DE-only patterns (blader#100-blader#104) per maintainer decisions + Task 5 mining consensus. EN-PARALLEL patterns (translated to DE with DE-specific trigger words + before/after examples): blader#1, blader#2, blader#3, blader#4, blader#5, blader#7, blader#8, blader#9, blader#10, blader#11, blader#12, blader#13, blader#16, blader#20, blader#21, blader#22, blader#23, blader#24, blader#27, blader#28, blader#30, blader#31, blader#32, blader#33, blader#34, blader#35, blader#36, blader#37 (28 patterns). DE-only patterns (blader#100-blader#104, no EN equivalent): blader#100 Akademische Rahmen-Floskel — 'im Rahmen der vorliegenden [Arbeit/Studie/Untersuchung/Analyse]' bureaucratic self-reference. Mining-derived (LLR 31.97, 31:0 AI:human). blader#101 Impersonales Reflexiv — '[es/zusammenfassend] lässt sich [sagen/feststellen/festhalten/zeigen]' AI hedge construction. Mining-derived (LLR 93.73 bigram + 33.00 four-gram). blader#102 Konjunktiv II Stacking — 3+ würde/wäre/hätte/könnte forms in close proximity for vague hedging. Per maintainer OQ2. blader#103 Anglizismen-Leakage — denglisch business buzzwords (insight, deliver, leveragen, Pain Points, ganzheitliche Customer Journey). Per maintainer OQ2. blader#104 Nominalstil-Inflation — noun-heavy bureaucratic verbing ('die Durchführung der Analyse' vs 'analysieren'). Per maintainer OQ2. DE PERSONALITY AND SOUL section mirrors EN with DE-appropriate register notes. Critical addition: domain note excludes DE career writing from soul-adding (DE Anschreiben register is formal-modest, opposite of US/UK puffery — adding soul makes them weaker). blader#7 DE AI Vocabulary trigger list: 33 phrases combining mined tokens (darüber hinaus, zusammenfassend, ganzheitlich, vorliegenden, umfassende, darstellt) with manually curated additions (vielfältig, facettenreich, nachhaltig, innovativ, zukunftsweisend, transformativ, ganzheitlich, intuitiv, nahtlos, robust, im Hinblick auf, vor diesem Hintergrund, es ist wichtig zu betonen, zentrale Rolle spielen, etc.) per OQ1. Excluded per OQ3: 6 Wikipedia-context-only DE-only entries flagged by DE Wiki AI-Cleanup project (productivity spikes, citation format, non-existent categories) — not applicable to general prose. Header documents the exclusion so future contributors don't re-add them. Tests: 207 → 211 passes (+4 DE pack tests: existence, expected pattern IDs, PERSONALITY section presence, no overlap with universal pack). Maintainer flagged for future review: blader#11 Elegant Variation — DE synonym system richer than EN, less sharp blader#34 Trailing Emphasis Fragments — less common in DE, signal stronger when present blader#36 Conditional Frame Stacking — overlaps with blader#102 Konjunktiv II; cross-referenced blader#8 Copula Avoidance — 'gilt als' legitimate legal term of art, apply lightly in legal domain blader#13 Passive Voice — DE academic uses passive more heavily than EN; SKIP in academic AND legal domains (will be enforced in Task 7 domains/de_overrides.md) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
duathron
added a commit
to duathron/humanizer-ext
that referenced
this pull request
May 28, 2026
…reer register (Phase 2 Task 7) 245-line DE override file mirroring domains/en_overrides.md schema + extending with 5 DE-only pattern rows (blader#100-blader#104) + DE career section (475 words) + DACH cultural-register inversion note. Override matrix (22 rows × 6 columns: Pattern + 5 non-casual domains): - All EN-PARALLEL pattern overrides translated to DE - 5 maintainer-flagged DE-specific adaptations applied: - blader#11 Elegant Variation: light across all domains (DE richer synonym system; sharper signal lost when applied strictly) - blader#13 Passive Voice: SKIP in academic AND legal (DE academic uses passive MORE than EN; was SKIP only in academic for EN) - blader#8 Copula Avoidance: light in legal ('gilt als' legitimate legal term of art) - blader#34 Trailing Fragments: kept strict where EN was strict (less common in DE, signal stronger when present) - blader#36 / blader#102 cross-reference (Konjunktiv overlaps in academic + legal) - 5 DE-only pattern rows: - blader#100 Akademische Rahmen-Floskel: strict everywhere (even academic) - blader#101 Impersonales Reflexiv: light in academic + legal, strict elsewhere - blader#102 Konjunktiv II: light in academic + legal, strict elsewhere - blader#103 Anglizismen-Leakage: light in technical + marketing, strict elsewhere - blader#104 Nominalstil-Inflation: SKIP in legal (DE Behördendeutsch), light in academic, strict elsewhere DE-specific domain guidance paragraphs: - academic: DE passive + Nominalstil heavier than EN; blader#101 + blader#104 softened - legal: Konjunktiv II for indirect speech is standard; blader#102 softened; 'gilt als'/'fungiert als' can be legal terms of art - technical: Anglizismen-Leakage softened (English tech terms unavoidable); flag denglisch verb constructions strictly - marketing: Denglisch in marketing is register marker (softened); DE buzzword-in-phrase rule + brand-tier audit step + 5-point preserve- everything checklist with DE examples - career: DACH formal-modest register (INVERSE of US/UK assertive self-promotion that EN career assumes). DE-specific AI tells: 'Mit großem Interesse', 'leidenschaftlich', 'ergebnisorientiert', 'ganzheitlich denkend', 'es würde mich außerordentlich freuen', etc. All 5 career preserve rules in DE (Metriken sind heilig, Eigennamen + Daten + Titel, Fachvokabular, Stellenausschreibungs-Schlüsselphrasen, konkrete Achievement-Aussagen). - casual: 'Ich' more weighty in DE; 'Man' constructions acceptable. Critical casual constraint (concept-noun preservation) translated. Tests: 211 -> 214 (+3 DE override tests: existence, table+guidance, pattern ID validity). Maintainer flags for review: - blader#11 'light' across ALL domains is broader than EN; relax to strict in career if FP eval over-softens - blader#15 included for EN symmetry, not strictly required by Task 7 spec - blader#36/blader#102 cross-reference is in a trailing blockquote (not inline); may want inline academic + legal mentions for visibility Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
Adds a minimal Streamlit UI at
integrations/streamlit/that wraps thehumanizerskill. Paste text → click Humanize → get the cleaned rewrite back with a native copy button, without the skill's default draft / audit / summary sections.This is the first non-skill code in the repo. Everything is scoped under
integrations/streamlit/so the skill itself is untouched. If you'd prefer to keep this repo pure-skill, I'm happy to move the wrapper out to a separate repo and link from the root README instead — just say the word.What the wrapper does
claudeCLI (claude -p --no-session-persistence …), so it reuses the user's existing Claude Code OAuth login — no API key required.ANTHROPIC_API_KEYis honored as a fallback.humanizerskill but adds strict output constraints so the returned text is just the rewritten prose — no "Draft rewrite" / "What makes this AI" / "Summary of changes" sections._PREAMBLE_RE+_TRAILING_RE) strips any leftover preamble or skill-trailer block if the model ever disobeys. The trailing regex is anchored to the skill's actual bolded headers (e.g.**Summary of changes:**,**Changes made:**) so legitimate prose that merely starts with "Notes" or "Summary" is preserved.st.code(wrap_lines=True)so there's a native copy-to-clipboard icon.Ways to run
cd integrations/streamlit && ./run.sh— creates a venv, installsstreamlit, openshttp://localhost:8501.cd integrations/streamlit && docker compose up --build. The compose file mounts~/.claude/into the container (RW, since macOS may needclaude /logininside the container), runs Streamlit as a non-root user (uid 1000), and binds port127.0.0.1:8501so the unauthenticated UI isn't exposed to the LAN by default.Files added
```
integrations/streamlit/
├── app.py # Streamlit UI + subprocess call to claude -p
├── run.sh # Local launcher (venv + streamlit)
├── Dockerfile # python + node + claude CLI + streamlit (non-root user)
├── docker-compose.yml # Mounts ~/.claude, loopback-bound :8501
├── .dockerignore
├── requirements.txt # streamlit>=1.56
└── README.md # Lifecycle / auth / stop / output / security docs
```
Notes for review
claude -p --no-session-persistencesubprocess — no state survives across clicks, nothing is written to the session store.docker compose down), anatexithook (registered exactly once viast.cache_resource, not per click) kills any in-flight subprocess.~/.claudetrust boundary, the non-root container user, the loopback port bind, and the single-user scope.Test plan
cd integrations/streamlit && ./run.sh, paste AI-sounding text, click Humanize, confirm cleaned output appears with a copy icon.Ctrl+Cin the terminal cleanly stops Streamlit and kills any in-flight claude subprocess.docker compose up --build, same flow. (not tested locally — no Linux host available; Dockerfile is identical to the macOS path so this is expected to work, but flagging for reviewer verification.)docker compose up -d --build, rundocker compose exec humanizer claude /loginonce, then humanize.ANTHROPIC_API_KEY=sk-ant-… ./run.sh, confirm no OAuth prompt. (not tested — no spare API key on hand; the code path is a singleos.environpass-through to theclaudesubprocess, which is the documented override.)🤖 Generated with Claude Code