Skip to content

About

Your Codex or Claude fixes the problem and writes the reply. 100% free, open source alternative to Zendesk, Intercom, Help Scout and Freshdesk.

Topics

Resources

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,414 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HappyToHelp: Customer Support, Solved. 100% free, open source alternative to Zendesk, Intercom, Help Scout and Freshdesk.

Part of Just Every · MIT licensed

HappyToHelp: the agent reviews Codex's suggested reply, presses Send, and the customer replies that it worked

Watch the full demo · 56 seconds

Three steps: the task sent to Theo's MacBook, Resolve completed with the fix, and the customer's widget showing the reply and her thanks

HappyToHelp inbox: Codex's internal note on the fix, the reply sent to Olivia Bennett, and her answer It worked! Thank you so much, with the local agent panel beside it
Your agent's fix, your reply and the customer's thanks, in one conversation.

HappyToHelp's Move in page: a Zendesk export uploaded and ready for review, with Approve and import
Move in from Zendesk: imports keep source details and never message your customers.

HappyToHelp

HappyToHelp is an open-source support workspace with a customer chat widget, shared inbox, AI-assisted replies, help centers, customer context and optional work delegated to your own Codex or Claude. It works with human replies without an AI provider. The editable React application runs on Cloudflare Workers with Hono, D1, R2, Queues and Durable Objects.

Release 0.4.28

Deploy version 0.4.28, tagged v0.4.28 once published. v0.4.26 is the upgrade baseline; the release upgrade checks cover v0.4.26, v0.4.25 and v0.4.24. The pinned installer is rer 0.2.117.

This release includes the content of the tagged but unreleased v0.4.27. Credential-shaped notification test fixtures blocked source scanning for that tag; they now use short example markers. The local size documentation also reflects the qualified rer 0.2.117 results. v0.4.26 remains the previous public release.

  • Reports: summary and team reports read indexed, message-bearing date cohorts, with separate timing distributions and SLA breakdowns. Workload reads the selected cohort and older active backlog while a maintained inventory preserves historical empty buckets. Overlapping handle sessions still include older tickets worked in the interval. Report evidence, labels and permissions remain live reads; these projections are not cached report totals.
  • Conversations and knowledge: transcript assembly reuses article references within a response and skips article-free source arrays. Socket replay reads bounded pages of raw message and ordered attachment projections, then renders current knowledge and rechecks authority before sending. Message corrections, attachment changes and erasure update the replay data while retaining event identities. An attachment index narrows message reads, and a solved-time index narrows the scheduler’s due cohort without changing rule eligibility or cursor order.
  • Backup and restore: derived report projections are excluded from portable archives and rebuilt after source rows and current write triggers are restored. Historical archive handling skips these derived backfills when the original inventory lacks their source subsystems. Keep normal backups and the installation’s existing custody and recovery requirements.
  • Installer and mail settings: the managed integration recipe now carries the complete native migration inventory and current binding declarations. Public mail validation covers native SendGrid and Mailgun as well as Resend, Cloudflare and the managed relay. Explicit off, none or disabled selections normalize to mail off and remove stale public provider settings from emitted plans; private bindings remain separately selected and checked. This does not activate mail or establish provider readiness.
  • Local size tooling: the pinned rer installer advances from 0.2.112 to 0.2.117. A seed-owned declaration exercises the built application with disposable synthetic local installations, exports SQL statement artifacts and supports a deliberate unbounded-read rejection exercise. Selected source and migration changes and daily scheduled verification use the shared build with queue consumers disabled for size measurement. This local tooling does not qualify live-provider limits or real-customer scale; synthetic text and attachment distributions and scheduled-consumer completion remain limitations.
  • Fresh hosted installs: after the full migration inventory and this Worker are installed, normal writes maintain the new report and replay projections and existing reads use the new indexes. On an empty database there is no historical cohort or replay data to backfill. Managed recovery still requires compatible platform custody and a verified assertion; SQL alone enables no recovery authority. Legacy import and adoption remain inert until a package is imported through the approved flow. Updating starts no import and activates no mail provider; live hosted delivery and provider qualification remain separate.
  • Migrations: four since v0.4.26, bringing the inventory from 196 to 200 files. 333_report_cohorts.sql is additive: it creates report tables, a view, indexes and maintenance triggers and immediately backfills derived membership, workload and bucket-presence rows without rewriting business rows. 334_media_message_reads.sql adds only the media-message read index. 335_socket_replay_projection.sql is additive to the outbox schema: it adds nullable raw-message and media columns, immediately fills existing outbox rows from retained native data, and installs synchronization triggers. It therefore writes derived data on upgrade. 336_solved_time_rule_reads.sql adds only the solved-time expression index. Apply missing migrations once in filename order before the new Worker serves HTTP or queue traffic. Migration 326 remains absent.

