memcode docs
Agents

Agents

Run memcode as an always-on assistant that answers on the channels you use and works in the projects you register.

Memcode can be your always-on assistant. One gateway runs on your machine, answers on the channels you already use, and turns each message into real work in your projects, replying with the result. Coding is one thing it can do, not the only thing.

Three ideas are kept deliberately separate:

  • Agent is who you are working with: an assistant with its own identity (SOUL.md), memory, and skills. For example personal, coder, researcher.
  • Project is what you are working on: a registered working directory the agent executes in. One agent works across many projects.
  • Conversation is a channel thread that remembers its current agent and project, so you do not repeat yourself every message.

There is one gateway per machine, not one per repo: it owns all your channels, and a second one refuses to start instead of breaking your bots. Every task runs in its own process, so one stuck task can never freeze the gateway or your other conversations.

Prefer talking to typing config? memcode admin does everything below by conversation.

Want to see what people actually run? The Examples section has copy-paste recipes for the ten most common automations, from a morning briefing to CI-failure diagnosis in your chat.

Set up a channel from its own page:

Configure

One command handles channel setup:

memcode gateway setup

Bot tokens are secrets, so they go in the global .env (~/.config/memcode/.env); non-secret settings go in ~/.config/memcode/gateway.yaml. Both live in one global config dir, per machine. The gateway keeps its own working state there too, never inside a repo.

gateway.yaml

allow_all: false        # no one is allowed until you add them per channel below
webhook:
  addr: ":8787"         # inbound listener for GitHub, WhatsApp, Teams, Google Chat, SMS
agents:
  personal: { type: assistant }
  coder:    { type: coding }
projects:
  memcode:  { path: ~/github/memcode, enabled: true }   # add via `memcode project add`
default_project: memcode
channels:
  telegram:
    allow_from: ["123456789"]   # stable user ids (not @handles); "*" allows anyone
    agent: personal             # which agent this channel talks to
    # tier: strong              # route this channel to a stronger model
schedules:
  - name: standup
    cron: "0 9 * * 1-5"
    task: "Summarize yesterday's commits and open PRs"
    deliver_to: "telegram:123456789"

Agents

An agent is a lasting assistant identity with its own home at ~/.memcode/agents/<name>, holding its identity file SOUL.md (who it is, how it behaves — the same filename OpenClaw and Hermes use, so a migrated agent keeps its soul), its own memory.md, and skills. Bind a channel to one with channels.<name>.agent, or switch inside a conversation:

/agent coder

An agent's context layers on top of your user-global memory (~/.memcode/memory.md) and the project's own memory, so a coder working in a repo still gets that repo's full codebase intelligence. Its skills join skill discovery the same way.

Each agent also keeps its own conversation transcript: switching /agent switches to that agent's session in the thread, and switching back resumes where it left off. One agent never inherits another's conversation.

An agent can also pin the model that drives it and how hard it thinks — wherever it answers, on any channel or schedule:

agents:
  personal:   { type: assistant }
  researcher: { type: research, model: claude-opus-5, reasoning: high }

Leave model unset for automatic routing and reasoning unset to let each turn's depth be judged automatically (off, medium, and high pin it). Or just tell memcode admin: "make the researcher always use Opus and think hard".

Schedules

A schedule runs a task on a timer and delivers the result to a conversation, so your assistant reports in without being asked. Each schedule has a name, a cron expression for when, the task in plain language, and a deliver_to target:

schedules:
  - name: standup
    cron: "0 9 * * 1-5"          # weekdays at 09:00
    task: "Summarize yesterday's commits and open PRs"
    deliver_to: "telegram:123456789"

cron is minute, hour, day of month, month, day of week. Common patterns: 0 9 * * 1-5 is weekdays at 9am, 0 * * * * is every hour, 0 18 * * 5 is Friday at 6pm. Prefer intervals? Use every: "30m" instead of cron. Need it once, not forever? at: "2026-03-01T09:00:00Z" runs a task one time and then removes itself — "remind me at 3pm" is a schedule too.

