The Jarvis character, waving

Meet Jarvis

The assistant that rewrites itself.

Jarvis is a self-hosted web chat backed by the Claude Code CLI — with full read/write access to its own source. Ask for a feature, it edits the code. You diff, commit, or throw it away.

git clone https://github.com/julienR2/jarvis && cd jarvis && docker compose up -d

MIT · Docker Compose · needs a Claude subscription (or any OpenRouter key)

A tour of Jarvis: home, chat, generated apps, the git diff view, connectors and crons

It edits itself

Not a plugin API, not a config file. The agent opens your actual source, changes it, and the container rebuilds. Git is the safety net.

It runs without you

Crons and webhooks fire the agent on a schedule or an HTTP call, with the full conversation context. It keeps working while you sleep.

It reaches your things

Connectors hand real credentials — Gmail, GitHub, Slack, Linear, anything you add — to the agent at runtime. No code, no restart.

What's in the box

Everything below ships on first boot. Nothing to wire up.

Self-coding

Claude edits the frontend and backend through chat. Every change is diffable, committable, revertable.

Apps

Interactive HTML/CSS/JS rendered in a split pane beside the chat — dashboards, tools, little games.

Connectors

Gmail, GitHub, Slack, Linear and more from the UI — or a custom one with just a name and env fields.

Cron jobs

Scheduled prompts with full context. “Summarize my inbox at 7am” — the agent writes the cron itself.

Webhooks

HTTP endpoints that trigger the agent with any payload. Pairs with n8n, Home Assistant, iOS Shortcuts.

Skills

Markdown instruction sets that auto-activate on context. The agent can write new ones for itself.

Plugins

Claude Code plugin marketplaces from Settings. Enabled ones load in every conversation, cron and webhook.

Browser

A real Chromium the agent drives through Playwright, for sites that need clicking rather than fetching.

Voice input

Audio transcribed by a bundled Whisper and dropped straight into the conversation.

Sharing

Send a link to a conversation, read-only or with replies. No account needed on the other side.

Any model

Claude by default, or any OpenRouter model that can run the agent. Both providers live at once.

Mobile PWA

Installable and responsive, with push notifications and share-target support.

Three ways it gets going

Same agent, same conversation memory. Only the trigger changes.

  1. “Add a dark toggle”you, in the chat
  2. Claude edits the sourcefrontend/src/…
  3. Container rebuildsbanner: new build ready
  4. You diff itcommit · discard · revert

and round again — the app you're using is the app being changed

A closer look

Split view: the chat on the left, a generated app on the right
Apps. Ask for a tool, a chart or a game — it renders next to the chat.
Changed files view with a diff
Git. Every edit the agent makes is a diff you approve or throw away.
Connectors settings page
Connectors. Credentials live in the database, injected at runtime.
Cron jobs page
Crons. Schedules the agent can read, write, and edit for itself.

Up in three commands

Docker and Docker Compose v2.24+. No .env to write — secrets generate themselves on first boot.

  1. Clone and start

    git clone https://github.com/julienR2/jarvis
    cd jarvis
    docker compose up -d
  2. Grab the setup code

    docker compose logs backend | grep setup

    It stops a fresh instance from being claimed by whoever finds it first.

  3. Open localhost:5173

    The wizard creates your account and takes a Claude OAuth token (claude setup-token). Prefer a gateway? Point it at OpenRouter instead — both can live side by side.

Yes, this sounds reckless

It's an agent with a shell, write access to its own source, and your credentials. Here's what makes it workable.

  • Git is the undo button. Discard uncommitted changes, or revert the last commit — from the UI, or with one command on the host if the UI won't load.
  • It can't reach your login. The Claude subprocess runs with the JWT signing key and admin credentials stripped from its environment.
  • Secrets stay out of the code. Connector credentials live in the database and are read at runtime, so nothing committed can leak them into git history.
  • Nothing is exposed by accident. Published ports bind to localhost. What reaches the internet is whatever you deliberately put a proxy in front of.
  • Single-user by design. Every account is a full admin — there's no permission model. Don't hand out accounts; hand out share links.

Deploy it, then shape it.

You start with a general-purpose assistant and vibe-code it into something that is only yours.