Update from v0.4.26 without resetting; v0.4.25 and v0.4.24 are also upgrade baselines. Back up D1, R2, Durable Object state, private settings and installation encryption custody, then stop the old Worker. Use Node 22.20.0, pnpm 10.12.4 and pinned rer 0.2.117. Retain native owners, permissions, support history, files, erasure fences and every applied migration identity. On v0.4.26 apply 333_report_cohorts.sql, 334_media_message_reads.sql, 335_socket_replay_projection.sql and 336_solved_time_rule_reads.sql once in that order. On v0.4.25 or v0.4.24 first apply the missing 330_identity_recovery.sql once even though 331 and 332 are already recorded, then apply 333 through 336 in filename order. Retain earlier published buyer steps, including 332’s conditional cleanup; older installations first apply every other missing published migration in filename order. Finish all missing migrations BEFORE the new Worker serves HTTP or queue traffic. Report and replay backfills run during migration; report projections are rebuilt after portable restore. There is no migration 326. Keep the durable recovery revocation watermark on rollback, and require fresh Managed custody binding after portable restore. Run rer deploy --dry-run against the retained installation before any separately authorized deployment. Legacy v1 remains cleanup-only and incomplete cleanup remains pending. No reset, mail activation, recovery adoption, production import, cutover or production deployment is authorized by this preparation.

See RELEASE.json, Updates and recovery and the changelog.

Version 0.4.0 adds Move in for reviewed support-history imports, resolution feedback with workspace-calendar Reports, Connections with scoped API tokens, signed webhook events and Slack delivery, and the rer local path. Native passwords, owners and data are kept. Before the updated Worker serves traffic, back up and apply the ten additive migrations 0110_move_in.sql to 119_local_portability.sql in order; an existing 0.3 installation follows Upgrading from 0.3.x. The changelog lists every change. Known limits:

  • Accessibility is on a confirmed owner HOLD; no WCAG conformance is claimed.
  • rer export archives cover D1, R2 and Durable Object storage (with a digest); full Base-data equivalence is not yet established.
  • Hosted operating costs are unmeasured; timed activation and paid-provider execution are not qualified.
  • Imports and connections are qualified with synthetic fixtures only, without real vendor exports or live Slack.
  • No hosted installation, compliance or FedRAMP qualification is claimed.
  • The hosted service at app.happytohelp.com is separate legacy production and is not part of this release.

Run it on your computer

The install and run guide covers installation, local sign-in and stopping the app, step by step. The Run HappyToHelp page has the quick-start command.

Start it with one line. You need Node.js 22 or later (with npm) and Git; check with node --version.

npx -y @runeditrun/rer dev just-every/run-happytohelp

That clones HappyToHelp into run-happytohelp, provisions the checkout's own pinned Node and pnpm, installs dependencies, sets up a local owner and starts the app. To set it up without starting it, use npx -y @runeditrun/rer setup just-every/run-happytohelp. Without Node, curl -fsSL https://runeditrun.com/install.sh | sh -s -- dev just-every/run-happytohelp brings its own. To start it again later, run cd run-happytohelp && rer dev.

The install also downloads Chromium (about 280 MB, into your user cache) the first time: rer verify and the browser checks run in it. Dev uses its local address for the chat widget and generates a private owner password. Wait for RER_READY, then open the RER_OPEN address to enter as the real local owner and reach Setup. No private answers, email service or AI account are needed. Use rer dev --stop from the checkout to stop the managed app.

Already running 0.3? Keep your checkout and data, and follow Upgrading from 0.3.x instead. See Install for private setup answers and Local command reference for ports, preview and idle shutdown.

To try the customer flow, install the widget on a local page, send a visitor message and reply from Inbox. Set that page's exact origin in Settings → Widget → Settings; the app's own origin remains allowed. A visitor's entered email can receive operator replies even when their identity is labelled Unverified. Local visitor and teammate mail is suppressed without storage or external sending. With a hosted sender, Email sent to provider · delivery not confirmed on a reply means acceptance, not confirmed inbox delivery.

Choose how to run it