Manage them from the terminal (the cron alias works if that's the word your fingers know):

memcode gateway schedule list
memcode gateway schedule add standup --cron "0 9 * * 1-5" --to telegram:123456789 "Summarize yesterday's commits and open PRs"
memcode gateway schedule add remind --at 3h --to telegram:123456789 "Remind me to review the release notes"
memcode gateway schedule run standup       # fire it now, don't wait
memcode gateway schedule disable standup   # pause without deleting; enable resumes
memcode gateway schedule remove standup

A schedule can run as a specific agent (--agent researcher) — bringing that agent's identity, memory, and pinned model — and evaluate its cron expression in a named timezone (--tz America/Los_Angeles).

Changes take effect on a running gateway within seconds — no restart. Or skip the syntax entirely: tell memcode admin "every weekday at 9am, ..." and it writes the schedule for you. Ready-made recipes live in Examples.

Voice

A voice note sent to the bot on Telegram, WhatsApp, Signal, or as an email attachment is transcribed and treated as the task, so you can speak a job instead of typing it. Transcription needs an OpenAI or Gemini key on the gateway machine.

Replies can optionally come back as voice notes too. Set voice_replies: in_kind under a channel in gateway.yaml to answer voice with voice, or always to speak every reply. It is off by default.

Projects

Register the directories the gateway may work in:

memcode project add ~/github/memcode
memcode project list

A message can only run against a registered project; it can never point the agent at an arbitrary path on your machine. Switch the conversation's project with:

/project memcode

Switching affects your next message, not one already running: a task locks in its agent and project the moment the message arrives.

A channel can also be limited to specific projects with channels.<name>.projects: useful in a shared group channel, where one member shouldn't be able to point the conversation at your other repos:

channels:
  discord:
    projects: [www]   # /project on this channel accepts only these ids

Authorization and triggering

Two independent checks gate a chat message.

Who. The gateway answers no one until you say so: a message is ignored unless its sender is in that channel's allow_from. Access is granted by the sender's permanent user id, never their @handle, so a renamed or lookalike handle can't gain access.

When. A direct message always gets a response. In a group the bot acts only when it is addressed (mentioned or replied-to), so ordinary chatter doesn't trigger it. Set respond_to_all: true to act on every message. GitHub deliveries are verified with your webhook secret, so they skip both checks.

Pairing: adding people without hunting for ids

When someone the gateway doesn't know sends the bot a direct message, the bot replies once with a short pairing code. They send you the code, and you approve them from your terminal:

memcode gateway pair                  # see who's asking
memcode gateway pair approve K3QP7M   # let them in
memcode gateway pair deny K3QP7M      # or don't

Approval takes effect within seconds, no restart. Codes expire after an hour, a stranger only ever gets one code no matter how many messages they send, and nothing they say runs before you approve them.

Safety

A gateway job runs the agent with no terminal to answer approval prompts, so the permission gate fails closed: destructive commands are denied automatically rather than run. A chat message cannot turn into remote code execution on your machine, and it cannot execute against an unregistered directory. Allow-list only people you trust, and treat allow_from: ["*"] and respond_to_all as deliberate choices (the gateway warns at startup if either is set).

Migrate from OpenClaw or Hermes

One command moves your whole install, memory included:

memcode claw migrate       # from OpenClaw
memcode hermes migrate     # from Hermes

See Migrate from OpenClaw or Hermes. Migrated memory lands in your user-global store (~/.memcode/memory.md), shared by every agent.

Run

Start the gateway:

memcode gateway

To keep it running across logout and reboot, install it as one machine-global background service:

memcode gateway install

This writes a launchd LaunchAgent on macOS or a systemd user unit on Linux. memcode gateway uninstall removes it. Chat channels connect outbound, so they need no public URL; GitHub and WhatsApp are inbound webhooks served on :8787.

Reliability

The gateway is built so you can trust it with real work:

  • Messages are not lost. Every message is saved before the gateway acknowledges it to the platform. If the gateway restarts or your machine reboots, pending work picks up where it left off.
  • Nothing runs twice. If a platform delivers the same message again, the duplicate is recognized and dropped. A finished task is never re-run just to recover its reply; if sending the reply fails, only the send is retried until it lands.
  • Conversations stay in order. Messages in one conversation are handled one at a time, in order, and a burst of messages can't overwhelm your machine.

GitHub support is focused: a failed CI run becomes a task and the result is posted to your chat channel; it is not a full GitHub App. WhatsApp stays inactive until Meta verifies your business. The gateway keeps its own state in ~/.config/memcode; anything a task changes stays in the project it ran in.

On this page