MaxyDocs
View as markdown →

Plugins Guide

What a Plugin Is

A plugin extends what Maxy can do. Each plugin adds a focused capability — contacts management, Telegram messaging, scheduling, email, research. Plugins are modular: you enable only what you need.

Maxy's own capabilities are plugins too. Marketplace plugins (like Stripe) work the same way — Maxy manages all of them through conversation.

The tables below are the install catalogue — every plugin the platform can ship. They are not evidence of what is enabled on the current account. For the live install set, ask Maxy to call capabilities-here.

Plugin Groups

Core (always active)

These are part of Maxy's foundation and cannot be disabled:

PluginWhat it does
adminPlatform management — system status, account settings, logs, session control. Also hosts the cross-cutting plainly skill: every text-producing agent (admin, public, every specialist) applies a plain-English precision pass to prose returned to humans, as a prime-directive prerogative. Agent-to-machine payloads (image-generate prompts, memory-write arguments, cypher) pass through verbatim. This is a prompt-level skill contract, not a hook: each agent's IDENTITY loads skill-load skillName=plainly on its first text-producing turn and applies the pass thereafter. Hosts the superpowers-sprint skill: structured sprint workflow built on the superpowers and code-review upstream plugins, dispatched on "run a sprint" or any .tasks/NNN-*.md invocation.
memoryGraph memory — search, write, reindex, and ingest knowledge
browserHeadless browser rendering — browser-render runs a JavaScript-heavy page in the device's Chromium and returns its rendered DOM. The JS-rendering leg of retrieval: WebFetch (summary) / url-get (verbatim, server-rendered) / browser-render (JS-rendered).
maxy-guideUser guide and platform documentation (this plugin)
cloudflareCloudflare Tunnel — remote access via your custom domain
schedulingCalendar and scheduling — events, appointments, recurring triggers. Any activity involving time (date, timestamp, day of week, month, duration) routes through time-resolve first. Two read-only tools (current-datetime, time-resolve) are always available to every public agent regardless of enabled plugins.
emailAgent email account — setup, read, send, reply, search, auto-respond
tasksTask lifecycle — create, update, list, relate, complete
workflowsPersistent named workflows — reusable instruction sets
contactsCRM contact management — create, lookup, update, list
prompt-optimiserPrompt optimiser — two modes. Chat-app mode turns a rough draft or task description into a single finished, copy-pasteable prompt tuned for Opus 4.7 adaptive thinking (claude.ai, Mac, iOS). In-session mode is applied automatically: a standing UserPromptSubmit directive hook (admin/hooks/prompt-optimiser-directive.sh) injects context every turn telling the admin agent to restate each non-trivial prompt through this skill and act on the restatement, skipped for one-word confirmations, slash-commands, and direct continuations. Compliance is behavioural — the hook steers the agent, it cannot force the skill call.
url-getFaithful page retrieval — fetches a server-rendered page, writes a verbatim markdown copy to an account-scoped reference file (no model in the path, so no copyright refusal), and returns a transformative summary plus the file path. Use instead of WebFetch when a faithful copy is needed (e.g. ingesting your own published writing).

Maxy Plugins (user-selectable)

These are enabled during onboarding and can be added or removed at any time. Some plugins enhance a specific specialist role — when enabled, that specialist gains additional capabilities.

PluginWhat it doesEnhances
business-assistantCustomer enquiries, scheduling, quoting, invoicing, daily briefingsPersonal assistant
salesBuying signal detection, closing techniques, objection handlingPersonal assistant
deep-researchStructured multi-source research — query decomposition, source evaluation, citationsResearch assistant
projectsStructured project execution — phased sprints, investigations, reviews, retrospectivesProject manager
telegramTelegram bot — BotFather setup, messaging, channelsPersonal assistant
whatsappWhatsApp messaging, pairing, and conversation browsingPersonal assistant
replicateImage generation — three models for photorealistic, design, and fast draft imagesContent producer, Research assistant
linkedin-importImport a LinkedIn Basic Data Export — Profile and Connections today, more CSVs as references landDatabase operator
notion-importImport a Notion workspace export (markdown + CSV) — pages, databases, hierarchy, attachments, schema-bounded relations, @person mentions account-filteredDatabase operator
obsidian-importImport an extracted Obsidian vault — pages map to :KnowledgeDocument, wikilinks resolve to intra-vault pages or existing entities, tags become :DefinedTerm, embedded images become :DigitalDocument. Two-phase tool (dry-run → operator disambiguation → commit).Database operator
x-importImport an X (Twitter) Basic Data Export — tweet stream renders as one chronological transcript and ingests as a single :KnowledgeDocument (source='x'); each DM sessionId ingests as one :ConversationArchive (source='x-dm', keyed on conversationIdentity) via conversation-archive-ingest.sh. Mentions, replies, and quote-tweet authors resolve to :Person on lowercased xHandle; every handle and DM senderId confirms against existing nodes (no auto-create). Per-thread KD granularity and :Post / :DirectMessage labels are explicitly rejected.Database operator
substack-importImport a Substack "Export your data" archive — per-essay :KnowledgeDocument {kind:'substack-post'} via librarian/document-ingest with synthetic stable attachmentId = "substack-post-${substackPostId}" (survives Substack edits); one :KnowledgeDocument {kind:'substack-subscriber-roster'} per import run with :MENTIONS {mentionContext:'substack-subscription', tier, totalOpens, totalClicks, lastOpenedAt, lastClickedAt, engagementWindowDays} to each subscriber :Person MERGEd on (accountId, email). Engagement aggregates parsed from email_activity.csv (or subscriber_activity.csv / emails.csv); overwrite-on-reimport. No new label, no new edge type, no new graph writer. Images attach via canonical :HAS_ENCLOSURE (or :MENTIONS fallback). Bulk-gate at >200 posts or >2000 subscribers.Database operator
memory/skills/conversation-archiveSource-agnostic conversation transcript ingest. One skill for WhatsApp _chat.txt, Telegram, Signal, LinkedIn DMs, Zoom transcript, meeting minutes, iMessage, Slack, X DMs — --source <enum> selects the per-source normaliser. Single Bash entry — bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source <enum> --participant-person-ids <csv> --scope <admin|public> — runs normalise → operator-confirms owner + every distinct sender (owner derived from env via Cypher, no flag) → sessionize at the fixed 8h gap → emit one JSON line carrying prepared sessions (turn-attributed text + per-session cursor). The dispatched specialist iterates the sessions in-turn, produces a typed-section JSON chunking for each, and calls the memory-ingest MCP tool with conversationIdentity set (writes :ConversationArchive, source=<enum>) once per session — chunks + cursor advance commit atomically inside one Cypher transaction, so a kill mid-archive resumes from the next session on re-issue without re-classifying anything already written. Re-imports are delta-append. Auto-creating participants is forbidden — any sender outside the operator-confirmed closed set LOUD-FAILs with parser-miss. Distinct from the live whatsapp plugin (Baileys).Database operator
memory/skills/conversation-archive-enrichPhase 2 for any named :ConversationArchive — source-agnostic per-row insight derivation. Operator-triggered (never auto-fires on Phase 1 completion). Walks the parent's :Section chunks in pages via the read-only MCP tool mcp__plugin_memory_memory__conversation-archive-list-chunks; the dispatched specialist reads each chunk in-turn and emits claims under the four-kind contract (mention, task, preference, observed-relationship); the skill hands those claims to mcp__plugin_memory_memory__conversation-archive-derive-insights for per-kind cypher emission, then runs the per-row operator gate (wire / skip / reject). Idempotent on (elementId(chunk), kind, contentHash) — re-runs collapse identical claims. Confidence floor is a hedging-avoidance instruction the skill embeds in the specialist's per-chunk prompt, not a numeric post-filter; per Task 433 the LLM step runs in-turn from the dispatched specialist rather than as a server-side OAuth round-trip.Database operator

Claude Official (marketplace)

Third-party plugins from the Claude marketplace:

PluginWhat it does
stripeLive access to payment and business data