Local dev is a loopback trial on your computer. An online installation in your own Cloudflare account lets the widget on your website reach the workspace. Both use the same rer commands. An independently managed project may select its own operating contract; this seed's CLI is not a platform admission requirement.

Deploy to your own Cloudflare account

For a new installation, acquire v0.4.28 once published, after installing rer as shown above:

git clone --branch v0.4.28 https://github.com/just-every/run-happytohelp
cd run-happytohelp

Start with a local build and validation:

rer deploy --dry-run

This needs no provider credentials, makes no Cloudflare requests, sends no mail and changes nothing remotely. It validates the deployment declaration and builds the application locally. The completion report lists any inputs needed for a real deploy; remote resources, credential validity, target secrets and remote readiness remain unchecked.

For a real deployment, read deployment prerequisites. When rer says See the deploy-kit owner-account instructions, it means What you need first: how to make the Cloudflare API token and find the account ID. Configure the real declaration and private account credentials, then:

rer deploy --environment production

The contract also requires a separately started read-only provider preflight with explicit owner consent and the owner's scoped Cloudflare token. For an existing Worker, that preflight permits only the account's Workers subdomain and the Worker's settings and secret names (three GETs), with no mail or mutations. That separate preflight is not yet implemented or live-qualified; the local dry run does not perform it or prove remote readiness.

For a new installation with outbound email, also supply real EMAIL_PROVIDER, EMAIL_FROM, EMAIL_API_KEY and OWNER_EMAIL inputs in an owned 0600 --env-file; the owner email must receive sign-in mail. Existing installations retain held secrets. The seven optional mailbox settings can stay unset. Remote provisioning remains separately unqualified.

rer deploy --environment production --env-file ~/happytohelp-production.env

Deployment provisions declared resources, applies migrations, publishes and checks health through Base deploy-kit. After a healthy deploy, rer deploy claims the owner named by OWNER_EMAIL (a real setup owner, or the value you supply privately) with a one-time token it then removes. Open your Worker's address and sign in by email as that owner to reach Setup. The owner's name is derived from their email. A Workers hostname does not name your business: a workers.dev website defaults to My workspace regardless of owner email. An explicitly chosen native workspace name takes precedence; you can change it in Project settings. Deploy refuses the local placeholder [email protected]: it has no mailbox. For a real deployment, supply OWNER_EMAIL privately in your environment or an owned 0600 --env-file. The local dry run can list missing production inputs without requiring them. rer signin --environment production directs you to this installation's /login page. HappyToHelp uses its native email/password sign-in; the command cannot mint an owner link. If mail fails, follow the working mail recovery in operations. rer deploy --environment NAME --remove --yes removes that environment's created Worker, D1, R2 and queues in one pass, including uploaded attachments in its R2 bucket, and reads back that each is gone. Export anything you need before removal. Hosted installation and real provider execution are not qualified by this release.

What you need and what it costs

HappyToHelp is MIT licensed with no seats or subscription fees. Your Cloudflare, email and optional AI providers bill your own accounts. Enable R2 and the account capabilities required by the declaration before deployment. An email sender must be verified. Local development needs no external mail or AI credential.

