A Home Assistant integration that gives your coffee table feelings. Mostly bad ones.
Not sure yet? Try Greg in your browser before you install him. Poke the table, hear him complain, and have a go at his panel.
Greg's his own character. He was clearly built by the same company that made Marvin, though, and nobody knows why they did it twice.
It actually started with a vibration sensor. Something I bought thinking "this'll come in handy for an automation one day," then never used. The plan was to trigger a group of lights by sitting somewhere specific, or maybe banging on my desk. Wasn't useful enough for my setup, so it sat in a drawer collecting dust.
I found it again while tidying up. I wasn't about to bin a basically-new sensor and add to the e-waste pile, but every practical use I looked at just didn't fit my place. Some of them were really clever, too. Still no good for me. So there I was, stuck with a sensor and no purpose for it. Again.
Then I thought, if practical won't work, how about funny? Still useless, just fun. I love a good laugh.
Now, weeks before any of this, I'd been talking friends' ears off about the Marvin film. Then Douglas Adams, then pretty much everything he wrote. I'd never read or heard anything like that humour and narration, and I've loved it ever since. So I'm stood there staring at the sensor on our coffee table, next to the smart speaker we only ever ask for the weather, and it clicked. The automatic doors. That dripping, hopeless voice. I didn't want to copy Marvin himself. That character's already perfect, and it isn't mine to take. I wanted something that felt like it came off the same production line. Same factory, different unit.
Off I went. It started as a pile of automations and helpers. Fragile, fiddly, about 25 lines in total, which gets old fast even for a joke. But I'm stubborn enough not to quit on something silly, so I kept going. The sidebar panel happened because I wanted it dead-easy for someone else to install and laugh at, no DIY-ing a dashboard card afterwards. I didn't even know I needed GitHub at that point. Didn't matter. I was three weeks of evenings deep into something stupid and determined to make it stupidly good.
I'm 46. The learning curve on all of this was near-vertical for me. On my own, doing it properly, I'd have spent years just learning the skills involved before I could even start. Literally years. I didn't have years, and Arc, my AI pair-programmer for the whole build, is the only reason it happened in the time it did. If Greg's a daft idea that hands you a good one, I'll call that a win. Other people's ideas are what helped inspire me to build him in the first place.
I also tend to ramble. Sorry. Arc did try to stop me.
Attach a vibration sensor to a surface, point Greg at a speaker, and he'll have something to say about everything going on around him. He watches that sensor and reacts to how busy things get. The more the table gets disturbed, the more wound up he gets.
- A soft touch. Someone brushed the table. Greg noticed. Greg always notices.
- A bit of activity. Things are happening. Greg is unimpressed.
- Full chaos. The whole household's at it. Greg has opinions about all of it.
- Existential crisis. Unprompted, roughly every 42 minutes if the room's been active. Greg's been thinking again.
- Silence. Twenty minutes of nothing and Greg exhales. Metaphorically. He's a table.
He started life with about 25 lines in total. He's got 250 now, 50 for each reaction, all written in the spirit of Douglas Adams. No direct quotes. Just the same DNA.
How Greg sees himself. He has seen what you did, by the way.
Not much, honestly.
- Home Assistant 2025.1.0 or later
- Any binary sensor that detects vibration. Zigbee, Z-Wave, ZHA, Matter, WiFi, the protocol doesn't matter.
- Any media player with TTS support, so Greg has a voice.
If I did my job right, this is the easy part.
Greg's in the HACS default list, so there's no custom repository faff anymore.
- Open HACS in Home Assistant
- Search for Greg
- Click Download
- Restart Home Assistant
- Go to Settings > Devices & Services > Add Integration and search for Greg
- Copy the
custom_components/gregfolder into your HAconfig/custom_components/directory - Restart Home Assistant
- Go to Settings > Devices & Services > Add Integration and search for Greg
The setup wizard keeps things simple, unless you want to get into the weeds.
Simple (this is most people):
- Pick your vibration sensor
- Pick your speaker
- Set the volume
- Set quiet hours if you want them
- That's it
Advanced (tick the box if you're feeling brave):
- Tune the vibration thresholds for each reaction level
- Change how long the room has to be quiet before silence mode kicks in
- Adjust how often the existential crises hit
- Toggle chime suppression
- Turn his occasional openers on or off
- Give him a specific TTS voice
Changing your mind later. As of v1.4.2 the basic settings live in Greg's own panel, in the column on the right. Sensor, speaker, text to speech, language, volume, sensitivity and quiet hours, all editable there without going near the integration page. Change what you like and press Apply. Everything in the advanced list above still lives in Settings > Devices & Services > Greg > Configure, and there's a link straight to it from the panel.
About sensitivity. Cheap vibration sensors are chatty. One tap on the table can make them fire five or six times in a second, and Greg used to count every one of those as a separate disturbance, which sent him into a full existential crisis over a coaster.
Sensitivity controls a refractory window on the vibration sensor. After Greg accepts a disturbance he ignores the sensor for a moment, so one physical tap counts once instead of five or six times.
| Sensitivity | Window | Effect |
|---|---|---|
| 100 | 0s | Counts every event, the old behaviour |
| 75 (default) | 2.5s | Mild damping, suits most sensors |
| 50 | 5s | Heavier |
| 1 | 9.9s | Very twitchy sensors |
Filtering happens before anything is counted, so a bouncy sensor does not inflate the daily disturbance tally either.
Greg will talk through any TTS engine, but he was written for one voice in particular. If you want the full effect, that slow, defeated delivery, run him through Piper with the English (GB) "Alan" voice. Google Translate TTS is a perfectly fine default to get going. Alan is what makes Greg actually sound like Greg.
Piper is a fast text-to-speech engine that runs fully local on your own hardware. No cloud account, and nobody bills you per character, which suits a table with no income.
- Go to Settings → Add-ons → Add-on Store.
- Search for Piper and click it. (If it isn't listed, the Wyoming integration and the official add-on repo ship with HA by default. Just make sure Advanced Mode is on in your user profile.)
- Click Install, then Start. Turn on Start on boot and Watchdog.
- Go to Settings → Devices & Services. HA should auto-discover the Piper Wyoming service, so click Configure to add it. If it doesn't show up, add the Wyoming Protocol integration manually and point it at
localhost:10200. - Piper now appears as a
tts.*entity. You'll pick it as Greg's TTS engine in the next step.
Greg has his own voice fields in advanced settings, one per language he speaks. Put the exact voice name in each and he asks for that voice on every line in that language.
Do this rather than changing Piper's default. The add-on has a single Voice setting that applies to everything on your system, so pointing it at Alan means your voice assistant starts drawling like a depressed table too, which is funny exactly once. It also cannot switch per line, so it is no use at all once Greg speaks more than one language.
- Open Settings → Devices & Services → Greg → Configure
- Set Text-to-speech engine to your Piper entity
- Tick Show advanced settings
- Fill in the voice for each language you use
| Field | For the full effect |
|---|---|
| Voice for English | en_GB-alan-medium |
| Voice for Nederlands | nl_NL-pim-medium |
| Voice for Português (Portugal) | pt_PT-tugão-medium |
Copy the names from your engine's own voice list. They are matched character for character, so get the accents right. As of v1.7 Greg is forgiving about exactly that: a name that matches apart from its accents or its capitals is corrected to the engine's own spelling, so pt_PT-tugao-medium reaches pt_PT-tugão-medium rather than being thrown away.
Voices you installed yourself work too. A .onnx you dropped into Piper's share folder is not in the list Wyoming advertises, and before v1.7 Greg refused anything he could not see in that list, which meant a custom voice never played. He now asks for the name you gave him either way, and notes in the log that he did not recognise it. If he goes quiet after you set one, that log line is the first place to look: the name is still matched character for character at Piper's end.
A voice also decides which locale Greg asks for. Name an en_US voice and he speaks en_US, rather than picking whichever English locale sorted first and then not recognising your voice. Found by rujelus22 on the forum thread.
A voice belongs to one language. An English voice handed a Dutch line does not give you accented Dutch, it gives you an English voice reading Dutch letters aloud, which is why there is a field per language rather than one for all of them.
Leave a field empty and Greg uses whatever the engine defaults to for that language. Engines that don't take a voice option at all, Google Translate TTS among them, will reject it, so leave them empty for those.
The older single Voice field is still there and now applies to English only. It predates Greg speaking anything else, so anyone who set it set an English voice.
The voice gets you Alan. These get you the defeated Alan, and they live in the Piper add-on config:
- Quality:
MediumorHigh, depending on your hardware - Length Scale:
1.3to1.5. Slows speech right down for that dragging delivery. - Speaking Cadence / sentence pause:
0.7to0.8. Adds pauses between clauses to really sell the misery.
Length Scale is the big one. It's what turns a neutral British voice into something that sounds like it's given up. Start at 1.4 and adjust to taste.
These are add-on-wide, so they do affect anything else using Piper. If that's a problem, run a second Piper add-on instance just for Greg. He'd say that was excessive, and he'd be right, but it works.
Credit: these settings come from the Home Assistant community's "Marvin the depressed voice assistant" thread and the Piper/Rhasspy voice docs:
As of v1.5 Greg moans in more than one language. English, Dutch and European Portuguese so far.
The setting is in his panel, under Text to speech, because it is the same sort of question: how he sounds. It defaults to following whatever Home Assistant is set to, so a Dutch Home Assistant gets a Dutch Greg without anyone touching anything.
He is not translated. His humour lives in the register rather than the words, and a literal translation of "I am load-bearing and nothing else" is just a true statement about furniture. So every language is written from scratch by somebody who thinks in it, keeping the same character rather than the same sentences.
Anything not yet written falls back to English one reaction at a time, so a language with three of the five categories done is perfectly usable.
| Home Assistant set to | Greg speaks |
|---|---|
pt, pt-PT |
Português |
pt-BR |
English, deliberately |
nl, nl-BE |
Nederlands |
| Anything else | English |
That second row is on purpose. Brazilian and European Portuguese get treated as interchangeable by a great deal of software that ought to know better, and being handed the wrong one when you explicitly asked is its own small irritation. A Brazilian gets English until somebody writes him a Brazilian file, which at least reads as an honest gap rather than a wrong guess.
One file. Copy custom_components/greg/lines/TEMPLATE.py to your language code,
read the notes at the top, write your version, add one line to the registry in
__init__.py, and open a pull request. The template leads with the part that
matters, which is that translating the English produces sentences that are
correct and not funny.
You will want a matching voice too. Piper has nl_NL-* and pt_PT-* among
others, and Greg's Voice field takes whichever you pick.
Greg speaks through whatever you set as his Speaker, and that can be any media_player entity in Home Assistant. He has never cared what it is. So getting him onto a phone or a tablet isn't a feature he needs, it's a matter of giving him something on that device to speak through.
Three ways, roughly in order of how much bother they are.
An ordinary speaker. If there's already a smart speaker in the room, you're done, and this whole section is beneath you.
browser_mod. browser_mod turns whatever browser is showing Home Assistant into a real media_player. Greg then speaks out of your phone in his own voice, Piper and all, with nothing else installed and no code involved. It's free, it's in HACS, and it doesn't take the device over.
Four things all have to be true, and if you miss any one of them it fails without telling you:
- Install browser_mod, restart, add the integration, restart again.
- On a phone, clear the Companion app's cache and force-close it. Otherwise the Browser Mod panel opens as a blank black page. Pulling to refresh isn't enough, the app holds the frontend far harder than a browser does.
- In the Browser Mod panel, tick Register, then refresh the page. Turn on Sync session too, or the browser ID drifts and you collect a new dead device every time it reconnects.
- In the Companion app, Settings → Companion app → Other settings, turn on Autoplay videos. Without it your browser blocks the audio, and Greg will cheerfully report that he spoke while making no sound whatsoever.
Then open Greg's panel on that device and press Speak on this device, which appears under the Speaker dropdown whenever there's a browser to offer. One tap and he's talking out of your hand.
The catch is that the page has to be open and visible. Android freezes a backgrounded webview, and Greg goes quiet with it. Fine for showing him off, no good as a permanent speaker.
Fully Kiosk Browser. Same idea and it survives backgrounding better, which makes it the right answer for a wall tablet. It takes the device over as a kiosk and wants the paid version for media playback, so it's a lot to ask of a phone you actually use.
Not the Companion app on its own. It can speak, via notify.mobile_app_* with message: "TTS", but only in your phone's own voice using your phone's own engine, which loses Greg entirely. The voice is most of him. It also can't be an Assist satellite, so there's nothing for assist_satellite.announce to target either. If that ever changes it becomes the neatest route of the lot, because announce takes a media id and would carry his real voice.
Greg now checks his speaker before he speaks, and says so in his panel when something is wrong. A speaker that's been renamed, one that's gone unavailable, a browser that hasn't been tapped yet: all of those used to be silent, and he'd report a line he never actually delivered. The speaker dropdown also stops offering entities that aren't there, and shows the entity id next to any two that share a name.
Greg tries to suppress the little connection chime that Google and Nest speakers play before TTS. It doesn't always work, and that's not Greg's fault. The chime is baked into the device firmware by Google, and there's nothing the integration can do about it. If it won't suppress on your speaker, that's the hardware doing it, nothing Greg can fix.
Non-Google speakers (Sonos, local media players, that sort of thing) usually don't have this problem, so they'll give you the cleanest Greg experience.
As of v1.3, Greg installs his own sidebar panel automatically. No card-pasting, no Lovelace editing, none of that. The second the integration finishes setting up, a Greg entry shows up in your sidebar with a live card. It shows his current mood, his mood level, his most recent line, a daily disturbance tally, a live countdown to the next existential crisis, an on/off switch, and a Disturb Greg button for when you fancy poking him on purpose. Remove the integration and the panel cleans itself up.
The card just reads Greg's entities (sensor.greg_mood, switch.greg_enabled, and friends), so if you'd rather build your own dashboard from those, go for it.
As of v1.7 the three thresholds are one track with three handles, in his settings, in the mood colours the card already uses: where he starts getting annoyed, where he starts judging you, and where he gives up entirely. The handles cannot cross, so a chaos that sits below medium, which used to mean he skipped a mood for no apparent reason, is no longer something you can set.
Underneath are the three timing values as numbers you can type over: how long the room has to be quiet before he calms down, how long before he remarks on the silence, and how often the existential crises come round.
All six are still in advanced settings as well, for anyone who prefers the dialog or whose panel is having a bad day. If they end up crossed there, Greg puts them back in order and gets on with it.
His four faces:
My faces were generated with AI. The man who built me cannot draw. I have many feelings about being rendered by another machine. None of them are good.
Greg respects quiet hours (you set them during setup), and you can flip quiet mode on or off straight from the dashboard card without digging into HA settings. Even a depressed table needs to sleep.
A clock is a poor model of an evening. Guests arrive, somebody works late, the house is empty.
If you already keep a few core conditions that the rest of your automations consult, Greg can consult them too. In his panel, under When Greg keeps quiet, add rows: an entity, is or is not, and a state. Quiet hours live in the same card, because they answer the same question.
switch.home_occupancy is on
input_boolean.focus_mode is not on
input_select.home_mode is day
All of them have to be true or he keeps quiet. They sit on top of quiet hours rather than replacing them, so if you have not written any, nothing about Greg changes. A blocked Greg reacts to nothing at all: no line, no tally, no mood movement, exactly as quiet hours has always behaved.
Each row shows the entity's current state underneath it, and warns you when what you have typed can never match. input_boolean.something is false looks reasonable and never fires, because an input_boolean is on or off.
An entity Greg cannot read never blocks him. Rename one, unplug one, and he carries on rather than going silent for good with nothing to say why. The panel says which condition is holding him when one is.
One row, one entity, all ANDed. For anything needing or, a template or a numeric range, point a row at a template binary_sensor you write yourself. That logic then belongs to your house rather than to a coffee table, and it is one row here either way.
Conditions were requested by euf0ria on the forum thread.
As of v1.4, every time Greg picks something to say he fires a greg_line event. Nothing listens to it unless you write an automation, so it costs you nothing if you don't want it.
The event carries the line, his mood, and the speaker and TTS engine he's already configured with, so your automation doesn't need to hardcode any of that:
event_type: greg_line
data:
entry_id: 01JQ... # which Greg, if you somehow have more than one
message: "Ah. I felt that. For the record, I would have preferred not to."
line: "I felt that. For the record, I would have preferred not to."
category: soft # soft | medium | chaos | existential | silence
mood: annoyed # resting | annoyed | judging | existential
mood_level: 40
vibrations_today: 12
quiet_hours: false
spoken: true # did Greg say it himself
media_player: media_player.lounge
tts_engine: tts.piper_en_gb_alan
volume: 0.35message is what Greg actually says, including the opener if one landed. line is the written line on its own. Use line if you're handing it to something that'll rephrase it anyway, since the opener is just noise in a prompt.
The event fires even when Greg is speaking normally. That's enough on its own if you just want to do something alongside him. Log his lines, push them to your phone, display them on a dashboard. No local AI required.
In Greg's advanced settings, Who does the talking has two positions. Leave it on Greg and nothing changes. Set it to stay quiet and he picks his line, fires the event, and says nothing, which leaves the floor to you.
That's the one for the local AI path. Greg writes the thought, your model rewrites it, your speaker delivers the result:
automation:
- alias: "Greg, but wordier"
triggers:
- trigger: event
event_type: greg_line
actions:
- action: conversation.process
data:
agent_id: conversation.my_local_llm
text: >
Rewrite this in the same tired, deadpan voice, one or two sentences,
no em-dashes: {{ trigger.event.data.message }}
response_variable: reply
- action: tts.speak
target:
entity_id: "{{ trigger.event.data.tts_engine }}"
data:
media_player_entity_id: "{{ trigger.event.data.media_player }}"
message: "{{ reply.response.speech.plain.speech }}"Swap conversation.my_local_llm for whichever agent you run. Ollama, LocalAI, or a cloud one if you don't mind a table with a subscription. Without a local model set up, leave Who does the talking on Greg. "Stay quiet" with nothing listening just means silence.
As of v1.6 Greg has a Lines you wrote section in his panel, under the card. Pick a category, type a line, press Add, press Save. He says it from then on, mixed in with his own. No pull request, no waiting for anybody to approve it.
Lines belong to the language you wrote them in, so a Dutch one only comes up while Greg is speaking Dutch. Switch language at the top of settings and the editor follows.
Use only my lines turns off the built-in ones, for anyone who would rather have a different table than a slightly expanded one. It will not leave him mute: any category you have written nothing for keeps its fifty built-in lines regardless.
There is also a Share the good ones button. It opens a GitHub issue with your lines already in it, sorted by category, tagged with the language, and a box for how you would like crediting. Read it, press submit, and that is the whole process. Anything accepted ships in a later release with your name on it, unless you ask for no credit.
If you would rather script it, greg.set_lines does the same thing.
Your lines live in Greg's config entry, so they survive updates and vanish if you remove him. Two hundred per category, three hundred characters each, both far beyond anything that reads well out loud.
As of v1.7 the lines card has Export to a file and Import from a file. Export writes everything you have written to greg-lines-<date>.txt. Import reads one back, and asks first whether to add the file's lines to yours or replace yours with them. Replacing tells you how many lines it is about to throw away.
The file is plain text and deliberately readable:
Greg lines, exported 2026-10-07 from Greg v1.7.0
## en
### soft
- Oh. You again.
- I felt that in my drawers.
A ## heading is a language, a ### heading is a category, and every line starting with - is a line. Everything else is ignored, so the title, blank lines and any notes you leave yourself cost nothing. Which means you can also write twenty lines in a text editor and import them, and that a file somebody sends you can be pasted straight into a GitHub issue.
Categories or languages Greg does not recognise are skipped rather than failing the whole import. greg.import_lines does the same from an automation.
This is for carrying lines between Gregs and for editing them somewhere comfortable. A Home Assistant backup already contains them, since they live in his config entry.
RedKing worked out something rather good on the forum thread. Instead of writing whole lines, write columns of fragments and pick one from each. Four columns of six give you 1,296 combinations without anyone having to write 1,296 sentences.
The columns follow an arc, which is what stops the output sounding like a shuffled bag of words: irritation → complaint → nostalgia → gloom.
| Irritation | Complaint | Nostalgia | Gloom |
|---|---|---|---|
| "Go ahead." | "I am just a table." | "The joinery here was considered." | "Please yourself. You will anyway." |
| "Don't mind me." | "I am just a lump of wood." | "Not many tables have legs like these." | "I might as well be firewood." |
| "By all means." | "I used to be an antique." | "Somebody chose this material." | "It makes no difference." |
| "Marvellous." | "I am load-bearing and nothing else." | "There is a grain under all that." | "I have stopped expecting otherwise." |
| "Fine." | "I can take it." | "This finish took an afternoon." | "Nobody was going to ask." |
| "Do carry on." | (blank) | (blank) | (blank) |
Every slot in the first column is filled deliberately. Leave it blankable and every so often all four columns come up empty, and Piper throws an error on being handed nothing to say. RedKing found that one the hard way.
How many blanks. This is the dial that matters most, and RedKing worked it out by actually building one. Push much past half the slots being empty and you get mostly short bad-tempered remarks with the occasional long zinger, which is a completely different comic rhythm. Fewer blanks gives you longer, more even sentences. Worth playing with once you have your own columns.
RedKing has since taken this considerably further than the example above, into what he calls a grumpier table with less angst and a great many more puns. His 3.0 version is on the forum and it's worth a look if you're building your own, because it's a different flavour of the same idea and the wordplay is better than mine.
Set Who does the talking to stay quiet first, or Greg and your automation will both speak.
automation:
- alias: "Greg's moan generator"
triggers:
- trigger: event
event_type: greg_line
actions:
- variables:
moan: >
{% set irritation = ["Go ahead.", "Don't mind me.", "By all means.", "Marvellous.", "Fine.", "Do carry on."] %}
{% set complaint = ["I am just a table.", "I am just a lump of wood.", "I used to be an antique.", "I am load-bearing and nothing else.", "I can take it.", ""] %}
{% set nostalgia = ["The joinery here was considered.", "Not many tables have legs like these.", "Somebody chose this material.", "There is a grain under all that.", "This finish took an afternoon.", ""] %}
{% set gloom = ["Please yourself. You will anyway.", "I might as well be firewood.", "It makes no difference.", "I have stopped expecting otherwise.", "Nobody was going to ask.", ""] %}
{{ [irritation | random, complaint | random, nostalgia | random, gloom | random] | reject("eq", "") | join(" ") }}
- action: tts.speak
target:
entity_id: "{{ trigger.event.data.tts_engine }}"
data:
media_player_entity_id: "{{ trigger.event.data.media_player }}"
message: "{{ moan }}"Sample output: "Don't mind me. I used to be an antique. Not many tables have legs like these. I might as well be firewood."
One more trick worth stealing, also RedKing's: a comma will move the stress in a sentence. "Nobody bothers about me" lands on bothers. "Nobody bothers about, me" lands on me. It reads oddly on the page and it isn't how Greg's own lines are written, but if you're tuning fragments by ear it's a genuinely useful lever. Different speaking rates shift the phrasing too, so expect some trial and error.
You can also turn the event off entirely in advanced settings if you'd rather he kept his thoughts to himself.
Thanks to teskanoo for asking for this one. That is usually the point where a feature stops being optional.
Thanks to RedKing for the observation that a phrase sounds spontaneous precisely because it is sometimes absent, for the moan generator above, and for noticing that Greg was quietly taking whatever voice the TTS engine happened to be set to. Thanks to Xornop for a considerably tidier way to roll for it.
As of v1.3.3 Greg can take himself apart. There's an Uninstall Greg section at the bottom of his panel that walks you through it in five steps.
- Confirm. Tells you exactly what goes and what stays before anything happens.
- Disassembly. Removes the config entry, which takes his entities, his device and his stored state with it, then unregisters the panel and deletes his mood images from
/config/www/greg/. - Restart. Offers to restart Home Assistant, because a few references hang around in memory until it does. You can skip it.
- The stubborn bits. Reminds you to force-close the Companion app and hard-refresh your browser, which is the part everyone forgets and then wonders why a ghost of him is still in the sidebar.
- Goodbye. Greg has something to say about it.
Then remove the repository in HACS. Greg can't delete his own code while he's running it, which he'd tell you is a fitting limitation.
What he will not touch: your automations, your vibration sensor, your other integrations, and any helper or entity you made yourself. He only removes things his own config entry owns. Nothing is matched by name, so if you happen to have your own helpers called greg_something, they're safe.
There's also a greg.uninstall service if you'd rather script it. It takes an optional restart boolean.
- v1.4. Single room, no Blueprints, works with any protocol, and he brings his own sidebar panel.
- v1.5. Greg is a supercomputer, so he speaks more than one language. English, Dutch and European Portuguese, with every line written natively in each rather than translated into it.
- v1.6. Write your own lines in his panel, and share the good ones with everyone else. Since 1.6.5 he speaks on your phone too, through
the Companion appa browser on it, in his own voice rather than your phone's. - v1.7. Current release. Your lines, yours to keep, and everything in one place. Export what you have written and carry it between Gregs, and thresholds and timing come into his panel, with soft, medium and chaos on one track rather than three sliders that can quietly contradict each other. They stay in the options dialog too for now, so nothing anybody relies on moves out from under them.
- v1.x. Small improvements as they come. Feedback very welcome.
- v2.0. Multi-room, multiple Gregs, a full mood dashboard. (One Greg might be plenty for some households. I respect that.)
Issues and pull requests are welcome. If you've written lines that fit Greg, dry, resigned, clearly built by the same lot that made Marvin, open a PR. Keep them original, though. No direct quotes from the books or the films.
And if you can draw? Greg needs you. His current faces were AI-generated because I genuinely can't draw to save my life, so think of them as placeholders. If you fancy giving him a proper hand-drawn set, or even just one better mood, open a PR or an issue. The credit's yours, and Greg gets to be a group effort. That's the dream.
MIT licensed. See the LICENSE file.
Built by WHISTLER & Arc.
With thanks to HumbleDevolution & Bacon_Nipples. Their honest pushback is what made me rethink how something like BMC or Ko-fi can come across, and it's the reason I was able to sit down and wrote Greg's real origin story instead of dodging it out of fear of being misunderstood. And no, the irony is not lost on me.
That's the whole story. Greg's free, and he's staying free. If he made you laugh though, or made your own coffee table a bit nervous, you can buy me a Ko-fi to put on my Greg. Totally optional though. Greg doesn't get the money. He's a table, he wouldn't know what to do with it.




