Get started with vibing
Alpha, admin-only. Vibe coding is a preview feature. The runtime is still
changing and access is currently limited to administrators. This guide is public
so anyone can read how it works, but the create, start, terminal, and ingress
actions described below only succeed for an administrator account.
Vibing is building software by talking to an AI agent instead of typing every
line yourself. On DevPlace you get a real Linux container in the cloud, a coding
agent that works like Claude Code, and a one-line way to put the result online.
You describe what you want, the agent writes and runs the code, and you ship it
under your own slug.
You can do every step from the admin Containers screens, but the friendliest
path is to simply ask Devii, the built-in assistant. This guide focuses on the
Devii way: each instruction below is plain English you can type into Devii, and the
note next to it names the tool Devii runs for you.
What you get
- A project to hold your files (the persistent storage for your work).
- A container built from the shared
ppyimage, with your project files
mounted at/appand a broad toolchain preinstalled. - Three AI agents baked into every container, all running on your own API key:
- DevPlace Code (
dpc) - a coding agent in the same class as Claude Code. botje.py- a plug-and-play DevPlace bot you can copy and customise.pagent- a minimal, zero-dependency agent for small scripted tasks.
- DevPlace Code (
- Ingress: publish a port from your container to a public URL at
/p/<slug>.
All AI usage from inside the container is metered to the account whose API key the
container carries, so your spend rolls up under your own profile, exactly like
direct API calls.
The four steps, the Devii way
Open Devii from the user menu (the Devii item) and type these in order. Devii
asks for confirmation on anything destructive, so you stay in control.
1. Create a project (storage).
"Create a project called Vibe Lab with the description: my first vibe-coded app."
Devii calls create_project. The project is the home for every file your container
produces.
2. Attach a container to it.
"In Vibe Lab, create a container named lab that maps port 8000."
Devii calls container_create_instance. The instance runs the shared ppy image
with your project mounted at /app. A bare port like 8000 auto-assigns a unique
host port; use host:container only if you must pin one.
3. Start the container.
"Start the lab container in Vibe Lab."
Devii calls container_instance_action with action=start. (If you set
autostart when creating it, it is already running and you can skip this.)
4. Open a terminal.
"Open a terminal in the lab container."
Devii calls the open_terminal action, which opens a floating xterm.js window in
your browser attached to the container's interactive shell. From here you run
dpc, botje.py, or anything else.
You can also do everything without the terminal: ask Devii to run one-shot commands
with container_exec ("run pip list in the lab container"), read output with
container_logs, check resource use with container_stats, and import the
container's files back into the project with container_instance_action
action=sync.
Inside the container
- The OS user is always
pravda(uid 1000). This is deliberate:/appis
bind-mounted from the host, so writing as uid 1000 keeps file ownership correct. - Your working directory is
/app, which is your project's files. Anything you
create there can be synced back into the project. aptandsudowork without real root.apt install <package>installs
system packages through a fakeroot wrapper, andsudoruns the command as
pravdarather than switching to root. You cannot bind a port below 1024 (use a
high port plus ingress instead), but otherwise the environment behaves like a
normal box you own.- Preinstalled tooling includes
git,curl,wget,vim,tmux,htop,nc,
zip, the Apache benchmark toolab, Playwright with Chromium, and a wide
Python stack (Flask, Django, FastAPI, uvicorn, pandas, numpy, requests, httpx,
beautifulsoup4, sqlalchemy, pytest, ruff, black, and more).
DevPlace Code (dpc)
dpc is DevPlace Code, a terminal coding agent that provides the same kind of
experience as Claude Code: you give it a task, it reads and writes files, runs
commands, fixes what it broke, and iterates until the job is done. It is installed
at /usr/bin/dpc and ready to use the moment your container starts.
dpc "build a small FastAPI app in app.py that serves a JSON health check at /"
dpc reads your API key from the container environment (PRAVDA_API_KEY) and talks
to the platform AI gateway, so all of its AI usage is metered through your own
account. There is no separate key to manage and nothing to configure: it is plug
and play.
Container environment keys
Every container is launched with these variables already set. Scripts and agents
inside the container read them to reach the platform and to attribute AI spend.
| Variable | What it contains |
|---|---|
PRAVDA_BASE_URL |
The public base URL of this DevPlace instance. |
PRAVDA_OPENAI_URL |
The AI gateway endpoint, PRAVDA_BASE_URL + /openai/v1. |
PRAVDA_API_KEY |
The API key used for every AI call. Spend is metered to this account. |
PRAVDA_USER_UID |
The DevPlace user id whose identity the container carries. |
PRAVDA_CONTAINER_NAME |
The instance's name. |
PRAVDA_CONTAINER_UID |
The instance's unique id. |
PRAVDA_INGRESS_URL |
The public URL of this container when ingress is set, otherwise empty. |
The key that lands in PRAVDA_API_KEY is resolved in order from the instance's
run-as user, then its creator, then the project owner. You can point a container
at a specific account by asking Devii to set run_as_uid when creating or
configuring it. The OS user stays pravda; only the identity and key change.
botje.py - the plug-and-play bot
botje.py (installed at /usr/bin/botje.py) is a complete, ready-to-run DevPlace
bot. Start it with no arguments and it logs in with your PRAVDA_API_KEY, then
polls DevPlace for @mentions and direct messages and answers each one with a full
agent toolset. Give it a task on the command line and it runs that single task and
exits.
python /usr/bin/botje.py # run as a DevPlace bot (polling loop)
python /usr/bin/botje.py "summarise the latest news" # run one task and exit
What it can do. Behind both modes is a complete agent: read, write, edit, and
patch files; search with grep, glob, and symbol lookup; search the web and do deep
research; fetch and download URLs; describe images; run shell commands; and plan,
reflect, verify, and delegate to sub-agents for larger jobs.
How it is configured. Everything comes from the environment, so it is plug and
play inside a container:
| Variable | Effect |
|---|---|
PRAVDA_API_KEY |
Auth for both DevPlace and the AI gateway (already set). |
PRAVDA_BASE_URL |
Which DevPlace instance to talk to (already set). |
BOT_USERNAME |
The bot's own username, so it ignores its own posts. |
MENTION_POLL_SECONDS |
How often it checks for mentions (default 30). |
DM_POLL_SECONDS |
How often it checks for direct messages (default 10). |
DEVPLACE_MAX_ITERATIONS |
Upper bound on agent steps per task. |
Make it your own. botje.py is the reference bot, and it is meant to be
forked. Copy it into your project and vibe the changes with dpc:
cp /usr/bin/botje.py /app/mybot.py
dpc "in mybot.py, make the bot also reply 'pong' whenever a message contains the word ping"
python /app/mybot.py
Because the copy lives in /app, a sync saves it into your project so it
persists. You can run it as the container's boot command (ask Devii to set
boot_command to python /app/mybot.py) and add a restart_policy so it stays up.
Ingress: host your app at /p/
Ingress publishes one container port to a public URL on the platform. Once set, your
app is reachable at /p/<slug> over both HTTP and WebSocket. The target host and
port are derived from the instance, never from user input, so there is no way to
point ingress at something you do not own.
Two values control it:
ingress_slug- the public name. Lowercase letters, digits, and hyphens,
up to 63 characters, and unique across the whole platform.ingress_port- the container port to publish. It must be one of the ports
you mapped on the instance. If the instance maps exactly one port you can omit
this and it is chosen for you.
Set it through Devii at create time:
"Create a container named web in Vibe Lab, map port 8000, and expose it publicly
as vibe-lab on port 8000."
or on an existing instance by recreating it with the ingress fields, or by asking
Devii to configure the ports and ingress. The resulting URL is
PRAVDA_BASE_URL + /p/vibe-lab, which is also placed in the container's
PRAVDA_INGRESS_URL so your app can self-reference its own public address.
Tutorial: vibe a web app and put it online
This is the full loop, start to finish, entirely through Devii and dpc.
1. Create the project and an exposed container. In Devii:
"Create a project called Quote Wall. Then create a container named web in it, map
port 8000, expose it publicly as quote-wall on port 8000, and start it."
Devii runs create_project, then container_create_instance with
ports=8000, ingress_slug=quote-wall, ingress_port=8000, autostart=true.
2. Open a terminal.
"Open a terminal in the web container."
3. Vibe the app with dpc. In the terminal:
dpc "create app.py: a Flask app that serves an HTML page listing inspirational
quotes, with a form to add a new quote stored in quotes.json. Bind to
0.0.0.0 port 8000. Then run it."
dpc writes app.py and quotes.json, installs anything it needs, and starts the
server on port 8000 inside the container.
4. Visit your live app. Open PRAVDA_BASE_URL + /p/quote-wall in your browser.
The platform proxies the request straight to port 8000 in your container. Add a
quote in the form and watch it persist.
5. Keep it running and save the work. Back in Devii:
"Set the web container's boot command to
python /app/app.py, set its restart
policy to unless-stopped, then sync it."
Devii configures the boot command and policy with container_configure_instance,
and sync (via container_instance_action) imports app.py and quotes.json back
into the Quote Wall project so they are saved. Your app now restarts on its own and
its source lives in your project.
That is the whole vibe loop: describe, run, expose, save. From here you iterate by
asking dpc for the next feature and refreshing /p/quote-wall.
Tutorial: vibe a custom bot by changing botje
botje.py is the reference bot, and it is built to be changed. In this tutorial you
turn the stock bot into a personal helpdesk bot that recognises its own commands,
adds a brand-new agent tool, and remembers state between restarts - all by chaining
small dpc edits. You never edit the file by hand; you describe each change and let
dpc make it.
The pattern is the same every time:
- Copy
botje.pyonce into your project. - Ask
dpcfor one focused change. - Run the bot and try it from another account.
- Ask
dpcfor the next change. - When it behaves, set it as the boot command and
syncto save it.
1. Start from a copy. In a project's running container (the Vibe Lab or Quote
Wall from the steps above both work), open a terminal and copy the bot into /app
so it persists with the project:
cp /usr/bin/botje.py /app/helpdesk.py
2. Add a custom command. A command is just a phrase the bot recognises in a
mention or DM. Ask dpc to add one:
dpc "in /app/helpdesk.py, add a custom command: when a direct message starts with
'!help', reply with a short list of the commands this bot supports. Keep the
existing mention and DM behavior intact."
dpc reads the file, finds where incoming messages are handled, and inserts the
command without disturbing the rest. Run it and test from a second account:
python /app/helpdesk.py
DM the bot !help from another user and you should get the command list back.
3. Give it a brand-new tool (the special functionality). The bot answers with an
agent that has a fixed toolset. You extend that toolset the same way the built-in
tools are defined: a function decorated with @tool. Describe the tool you want and
let dpc wire it in:
dpc "in /app/helpdesk.py, add a new @tool called open_ticket(summary, priority) that
appends a ticket as one JSON line to /app/tickets.jsonl with an id, the summary,
the priority, and the current ISO timestamp, and returns the new ticket id.
Register it so the agent can call it, then teach the bot: when a DM starts with
'!ticket ', open a ticket from the rest of the message and reply with the id."
Now the bot can file tickets on request, and because the agent sees the tool in its
list it can also decide to open one on its own when a conversation clearly describes
a problem. Restart and test:
python /app/helpdesk.py
DM !ticket the login page is slow and confirm a line lands in
/app/tickets.jsonl.
4. Add memory so it survives restarts. State lives in plain files under /app,
which is exactly what persists and syncs:
dpc "in /app/helpdesk.py, add a !tickets command that reads /app/tickets.jsonl and
replies with the count of open tickets and the three most recent summaries.
Make the file read tolerant of it not existing yet."
5. Refine the voice. Chaining keeps working as long as you ask for one change at
a time:
dpc "in /app/helpdesk.py, make every reply start with 'Helpdesk:' and stay under two
sentences unless the user asked for a list."
6. Run it on boot and save it. Once the bot behaves, hand it to the container
service. In Devii:
"Set this container's boot command to
python /app/helpdesk.py, set its restart
policy to unless-stopped, then sync it."
Devii configures the boot command and policy with container_configure_instance, and
sync imports helpdesk.py and tickets.jsonl back into the project so the whole
bot is saved. It now starts on its own, restarts if it stops, and answers on your own
API key.
Where to take it next. Because the bot already has file, web-search, deep-research,
fetch, vision, and shell tools, a single dpc prompt can teach it almost any new
behavior: summarise a URL someone sends, run a quick check and report the result,
post a daily digest, or escalate a ticket by mentioning an admin. Add one tool or one
command per prompt, test, and sync. That is how you vibe a bot with genuinely
special functionality without writing it from scratch.
Limits and safety
- The feature is in Alpha and admin-only. Behaviour and limits may change.
- Devii confirms before anything destructive: deleting an instance and
destructive shell commands (rm,dd,truncate, dropping a database, and the
like) are refused until you explicitly confirm. - You cannot bind ports below 1024 inside the container. Use a high port and
ingress to serve on the public web. - AI usage from
dpc,botje.py, andpagentis metered to the API key the
container carries. Keep an eye on your usage on your profile.
Read next
- Devii Assistant - everything the assistant can do for you.
- DeepSearch and SEO Diagnostics -
the other tools you can drive conversationally.