Claude Anthropic Verticals (marketplace, opt-in)

Optional plugins from Anthropic's vertical marketplaces. The installer registers claude-for-financial-services and knowledge-work-plugins so the install commands work; none are auto-installed. You pick each deliberately during first-run onboarding (Step 1) or by name at any time.

PluginMarketplaceWhat it does
kyc-screenerclaude-for-financial-servicesParses onboarding documents, runs a rules engine, flags gaps. Outputs are draft work product for human review — your compliance specialist owns sign-off. Relevant to UK estate agents under MLR 2017.
meeting-prep-agentclaude-for-financial-servicesBriefing pack before every client meeting, FSI-flavoured templates. Overlaps with the business-assistant calendar-prep flow — choose one deliberately.
pdf-viewerknowledge-work-pluginsLive interactive viewer to view, annotate, and sign PDFs — mark up contracts, fill forms, stamp approvals, place signatures, download the annotated copy. Click-through replaces conversation for this surface (v0.2.0, different shape from chat-driven skills).

Install verbatim:

  • claude plugin install kyc-screener@claude-for-financial-services
  • claude plugin install meeting-prep-agent@claude-for-financial-services
  • claude plugin install pdf-viewer@knowledge-work-plugins

Premium Plugins

Brand decides which premium plugins ship. The brand's shipsPremiumBundles field in brand.json is the gate; three shapes are supported:

  • omitted / false — ship nothing from premium-plugins/ (the legacy Maxy default).
  • true — ship every bundle under premium-plugins/* (Real Agent / realagent-code).
  • ["bundle-a", "bundle-b"] — ship only the named bundle directories (Maxy Code's ["venture-studio"]). Names with no matching directory on disk are silently dropped; non-allowlisted bundles are stripped from any account that was previously stamped with them.

There is no per-account purchase record; the brand decides the shipping set.

PluginTypeWhat it doesPublic agent
teachingSkillsInteractive tutoring, lesson planning, and study pack generation from your knowledge baseYes — all 3 skills serve students and parents
real-agentBundle (13 sub-plugins)UK estate agency skills — sales, listings, vendor management, buyer management, lead generation, coaching, business operations, teaching, Loop CRM (five value pillars: auto-respond, viewing lifecycle, pipeline mining, listings prospecting, maintenance & preferences), PropertyData market analytics (valuation, sold prices, £/sqft baselines, £/sqft growth, demand-rent, area risk, planning precedent, UPRN matching, property-type distribution), gov.uk EPC floor-area lookup, property brochures, social-share image cards, A4 market reports, and single-address preval packs (full UK address → 4-page A4 PDF covering valuation, area, and demand). 3 specialist roles (negotiator, valuer, compliance)4 sub-plugins (estate-sales, buyers, estate-coaching, estate-teaching)
writer-craftSkills + AgentManuscript review and writing craft — story architecture, reader engagement, prose craft, editorial practice, and multi-level reviewNo — writing craft serves the author
venture-studioSkills + AgentFounding-a-business workflow — office-hours discovery, brand pack, zero-to-prototype validation, and the full investor data room (business plan, prospectus, term sheet, deck blueprint, A4 print pipeline). Pre-seeds a Project with one Task per artefact so nothing gets forgotten.No — founder-facing only

How it works: Every boot Maxy delivers the brand's premium plugins from staging into platform/plugins/ and stamps enabledPlugins against what is actually on disk. No conversation needed — the brand's full set is active from the first turn after install. Updates and reinstalls re-deliver from staging.

Some premium plugins are bundles — multiple sub-plugins shipped under one directory in premium-plugins/, each independently activatable. For example, Real Agent ships 10 sub-plugins covering different aspects of estate agency work. They are all enabled by default. Sub-plugins you don't want active can be turned off individually with "disable <name>"; enabling or disabling individual sub-plugins does not affect the others.

If you ask Maxy about a tool from a plugin your brand does not ship (for example, a Maxy install asking about a Real Agent Loop CRM tool), Maxy responds with a structured <tool-surface-error> envelope naming the missing plugin and the remedy, rather than improvising with a generic alternative.

Public agent embedding: Premium plugins marked as public-eligible have their full content (skills and reference knowledge) embedded in public agent prompts. This means a public agent for a Real Agent member can handle buyer enquiries, book viewings, deliver coaching content, and onboard new applicants — all powered by the premium plugin's domain knowledge. Plugins marked admin-only (listings, vendors, leads, business) are only available to the account owner's admin agent.

Some premium plugins include specialist helpers that Maxy can dispatch for specific tasks (e.g. the writer-craft plugin includes a manuscript reviewer). These are activated automatically when the plugin is enabled.

Some premium plugins include pre-built public agent templates — ready-made configurations for customer-facing agents. When you enable the plugin, Maxy shows you what templates are available and offers to create agents from them. You review and approve every file before the agent is created. The template is a starting point — you can edit the identity, personality, plugins, and settings to make it yours. The result is a standard public agent, indistinguishable from one you created from scratch.

Some premium plugins ship pre-built workflows that are created when the plugin is enabled. These workflows are fully yours — you can inspect, edit, run, and manage them through conversation, exactly like workflows you create yourself. The plugin provides the starting point; you own the result.

If a premium plugin ever stops workingdocuments, teaching, anything else you've paid for — and Maxy responds as if it doesn't have those tools, the platform's health check (/api/health.missingPlugins) will name the affected plugin. Tell Maxy "deliver the {{plugin}} plugin" — it re-runs the same delivery step that fires automatically at session start. If the plugin isn't in the device's staging area, re-run the installer for this brand.

Choosing Plugins

During first-time setup, Maxy presents a plugin selection screen where you choose which plugins to activate. Core plugins are pre-selected and locked. Recommended plugins are pre-selected but optional. You can change your mind later.

Adding or Removing Plugins

Tell Maxy:

  • "Enable the Telegram plugin"
  • "Add the Stripe plugin"
  • "Disable the deep-research plugin"

Maxy handles the installation or removal. If the plugin requires any setup (API keys, bot tokens, configuration), Maxy will walk you through it.

Viewing Your Plugins

Ask Maxy: "What plugins do I have?" or "List my plugins."

Operator-Authored Plugins (skill-builder output)

Skills you create at runtime through the admin skill-builder skill are saved on disk as their own plugin under data/accounts/{accountId}/plugins/{pluginName}/. The admin agent calls mcp__plugin_admin_admin__store-skill, which composes PLUGIN.md (on first call) and skills/{skillName}/SKILL.md plus any reference files. The agent supplies pluginName, skillName, description, publicEmbed, body, and optional references — the path is computed by the tool, never by the agent.

These operator-authored plugins survive reinstall because the installer's wipe zone excludes data/. At admin session start the platform mirrors data/accounts/{accountId}/plugins/* into the runtime plugins directory so the same parsePluginFrontmatter / assemblePublicPluginContent / loadEmbeddedPlugins loaders that read shipped and premium plugins also pick up operator-authored ones — no special-case loader path. The admin agent sees every operator skill by default; per-skill publicEmbed: true|false controls which skills surface to the public agent.

To edit an operator-authored skill later, ask Maxy to update it — the admin agent re-runs store-skill for the same pluginName/skillName and the new content overwrites in place. To remove one, delete the directory under data/accounts/{accountId}/plugins/{pluginName}/skills/{skillName}/ (or the whole plugin) — the next session start re-mirrors the remaining skills only.

pluginName collisions with shipped plugin names are refused by store-skill with a structured error. See .docs/agents.md § "Operator-authored skills as plugin files" for the full contract.

Brand Templating (for plugin and skill authors)

Skill content, plugin manifests, agent templates, and reference files reference the operator-visible brand name only via the literal Maxy placeholder. The platform substitutes from brand.json.productName at read time — Maxy installs render Maxy, Real Agent installs render Real Agent, all from the same source content.

Author rule: never write the literal string Maxy (or any brand name) in shipped skill, plugin, or template content. Use Maxy whenever the operator should see the brand name. The audit grep grep -rn "\bMaxy\b" platform/plugins/admin/skills/ platform/plugins/*/skills/ platform/templates/agents/ must return zero matches; a literal brand name is a defect, not a stylistic choice.

