Run the DuploCloud AI HelpDesk platform on your laptop in containers — then build your own Agent against it. Each Agent you write ships a backend, a UI, and its own provisioning, and hot-loads into the running platform with no restart.
- A whole platform, locally. Seven containers, one command.
- Your own resource types. Not plugins bolted on the side — they get a REST API, a portal UI, and a provisioning workflow, exactly like the built-in types.
- Hot-load, no restart. Build, deploy, and the new type is live in the UI seconds later.
- AI-guided authoring.
/duplo-extensionin Claude Code scaffolds and builds an Agent from a plain-language requirement.
You need a container runtime with Compose v2 (docker or podman — set RUNTIME
in .env to pin one, otherwise it is auto-detected), Python 3, and access to an LLM. ./run.sh prompts for
Anthropic, AWS Bedrock, or an Anthropic-compatible LLM gateway (OpenRouter, Bifrost, LiteLLM, …).
git clone https://github.com/duplocloud/devkit my-agent && cd my-agent
./run.shFirst run asks for an admin email — a work or personal address you can read right now (privacy-relay and disposable domains are not accepted) — and DuploCloud emails you a verification link. Click it and the run continues on its own, then asks for a password and an LLM provider and brings the stack up, registering your chosen provider's model as the System default LLM. Sign in at http://localhost:4210.
That is the platform up. To make it do something, pick one:
→ Quickstart — connect an AWS account with a read-only access key and ask the agent real questions about it — "list all S3 buckets" — then build your first Agent: a domain whois lookup that hot-loads into the platform you just started.
→ Getting started — the full path, one page at a time: adopting the repo, connecting AWS and Kubernetes, then building s3-guard — an Agent that scans every bucket in a region against six security rules, charts the violations over time, and fixes the ones you tick.
docker-compose.yml |
The platform from published images: mongo, qdrant, studio, agent, dind, ui, xterm, installer |
.env / .env.example |
Image tags, auth, LLM credentials, and the build target |
run.sh stop.sh logs.sh |
Lifecycle |
scripts/ |
Build, deploy, register, and upgrade |
samples/ |
Worked reference Agents |
.claude/ |
The /duplo-extension authoring command, its skill, and 20 reference guides |
extensions/terraform/ |
The real, shipping Terraform extension — source, fetched once by run.sh, disconnected from git and yours to modify |
extensions/<name>/ |
Yours (subject to our and any third party's rights in the underlying software and technology upon which they are built). The one thing an upgrade never touches |
The installer service installs extensions into the running studio and keeps them current.
Your own build. Build it into extensions/[name]/dist/:
./scripts/build-extension.sh extensions/[name]The installer installs each build in extensions/[name]/dist/ that changes while it runs, within about 20 seconds,
including a rebuild at the same version. The studio may keep running the previous backend DLL after a same-version
reload, as deploy-extension.sh warns, so bump the version for backend changes.
A build already in dist/ when the installer starts, as after ./run.sh --reset, waits for its next rebuild, and so
does an extension you remove. The installer also leaves alone a build older than the installed version, unless that
version failed to load.
./scripts/deploy-extension.sh extensions/[name]/dist/extension.zip hands that build to the installer while it runs,
waits for the installer to report it, and exits non-zero with the installer's reason when it does not install it. For
a build the installer leaves alone, with the installer stopped or EXTENSIONS_ENABLED=false, for an id in
EXTENSIONS_EXCLUDE, or for a zip outside extensions/, it loads the zip itself.
The installer reinstalls a same-version rebuild only over a build it installed itself. After a load it did not make,
such as deploy-extension.sh with the installer stopped or Extension Studio's in-platform flow, bump the version or
run ./scripts/remove-extension.sh [id] before relying on the installer for a rebuild.
From the catalog. The Available tab lists the extensions your license entitles you to. Install there hands
the click to this installer only once the UI tag and the studio tag in .env.example are images that do that.
Those two tags predate that handoff. The installer reads that catalog only when .env sets these keys, so by
default it runs on your own builds alone:
LICENSE_SERVER_URL=https://console.duplocloud.com
URL_ROUTE_URL=https://results.prod-apps.duplocloud.net/urls
CHANNELS_BASE_URL=https://channels.prod-apps.duplocloud.net
CHANNELS_BUCKET=duplo-helpdesk-channelsRe-run ./run.sh after changing them. EXTENSIONS_ENABLED=false in .env stops the installer installing anything,
and EXTENSIONS_EXCLUDE takes a JSON array of extension ids it leaves alone. docker-compose.yml lists the other
EXTENSIONS_ keys it passes through.
How it checks an install. The installer judges an install by the studio's /healthz and the extension's row. It
sees a studio restart only as missed /healthz reads spanning at least 5 seconds followed by an answer. A quicker
restart goes unseen, and the row alone then judges the install.
A load that hangs the studio. Under compose the installer backs out only through the studio's API, so it cannot
back out a build that hangs the studio when it starts. Stop the studio, disable the extension's row by hand, with
[id] its manifest id, and start the studio again:
docker compose stop duplo-ai-studio
docker compose exec mongo mongosh -u authuser -p authpass --authenticationDatabase admin duplo-ai-helpdesk \
--eval 'db.loaded_extensions.updateOne({ExtensionId: "[id]", IsCurrent: true}, {$set: {Status: NumberInt(1)}})'
docker compose start duplo-ai-studioTo install a fixed build, run ./scripts/remove-extension.sh [id] and then rebuild. The rebuild has to differ in
content from the build that hung, since the installer may hold that exact build. An install whose load timed out also
waits until you restart the studio, with docker compose restart duplo-ai-studio. Under podman, use podman compose
for each docker compose above.
| Page | What it covers |
|---|---|
| Getting started | Prerequisites, adopting the repo, and your first extension |
| Architecture | How the services fit together and how hot-loading works |
| Configuration | Every .env variable, its default, and its effect |
| CLI reference | run.sh, stop.sh, logs.sh, and every script — flags and behavior |
| Upgrading | Taking framework updates without losing your work |
| Troubleshooting | Symptoms, causes, and fixes |
| FAQ | Licensing, data, and platform support |
The full documentation index has everything, including the extension-authoring reference guides.
- The dev-kit source is open source. Everything DuploCloud authored here —
run.sh,scripts/,samples/,docker-compose.yml,nginx/,.claude/— is Apache-2.0. Clone it, modify it, redistribute it. That's the point. - The container images are not. The
quay.io/duplocloud/*images this kit runs are proprietary, licensed separately under TERMS.md, and may not be modified. - The vendored UI library is not, either. The tarball every sample installs from the repo-root
packages/is the compiled DuploCloud platform UI library (@duplocloud-internal/ng-common-lib) — proprietary DuploCloud IP, not open source, and not covered by the Apache License despite living undersamples/. You may build your Agents against it and ship the parts your build bundles into a compiled Agents; you may not republish, repackage, or modify it. See TERMS.md and theNOTICEbeside each tarball. - This kit is for local development only. As more fully described in the TERMS, the closed source materials are provided for non-production use only.
- Going to production? Contact sales@duplocloud.net for a production license.
- Your Agents are yours. DuploCloud claims no rights in anything you write under
extensions/. See NOTICE for the full breakdown.
| Document | What it covers |
|---|---|
| LICENSE | Apache-2.0 — the dev-kit source DuploCloud authored (run.sh, scripts/, samples/, docker-compose.yml, nginx/, .claude/). Use, modify, and redistribute freely. Does not cover the vendored library tarballs under packages/ or **/frontend/vendor/. |
| NOTICE | The boundary: what Apache-2.0 covers, what it doesn't (the container images and the vendored UI library), and the third-party images. Apache-2.0 §4(d) requires you to keep it in any redistribution. |
| TERMS.md | The proprietary pieces that are not Apache-licensed: the quay.io/duplocloud/* container images (local development only, no modification, production requires a separate license) and the vendored @duplocloud-internal/ng-common-lib tarball (build against it and ship what your build bundles — nothing else). Also confirms you own your extensions. |
| SECURITY.md | Reporting a vulnerability. Email ai-reporting@duplocloud.net — don't open a public issue. |
| PRIVACY.md | The usage metrics the UI sends if you opt in, tied to your sign-in email — what is collected and what is not. |
| CONTRIBUTING.md | PRs improving the framework are welcome. Your own extensions stay in your repo and don't belong upstream. |
| CODE_OF_CONDUCT.md | Contributor Covenant 2.1 — the behaviour expected in issues and pull requests here, and what happens when it isn't met. Report a problem to ai-reporting@duplocloud.net. |
| SUPPORT.md | Where to get help and what to expect: GitHub Issues, best effort, no SLA. Also what belongs somewhere else. |
See License and use above for the short version, or sales@duplocloud.net for a production license.