Configure optional model keys, the Apify crawler (for website sources larger than the built-in reader's 40 pages; see Website knowledge), Qdrant search, GitHub and email only when you need them. See Optional features and their settings and Measure local usage and costs. The optional local agent runs on the computer doing the support work and has its own runtime prerequisites.

After you install

Your workspace is already set up when you first sign in. It has a starter assistant for visitors, a reply-by-email mailbox when the installation holds an INBOUND_EMAIL_TOKEN, and mail that leaves from the installation's own sender until your sending domain is verified. The inbound token authenticates incoming mail; configure your email provider's domain routing and webhook before replies can arrive. Creating the workspace may send you one welcome email. Use Setup, the first entry in Settings (its row there counts what still needs you; an empty inbox links to it): Needs you lists what cannot be done for you (the widget on your website, an AI key and, with a hosted email provider, your sending domain's DNS records), and What we've set lists the rest. Anything under Needs you can be skipped for now and picked up later from Skipped. The system runs its own checks while Setup is open, and what it confirms is counted ("N of M confirmed", without what you skipped): mail to you, sender DNS, inbound mail, model access, spend ceilings, widget origin and an authenticated widget visit. Saved settings alone do not complete them. Add the widget through Settings → Widget, set its exact website origin, publish useful articles and invite teammates through Settings → Agents. By default the widget does not ask for an email. For visitors to receive replies by email, enable Settings → Widget → Settings → Required contact details → Require email. The visitor enters their address before sending a message; operator replies can then use it on a hosted installation with email sending configured.

Set up AI replies

Your starter assistant answers visitors by itself, from the help articles you publish and from what we read on your website, and within your daily limits, as soon as the installation has a key from an AI provider. Until then, new conversations stay with your team and the AI page and Setup say a key is missing.

  1. Get an API key from OpenAI, Anthropic, Google, DeepSeek, xAI or OpenRouter. The provider bills you for what you use.
  2. Add the key to your installation under the name for that provider: OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY (or GEMINI_API_KEY), DEEPSEEK_API_KEY, XAI_API_KEY or OPENROUTER_API_KEY. The setup answers can store one at install time (see Install).
    • On Cloudflare: in the Cloudflare dashboard, open your Worker, go to Settings → Variables and Secrets and add the key as a secret. You can also set it in your terminal before you run rer deploy --environment production (see Optional features and their settings).
    • On your own computer: add a line such as OPENAI_API_KEY=your-key to a file named .dev.vars in the run-happytohelp folder, then restart the app.
  3. Setup notices the key. While the starter assistant is untouched it uses a model of whichever provider's key is installed, and Setup confirms the key with the provider. To use a different assistant, open Settings → AI, add one (or choose Customize on an existing one), enter the Model it uses and keep it Enabled. Then, under Responder defaults, choose which assistant answers visitors, and with AI replies whether its replies are sent automatically, kept as drafts for your team to send, or turned off. In draft, a reply your local computer agent prepares waits in its report for you to use and send, and a visitor who writes while your team is away gets your away message, as if no assistant were assigned. Such a visitor's conversation also appears in Open and Unassigned.

Keep key values out of chat messages and the browser. To cap what visitors can spend, see Limits and AI ceilings.

Try a demo inbox

When your workspace has no conversations yet, the inbox greets you with one next action and a quiet Try a demo inbox link under it. The link creates a separate, clearly labelled workspace called Demo inbox · Northstar Outfitters, with:

  • fictional customer conversations
  • a drafting assistant you can edit
  • three published FAQ articles

Creating the demo makes no AI, email or other provider calls. To see AI drafting, open a demo conversation and press Generate. HappyToHelp then drafts suggested replies for you to review, using your AI provider. The demo's assistant uses OpenAI's gpt-5.6-luna model, so this needs OPENAI_API_KEY unless you change the assistant's model (see Set up AI replies). Generate never sends a reply to a customer.

When you are done, delete the demo workspace from its settings.

Support history, feedback, Reports and connections

Owner/admin Move in reviews five kinds: conversations, contacts, tags, saved replies and articles. Inspect per-kind plans, rejections, omissions, conflicts and publication changes; approve, resume a stopped batch, follow report links, repeat or undo through the same current role checks. Original source IDs, timestamps and private notes remain attributed; published articles stay published and drafts stay drafts. Apply and undo are inert: no mail, widget messages, model work, assignment or connection notifications. The moving-in guide explains formats, source custody and conflict-safe undo. Validation is documented-format, synthetic-only; realExport: not-supplied. The 9 October owner ruling requires exact business-state equality on repeat and undo. Platform counters/sequences, audit and import journals are excluded; business notes, source links, identities and native contact content remain checked.

A resolved widget conversation asks Did this answer your question? with thumbs up/down and an optional comment up to 1,000 characters. Only its owning visitor session can rate its current closed cycle; widget action limits apply and changes retain history. Native records store AI, assisted, human or unknown provenance. A visitor message reopens the conversation; another resolution gets its own record. Reports uses the workspace timezone and 7/30/90-day or custom calendar ranges for volume, median/p90 first response and resolution times, AI resolution and satisfaction counts/rates, daily series and latest comments with conversation links. Conversation and summary CSV exports guard formula-leading cells. Imports are excluded and Reports calls no model. The Reports guide and workspace workflows explain the denominators.

Settings offers seven explicit token scopes, optional expiry, one-time secret display, hashed storage, revoke, last use and audit. The API guide contains thirteen Bearer-only operations. Webhooks support four signed events, explicit test sends and safe attempt logs; public HTTPS destinations are checked against SSRF. Slack has incoming-webhook and bot-plus-channel modes. Both have recorded-response checks only; live Slack: not-supplied. Deliveries use ordinary platform HTTPS fetch with manual redirects. Every 3xx fails without following its Location. Requests are limited to 1 MiB, responses (including streams) to 64 KiB, and the entire request/response to 10 seconds. Public HTTPS destination syntax and literal IP validation remain enforced; this edition does not claim DNS pinning. Base HTTP 500 remains uncertain without automatic replay; 429 retains four bounded attempts with the same logical identity and exact body.

Installed owners land on the Setup page, where the system has already done what it can and lists only what needs them; new workspaces lead with the widget snippet, with secrets and verification controls under Advanced. Empty inboxes offer widget installation, a link to Setup and a demo. Workspace headers follow the selected workspace; visitors intentionally see the operator's display name. Local development suppresses email without storing messages.

Export conversations

In Reports, choose Export workspace conversations (JSON). The transcripts.json download includes every workspace conversation across all dates and imports, with its messages, private notes and attachment names and metadata. Attachment bytes remain in the workspace; use the portable backup for those. Exports ask for recent confirmation: accounts without a second factor can choose Email me a sign-in link, press Sign in from their mailbox in the same browser, then return and press Continue. This also works for older email-claimed owners whose generated password was never known. After mailbox confirmation, Profile → Security lets you set a new password without the old one. Enrolled second factors remain required. Reports and its analytics CSVs exclude empty widget conversations.

Contributor setup

For work on the source, select Node 22.20.0 and pnpm 10.12.4:

pnpm install --frozen-lockfile
pnpm exec rer describe --json
pnpm exec rer check --profile first-party

Verify

rer verify

The complete target checks the contract, real build, typecheck, native runtime, command journey, current workflows and selected Base copies. For a change, run its touched tests plus pnpm run typecheck; CI is the full wall. Browser suites and full verification run on the designated remote runner. Provider fixtures prove local protocol behavior; hosted acceptance and paid-provider execution require separate evidence. Preserve the current holds.

Local size check

After pnpm run build, run pnpm exec rer size --write-statements .local-evidence/size/statements. The seed-owned declaration uses disposable local D1 installs of the built application, native owner and widget sessions, and the declared minute schedule. It checks inbox/list/search, conversation and transcript reads, message admission, sockets, reports, knowledge, outbound tickets and the AI draft route. pnpm exec rer check --profile first-party validates the declaration.

The large fixture carries 162,000 contacts, 161,893 conversations, 27,000 messages and outbox rows, 2,835 media rows and 3,034 pending workflow events. The small fixture carries roughly one hundredth; both retain 644 published documents and 373 reply blocks with the historical source-occurrence skew. These are synthetic counts from the 11 November K24/K26/M2 observations, refreshed against migrations through 332. Document text lengths and attachment byte-size distributions remain missing; generated text and 2,048-byte media metadata are placeholders. The fixture moves the bootstrapped owner's native session to its synthetic workspace.

The default 90 FROM-item/expression-depth margin and 10% + 200 rows growth check remain. Reports have initial engineering ceilings of 1M/1.5M rows and explicitly allow cohort growth because they aggregate a selected 90-day window. Those are budgets, not measured provider limits. Existing flows retain the historical working ceilings; added routes have initial engineering budgets. No credentials or real conversations are used. The published 0.2.112 command let consumer work enter the meter, and report statements exceeded the 90-item margin. With the pinned, qualified rer 0.2.117, all 17 unchanged control flows pass (inbox reads 2,359 to 2,403 rows); the copied-build full-table-query fault is refused solely for ceiling and growth. Queues are held. Scheduled knowledge refresh and legacy importer fixtures target admission/wakes; consumer completion is not qualified. The two legacy run rows are discovery fixtures without R2 package custody. The no-key draft flow expects 409 and does not qualify generation.

Verify runs size once nightly and on query/migration changes, using its shared build. External statement-only handoff: download size-statements-<full-commit>-rer-<installed-version>-<run-id>-<attempt>; identity.txt identifies the exact checkout and package, and statements/{small,large}.json are the stable inputs for separately credentialed real-D1 statement checks. Do not transfer application data.

To prove rejection, run node tests/size-check/proof.mjs after building. It requires all original flows to pass, then adds an unbounded conversation read only to a disposable built Worker copy and requires the same public rer size command to fail the inbox growth and ceiling checks. Application source stays clean.

Where to go next

Development lives in just-every/run-happytohelp; the private repository is retained for research and evidence only.

License

MIT. Third-party asset notices remain under docs/licenses.

About

Your Codex or Claude fixes the problem and writes the reply. 100% free, open source alternative to Zendesk, Intercom, Help Scout and Freshdesk.

Topics

Resources

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages