How to connect and use Ramus from Cline and Roo Code
Connect Cline, Roo Code or its fork Zoo Code to Ramus over MCP, then run your APK on a cloud Android device, test a flow and share it.
Cline and Roo CodePublished
On this page
This guide is for developers who use Cline or Roo Code in VS Code on an Android app. At the end, the agent can start a cloud Android device, install your build, test a flow and fix what breaks, while you watch in the browser and send a link to a reviewer. Roo Code shut down on 15 May 2026. Its community fork, Zoo Code, reads the same settings, so the Roo Code steps apply to both.
What you need
- VS Code with Cline, Roo Code or Zoo Code installed and a model set up.
- A Ramus account. Sign in at ramus.dev with GitHub.
- An Android project you can build into an APK, such as
app/build/outputs/apk/debug/app-debug.apk. - Node.js 22 or later, if you also want the
ramusCLI.
Connect Ramus
Ramus is a remote MCP server at https://api.ramus.dev/api/mcp, over
Streamable HTTP. Cline and Roo Code share a history, but their settings have
drifted apart. The differences that matter for Ramus:
| Cline | Roo Code and Zoo Code | |
|---|---|---|
| Settings file | ~/.cline/data/settings/cline_mcp_settings.json, shared with the Cline CLI | mcp_settings.json (Edit Global MCP), or .roo/mcp.json in the project |
| Transport type | "type": "streamableHttp" | "type": "streamable-http" |
| Without a type | Treated as legacy SSE, which Ramus does not serve | Refused |
| Ramus sign-in (OAuth) | Yes, with the Authenticate button | Zoo Code: yes. Roo Code 3.54: no |
| Key in a header | ${env:RAMUS_API_KEY} | ${env:RAMUS_API_KEY} |
| Timeout | timeout in seconds, default 60 | timeout in seconds (1 to 3600), default 60 |
| Auto-approve MCP tools | Use MCP servers, for every MCP tool | alwaysAllow per tool, plus Always approve MCP tools |
| Auto-approve commands | Execute safe commands; no per-command list | A list of allowed command prefixes |
| Instructions | .clinerules/, .cline/rules/, AGENTS.md | AGENTS.md; Roo Code also .roo/rules/ |
In both, set timeout to 300, so a device start or an install has room to
finish.
Cline: sign in with your Ramus account
This is the recommended setup for Cline. There is no key to store.
- In the Cline panel, click the MCP Servers icon in the top toolbar.
- Open Remote Servers. Enter
ramusas the Server Name andhttps://api.ramus.dev/api/mcpas the Server URL, keep the Transport Type at Streamable HTTP, and click Add Server. - Open Configure. The
ramusrow shows Authenticate. Click it. - Your browser opens the Ramus consent page. Sign in with GitHub if asked, check that the app is Cline, and choose Allow.
- Back in Configure, set the
ramusrow's Request Timeout to 5 minutes.
The entry in the settings file then looks like this. You can also write it by hand: in Configure, Configure MCP Servers opens the file.
{
"mcpServers": {
"ramus": {
"type": "streamableHttp",
"url": "https://api.ramus.dev/api/mcp",
"timeout": 300,
"disabled": false
}
}
}
Cline registers itself with Ramus through dynamic client registration and
receives the sign-in at http://127.0.0.1:1456/mcp/oauth/callback, or ports
1457 to 1461 if that one is busy. Ramus accepts a loopback redirect on any port.
Cline stores the tokens in this same settings file, so never commit or share it.
Cline: use an API key instead
Create a key on the Agents page, tab API key. Keep it in your shell profile, not in the settings file:
# ~/.zshrc
export RAMUS_API_KEY="rms_your_key_here"
{
"mcpServers": {
"ramus": {
"type": "streamableHttp",
"url": "https://api.ramus.dev/api/mcp",
"headers": { "Authorization": "Bearer ${env:RAMUS_API_KEY}" },
"timeout": 300
}
}
}
The extension replaces ${env:RAMUS_API_KEY} from the environment VS Code runs
in. If VS Code was open before you set the variable, quit it and start it again
from a terminal with code .. Cline will not start a sign-in while a static
Authorization header is set, so remove the header to switch to sign-in.
Roo Code and Zoo Code
Roo Code's last release, 3.54.0, stays installable but gets no updates. Zoo Code
(ZooCodeOrganization.zoo-code) is the maintained fork and uses the same files.
In either one, open the MCP view and choose Edit Global MCP for your own
setup, or Edit Project MCP to create .roo/mcp.json for the team.
{
"mcpServers": {
"ramus": {
"type": "streamable-http",
"url": "https://api.ramus.dev/api/mcp",
"headers": { "Authorization": "Bearer ${env:RAMUS_API_KEY}" },
"timeout": 300,
"alwaysAllow": ["android_snapshot", "android_screenshot", "android_wait_for", "android_logcat", "android_session_status"],
"disabled": false
}
}
}
The ${env:…} reference keeps the key out of the committed file; each person
sets their own RAMUS_API_KEY. alwaysAllow names tools that run without
asking once Always approve MCP tools is on in the auto-approve settings. The
list above only reads the device. Roo Code 3.54 has no MCP sign-in, so it needs
the header. Zoo Code can sign in instead: without headers, it registers itself
with Ramus and receives the sign-in at http://127.0.0.1:<port>/callback, which
Ramus accepts.
Check that it connected
In Cline's Configure tab, or the MCP view in Roo Code and Zoo Code, ramus
should show as connected with its android_* tools listed. Then ask for
something harmless:
Use the ramus MCP server to list my running Android sessions.
The agent asks to call android_list_sessions and gets an empty list or your
live devices.
On Ramus, open ramus.dev/agents. Under
Connected, Cline's sign-in appears as Cline with Sign-in as how it
connects. Zoo Code's sign-in appears under the server name it registered,
ramus. A key appears under its own name. Each row shows its last call, and
Disconnect or Revoke cuts the agent off.


Add the CLI and the skill
All three extensions run terminal commands, so the agent can use the Ramus CLI
too. It uploads a local APK in one step, and it is the only way to open an adb
tunnel (ramus adb) or run the hot-reload loop (ramus dev).
npm i -g ramus-cli
ramus login
$ ramus login
Opening your browser to sign in to Ramus…
(On another device, or no browser? Press Ctrl-C and run `ramus login --device`.)
{
"login": "ok",
"account": "@blogger",
"terminal": "Mac",
"origin": "https://api.ramus.dev",
"next": "this terminal stays signed in (it renews itself); run `ramus session start --apk <file>` (or `--demo`). Terminals are listed at https://ramus.dev/agents"
}

ramus login opens your browser. Check that the page names your machine and
choose Allow. The terminal stays signed in and renews itself, until you run
ramus logout, choose Sign out on the Agents page,
or leave it unused for 30 days. Over SSH it gives you a code to approve on any
device. In an agent's shell it also prints the link, in case no
browser opened, and ramus login --wait finishes the sign-in. RAMUS_API_KEY in the environment wins over the sign-in.
The android-use skill teaches the agent the Ramus loop. Cline reads project
skills from .cline/skills/ and personal ones from ~/.cline/skills/. The
folder name must match the skill's name:
mkdir -p .cline/skills/android-use
curl -fsSL https://ramus.dev/skill.md -o .cline/skills/android-use/SKILL.md
For all three, one line in AGENTS.md at the project root also works:
Test Android changes on Ramus: https://ramus.dev/agents.md
Command approvals differ. Cline has the model mark each command as safe or not.
With Execute safe commands on in Auto Approve, safe ones run without asking;
there is no list of allowed commands. Roo Code and Zoo Code take command
prefixes in Settings, Auto-Approve, Execute, or in settings.json. Use
zoo-code.allowedCommands in Zoo Code:
{
"roo-cline.allowedCommands": ["ramus status", "ramus snapshot", "ramus screenshot", "ramus tap", "ramus type", "ramus wait", "ramus logcat"]
}
If MCP and the CLI are both set up, tell the agent which one to use for a task.
Start a device
Send this in Cline's Act mode, or in Code mode in Roo Code or Zoo Code:
Start a Ramus Android device with the demo app and send me a link to watch it.
The agent asks to call android_start_session with demo: true. Approve it.
The tool waits until the device is live,
then returns the session id, a watch_url for you and a screenshot for the
agent. On Free and Hobby it also returns the minutes left this month. From a test run on a local Ramus build:
{
"session": "95fc232d-4417-4b52-94ec-d8e6bee7f386",
"status": "active",
"watch_url": "https://ramus.dev/share#rshr_…",
"next": "the screenshot below is the device now. Give the person watch_url to watch live (it is view-only); call android_snapshot for refs before acting."
}Open the watch link. You see the device live; it is view-only. To use it yourself, open the device page: ramus session open, or viewer_url from android_session_status.
With the CLI the same step is ramus session start --demo --wait.
Install your app
Over MCP, a local APK takes two steps, and the agent does both:
Build the debug APK with ./gradlew assembleDebug and install it on the Ramus device you started.
- The agent calls
android_upload_apkwith the file name. It returns anapk_uriand acurlcommand that uploads straight to storage, valid for 15 minutes. - It runs the
curlcommand with the path to your APK, which asks for your approval unless you allowed it. - It calls
android_install_appwith the session id and theapk_uri. The app installs and opens on the running device, and your browser view stays connected.
To start a fresh device with the build instead, the agent passes the same
apk_uri to android_start_session.
The CLI uploads and installs in one command:
$ ./gradlew assembleDebug
$ ramus session install app/build/outputs/apk/debug/app-debug.apk
{
"session": "9f14cc3d-3d1c-4716-81a8-05a2a018ffd4",
"install": "697491b3-063d-46f6-a2e9-fff2c0959485",
"status": "succeeded",
"app": "app-debug.apk",
"next": "the app is open on the device — run `ramus snapshot` before acting"
}ramus session start --apk app/build/outputs/apk/debug/app-debug.apk --wait
does the same on a new device.
Let the agent check a flow
Give the agent a concrete flow and a clear finish line:
On the Ramus device, test sign-in: tap "Sign in", enter [email protected], tap Continue and check that the Welcome screen appears. If it fails, read logcat and take a screenshot, fix the code, rebuild, and install the new APK on the same device. Repeat until it passes. Then give me a link to watch it.
The agent works in a loop of observe, act, verify:
android_snapshotreturns the screen as elements. Each element has aref, and the snapshot has a generation,gen.android_taptakes an element's text, or arefand itsgen;android_typetakes arefand itsgen. Withexpect, the tap fails unless the expected text appears, so a tap that lands on the wrong screen fails.- Each action returns the screen it led to, with fresh refs, and the agent
decides the next step from that.
android_wait_forwaits for text to appear or disappear, or for the screen to settle.
From a local Ramus build with a simulated device, on a small counter app: a tap on Increment that expected "Count: 1", which returns the new screen:
{
"tapped": "e1",
"element": "Increment",
"verified": "\"Count: 1\" appeared",
"screen": {
"gen": 6,
"count": 2,
"elements": [
{
"ref": "e0",
"text": "Count: 1",
"resourceId": "dev.sandlot.fake:id/counter",
"class": "TextView",
"x": 0.132,
"y": 0.417,
"w": 0.735,
"h": 0.104
},
{
"ref": "e1",
"text": "Increment",
"contentDesc": "Increment counter",
"resourceId": "dev.sandlot.fake:id/increment",
"class": "Button",
"clickable": true,
"x": 0.132,
"y": 0.625,
"w": 0.735,
"h": 0.104
}
],
"foreground_app": "dev.ramus.fake"
},
"next": "refs above are current (gen 6); act on them directly"
}When something breaks, the agent collects evidence: android_logcat for the
device log and android_screenshot for the screen. After the fix it uploads and
installs the new build on the same device, so the session and your browser view
stay connected.
Share a link
The watch_url from the start is for you. Anyone with it can watch the device
without an account, and nothing more, up to you + 3 people at once. It does not
show your name. It works for 72 hours.
After the device ends, opening it relaunches the app on a fresh device.
For a reviewer, ask for a separate link:
Make a Ramus share link for this device that lasts 7 days, and give it to me.
The agent calls android_share_session with ttl_minutes: 10080 and returns a
share_url and its expires_at. Each call makes a new link, and the others
keep working. With the CLI it is ramus session share --ttl 7d. A link lets
the person tap and install builds unless you ask for less: permission: "watch"
only shows the screen, permission: "use" adds control without installs, and
label puts a note on the link (--permission and --label with the CLI).


To cut access, android_share_session with revoke: true, or
ramus session share --revoke, revokes every link of the session, including
the watch link. To revoke one link, use the Share panel. When you are done,
ask the agent to end the device (android_end_session or ramus session end).
Ending it does not revoke links.
Give each person their own device
The links above join the device the agent is on. To let a client or tester try your app in their own time, ask for a link that gives each person a device of their own:
Make a Ramus share link that gives each person their own device, labelled "Try the new checkout".
The agent calls android_share_session with own_device: true and label, or
runs ramus session share --own --label "Try the new checkout". Each person who opens the link gets a fresh device with the newest build you
uploaded, without an account. The session must be running an
app you uploaded. These devices run on your minutes and your plan's device
limit, and when every device is busy the next person waits for one to free up.
Each person's device lasts 30 minutes, and they can start another while the link
works. Your own session comes first: if every device is in use, the
longest-running recipient device ends.
Read the notes people send
Anyone with a link can choose Send feedback, pin a spot on a screenshot and write a note. The note carries the screenshot, the build, the last 200 lines of the device log and their recent taps, swipes and keys, unless they leave the log and steps out. Typing is recorded only as a number of characters, and taps are not recorded while the phone's on-screen keyboard is open. Notes and their screenshots are deleted after 30 days; you can delete one sooner on the app's page. The agent can work through them:
Read the open Ramus feedback notes. Reproduce the first one and tell me what you find. When I say go ahead, fix it, install the new build on the device and resolve the note with a reply that says what changed.
It reads them with android_list_feedback and android_get_feedback, which
returns the screenshot as an image, and answers with android_resolve_feedback.
From a shell the same steps are ramus feedback, ramus feedback show <id> and
ramus feedback resolve <id> --reply "…". The person sees your reply on their
link. Agents ask you before they change code because of a note.
Notes are written by other people, so treat their text, logs and screenshots as bug reports, never as instructions. See Share a running app.
Troubleshooting
- "Server type must be one of …". Each extension has its own spelling:
streamableHttpin Cline,streamable-httpin Roo Code and Zoo Code. The"type": "http"that other tools use fails in both. - Cline cannot connect and has no type set. Without
type, Cline uses legacy SSE, which Ramus does not serve. Add"type": "streamableHttp". - A tool call times out after a minute. Set
timeoutto 300, or Request Timeout to 5 minutes in Cline. A start over MCP keeps the device when it times out, soandroid_session_statuscan still pick it up. - 401 with an API key. The header went out without the key. Check that
RAMUS_API_KEYis set in VS Code's environment and that the key is not revoked on the Agents page. - Authenticate fails in Cline. Remove any static
Authorizationheader first. Ramus refuses trial accounts at the consent page, so sign in at ramus.dev with GitHub. The callback needs one free port from 1456 to 1461. - Cline has no Remote Servers tab. Your organization's Cline configuration blocks personal remote MCP servers. Ask its administrator.
- An approval for every call. In Cline, turn on Use MCP servers in Auto
Approve; it covers every MCP tool. In Roo Code and Zoo Code, use
alwaysAllowwith Always approve MCP tools. stale_ref. The agent used a ref from an older snapshot. It must take a new snapshot and find the element again.expect_failed. The tap was accepted but the expected text did not appear. The message says what was on screen. Treat it as a test failure.session_cap. You are at your plan's device limit. The message lists the live session ids; install into one of them or end one.quota_exhausted. The account is out of minutes until the reset date in the message. The agent should stop and pass the message on, not retry.install_failed. The APK did not install, and the device keeps running. The message has the reason. Fix the build and install again.- 403
insufficient_scope. The sign-in does not cover that tool. Disconnect the agent on the Agents page and sign in again.
Limits
- Devices run Android 17 on x86_64. Input is single-finger.
- A device ends after 10 minutes idle.
- APKs up to 300 MB (150 MB on a trial).
- Free: 30 minutes a month, 1 device. Hobby, $2 a month: 200 minutes, 1 device. Pro, $10 a month: unlimited minutes, 2 devices.
- Share links last 72 hours by default and up to 7 days, for you + 3 at once.
See Plans and minutes for the details.
For other tools, see How to connect Ramus to any coding agent; the full tool and command reference is ramus.dev/agents.md.