The runtime substitution happens at every read site that flows content into a system prompt or operator-visible UI: the admin agent's plugin-read tool (references + PLUGIN.md), the skill-load tool (SKILL.md by skill name — one-call resolver+reader, the canonical primitive for SKILL.md), the public agent's recursive plugin assembly, and IDENTITY / SOUL / AGENTS / KNOWLEDGE markdown reads. Missing or empty productName hard-fails — there is no fallback to a default brand string. See .docs/agents.md § "Brand templating" for the full contract.

MCP Plugin Observability (for plugin authors)

Every console.error line from a plugin's MCP server can be teed into the per-conversation agent stream log so a single logs-read call returns one conversation's full timeline — agent events and plugin diagnostics interleaved in chronological order.

Opt-in (one line at the top of the MCP server's entry file):

import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
initStderrTee("your-plugin-name");

After this, every console.error("[your-tool]...") from any tool in the plugin appears as [<iso-ts>] [mcp:your-plugin-name] [your-tool]... in the per-conversation stream log claude-agent-stream-{sessionId}.log, alongside the usual agent events. The raw per-server file mcp-your-plugin-name-stderr-{date}.log is still produced for deep-dive grep.

Premium plugins. Source lives at premium-plugins/<bundle>/plugins/<name>/mcp/src/ — deeper than platform plugins, so the source-relative import to platform/lib/mcp-stderr-tee/dist/index.js uses more ../ segments. The bundler rewrites the compiled output to the canonical ../../../../lib/mcp-stderr-tee/dist/index.js at staging time and ships platform/lib/mcp-stderr-tee/{dist,package.json} into premium-plugins/<bundle>/lib/mcp-stderr-tee/ so the import resolves at deployed depth. The bundler fails loudly if platform/lib/mcp-stderr-tee/package.json is missing (it must pin type so install-location parent walks cannot mis-classify the dist file) or if any lib referenced by a rewritten import has no source dist.

How the tee decides which file to write to: the platform sets STREAM_LOG_PATH as an environment variable on every MCP server spawn, pointing to the conversation-scoped stream log. The MCP server does not know about conversations — it just trusts STREAM_LOG_PATH. Multiple concurrent conversations produce multiple concurrent MCP server processes, each teeing to its own file; no cross-conversation leakage.

Bash commands stream straight into the PTY. Maxy Code's admin and public chat run on the native Claude Code PTY (Task 287). The per-conversation server-side stream log that the retired web-UI dispatcher tailed is gone; agent-invoked Bash commands (including direct cloudflared invocations for Cloudflare setup — Task 288) print their stdout and stderr directly, and the PTY renders the output in chat verbatim.

Retrieve MCP diagnostic lines for a conversation:

  • All servers: logs-read { type: "system", sessionId: "..." } → grep [mcp:<name>] on the returned stream log.
  • One server raw feed: logs-read { type: "mcp" } → tails the most recent mcp-<name>-stderr-*.log (per-plugin, not per-conversation).

Tee-state markers land in the stream log: [platform] [mcp-tee-attach] server=<name> streamLogPath=... when the tee wires up, [platform] [mcp-tee-skip] server=<name> destination=... reason=... when a destination fails (missing LOG_DIR, unwritable path, STREAM_LOG_PATH not set, etc.), [platform] [mcp-tee-detach] server=<name> on graceful shutdown. If a server invoked tools but no [mcp:<name>] lines appear in the conversation's log, look for the skip marker first.

Main-subprocess stderr. The same teeing pattern applies to the main Claude Code subprocess's stderr — every line lands in the per-conversation stream log as [subproc-stderr] …, with lifecycle markers [subproc-stderr-tee-attached] pid=… and [subproc-stderr-tee-detached] pid=… bytes=N lines=N. A bytes=0 lines=0 detach means the tee was attached but the subprocess emitted nothing on stderr — which is the normal state today, because the Claude Code CLI is a bundled Bun runtime binary that does not honour Node's NODE_DEBUG env var. The platform records this explicitly with one line per spawn: [subproc-debug-unavailable] reason=bundled-bun-binary-ignores-node-debug pid=… cli=claude. A reader who finds a [spawn] without these markers should treat that as a regression of the tee infrastructure, not as silence.

Failure-path observability contract (earlier platform fixes + earlier platform fixes)

The initStderrTee wrapper writes to the per-conversation stream log and per-server raw file via createWriteStream — async, buffered. Any diagnostic console.error(…) followed by an immediate process.exit(…) is lost: the event loop never drains the WriteStream before the process terminates. Same race for any synchronous module-load throw: Node's uncaught-exception handler writes the stack to raw fd 2 and exits before the patched async stream flushes. The platform's [mcp-init-error] tail="(no stderr file)" line — operationally useless — is the public symptom of this race.

Two layers now close the gap, each load-bearing on its own:

  1. Plugin-side sync-write discipline. Plugins that call process.exit during module load (rare — graph-mcp is the in-tree example; it spawns a child at boot to proxy upstream stdio) use fs.appendFileSync at every named exit path to guarantee the cause lands in both log destinations before exit. Lines follow the [mcp:<name>] [<plugin-prefix>] <cause> format so existing grep '[mcp:<name>]' investigator paths work. Each destination is wrapped in its own try/catch — an unwritable log must not mask the primary failure. This is the discipline propagated to any plugin author who knows their failure paths.

  2. Parent-side mcp-spawn-tee wrapper. Every node-based core MCP server is spawned via the lib/mcp-spawn-tee wrapper rather than node <entry> directly. The wrapper spawns the real entry with stdio: ['inherit', 'inherit', 'pipe'] and writes child stderr chunks to ${LOG_DIR}/mcp-${name}-stderr-<date>.log via appendFileSync while passing the same chunks through to its own stderr (Claude Code's consumer is unchanged). Synchronous appendFileSync survives process.exit, so the per-server file captures even (a) module-load throws before initStderrTee runs, (b) MODULE_NOT_FOUND on the entry script itself, and (c) anything else a plugin author missed. The wrapper writes [mcp-spawn-tee-attached] server=<name> pid=<n> on attach and forwards SIGTERM/SIGINT to the child. This is the layer that makes capture independent of plugin discipline. Playwright stays unwrapped because it spawns via npx, not node.

A third layer closes the same gap from the platform side: when claude-agent.ts observes an init event with any MCP server reporting status:"failed", it reads the last 512 bytes of ${LOG_DIR}/mcp-<name>-stderr-<date>.log and emits [mcp-init-error] server=<name> tail=<quoted> into the stream log. Absent file → tail="(no stderr file)"; empty file → tail="(empty)". With the spawn-tee wrapper now interposing on every core MCP, tail="(no stderr file)" post-Task-743 means the wrapper itself is broken — file follow-up.

Signal inventory after a failed session: [init] FAILED MCP servers: <names> (names), [mcp-init-error] server=<name> tail=… (cause for each, from the platform's tail probe), [mcp-spawn-tee-attached] server=<name> pid=<n> (proof the wrapper attached), [mcp-spawn-tee-exit] server=<name> code=<n>|signal=<s> (proof the wrapper saw the exit), and optionally [mcp:<name>] [<plugin>] … from plugin-side sync-writes. Their union gives the investigator three independent sources for the same failure.

Boot-smoke as publish-time gate. The memory MCP carries scripts/boot-smoke.sh that spawns dist/index.js with stub env, sleeps 2s, asserts kill -0 <pid>, and reports [boot-smoke] memory ok|FAILED tail=<n-lines>. Wired to prepublish in plugins/memory/mcp/package.json. The pattern is propagatable to other plugin MCPs — it's deliberately not generalised yet because each plugin's stub-env requirements differ (memory needs ACCOUNT_ID + PLATFORM_ROOT + NEO4J_URI + SESSION_ID; others differ).