---
title: "Run goose on a remote server"
description: "The open-source goose agent on your own VM: Claude and GPT with no API keys, MCP extensions, and recipes that run on a schedule while you're away."
url: https://exe-staging.dev/deploy/goose
category: "AI agents"
updated: 2026-10-28
---

# Run goose on a remote server

An agent that keeps working, and keeps its appointments, after you log off.

- **Software:** goose (https://goose-docs.ai/)
- **Source:** https://github.com/aaif-goose/goose
- **License:** Apache-2.0
- **Time:** 5 minutes
- **Example VM name:** `my-goose` (yours will differ; on the VM, `hostname` prints it)
- **Machine-readable:** https://exe-staging.dev/deploy/goose/manifest.json

## What you get

- goose connected to Claude and GPT through exe.dev, with no API key to paste
- A project folder at `~/project` on persistent disk
- A `goose` tmux session that survives disconnects
- goose's server with its recipe scheduler, on localhost only, back after a reboot

Running on the VM:

- **goose CLI**: connected to exe.dev's LLM integration, data in `~/.config/goose`
- **goose server**: goose serve with the recipe scheduler, under systemd, port 3284, data in `~/.local/share/goose`
- **Your project**, data in `~/project`
- **tmux**: keeps your terminal session running when you disconnect

How it is reached:

- ssh my-goose.exe.xyz (private): your terminal
- ssh -L 3284:localhost:3284 my-goose.exe.xyz (private): goose Desktop on your computer, through an SSH tunnel

## Deploy with Shelley

Open https://exe-staging.dev/new?prompt=Set%20up%20goose%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe-staging.dev%2Fdeploy%2Fgoose.md%20from%20top%20to%20bottom.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-goose.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-goose.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20goose%20connected%20to%20Claude%20and%20GPT%20through%20exe.dev%2C%20with%20no%20API%20key%20to%20paste%0A-%20A%20project%20folder%20at%20%60~%2Fproject%60%20on%20persistent%20disk%0A-%20A%20%60goose%60%20tmux%20session%20that%20survives%20disconnects%0A-%20goose%27s%20server%20with%20its%20recipe%20scheduler%2C%20on%20localhost%20only%2C%20back%20after%20a%20reboot%0A%0ARun%20the%20VM-side%20setup%20in%20%22Start%20coding%22%20and%20%22Keep%20goose%20running%22.%20If%0A%60~%2F.config%2Fgoose%2Fconfig.yaml%60%20already%20exists%2C%20set%20the%20provider%20and%20model%0Ain%20it%20instead%20of%20replacing%20it.%20Create%20tmux%20detached%0A%28%60tmux%20new%20-d%20-s%20goose%20-c%20~%2Fproject%60%29%20rather%20than%20attaching%2C%20and%20reuse%0Athe%20session%20if%20it%20already%20exists.%20Do%20not%20launch%20interactive%20goose%2C%20do%20not%0Arun%20%60goose%20doctor%60%20or%20%60goose%20configure%60%2C%20and%20do%20not%20schedule%20any%20recipe.%0AVerify%20from%20~%2Fproject%20with%0A%60goose%20run%20--no-session%20-t%20%22Reply%20with%20exactly%3A%20OK%22%20%3C%2Fdev%2Fnull%60%2C%20check%0A%60tmux%20has-session%20-t%20goose%60%2C%20that%20%60systemctl%20is-enabled%20goose%60%20prints%0A%60enabled%60%2C%20and%20that%20%60curl%20-s%20http%3A%2F%2F127.0.0.1%3A3284%2Fstatus%60%20prints%20%60ok%60.%0ASkip%20the%20later%20optional%20instructions%20and%20FAQ.%20Finish%20with%20the%20SSH%20command%0Afrom%20%22Take%20a%20break%22%2C%20using%20this%20VM%27s%20name%2C%20and%20tell%20the%20owner%20to%20run%0A%60goose%20session%20-n%20main%60%20inside%20it.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open.%0A to create a VM whose agent, Shelley, follows this recipe. From a terminal:

```sh
curl -fsSL https://exe-staging.dev/deploy/goose/prompt.txt | ssh exe.dev new --prompt=/dev/stdin
```

Or follow the steps below by hand.

[goose](https://goose-docs.ai/) is an open-source AI agent, started at Block
and now part of the Linux Foundation's Agentic AI Foundation. It writes and
runs code, uses any MCP server as an extension, and runs **recipes**:
reusable tasks in YAML that it can repeat on a schedule.

On an exe.dev VM, goose gets Claude and GPT through exe.dev's
[LLM integration](/docs/integrations-llm): no API keys to paste, and model
usage billed to your exe.dev account. The VM stays on, so a conversation
carries on after you disconnect, and a recipe scheduled for 9am runs at 9am
whether or not your laptop is open.

## Start coding

On your computer, create a VM and connect. Pick any free name; if you've
already clicked Deploy or have a VM, skip the first command and use its name:

```bash
ssh exe.dev new --name=my-goose
ssh my-goose.exe.xyz
```

On the VM, install the goose CLI with its official installer. It puts
`goose` in `~/.local/bin`; `CONFIGURE=false` skips the interactive setup,
which you don't need:

```bash
curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash
goose --version
```

Point goose at exe.dev's LLM gateway. Each file in
`~/.config/goose/custom_providers` adds a provider; these two need no API
key, because the gateway at `llm.int.exe.xyz` only answers your VMs. Then
make Claude Sonnet the default:

```bash
mkdir -p ~/.config/goose/custom_providers
cat > ~/.config/goose/custom_providers/exe_claude.json <<'EOF'
{
  "name": "exe_claude",
  "engine": "anthropic",
  "display_name": "Claude via exe.dev",
  "base_url": "https://llm.int.exe.xyz",
  "requires_auth": false,
  "supports_streaming": true,
  "models": [
    { "name": "claude-sonnet-5-5" },
    { "name": "claude-opus-5-5" },
    { "name": "claude-haiku-5-5" }
  ]
}
EOF
cat > ~/.config/goose/custom_providers/exe_openai.json <<'EOF'
{
  "name": "exe_openai",
  "engine": "openai",
  "display_name": "GPT via exe.dev",
  "base_url": "https://llm.int.exe.xyz/v1/chat/completions",
  "requires_auth": false,
  "supports_streaming": true,
  "models": [
    { "name": "gpt-6.1-sol" },
    { "name": "gpt-6-luna" }
  ]
}
EOF
cat > ~/.config/goose/config.yaml <<'EOF'
active_provider: exe_claude
providers:
  exe_claude:
    enabled: true
    model: claude-sonnet-5-5
    configured: true
EOF
```

Make a project folder and check that goose can reach the model. It should
print `OK`:

```bash
mkdir -p ~/project && cd ~/project
goose run --no-session -t "Reply with exactly: OK"
```

Open a tmux session and start a named goose session inside it:

```bash
tmux new -A -s goose -c ~/project
goose session -n main
```

Give it a small task. For example:

> Build a tiny website for a bakery that only sells one kind of bread.

goose runs commands and edits files without asking first; that's its
default `auto` mode. Type `/mode approve` to have it ask before each
change, or `/mode chat` to talk without tools.

## Take a break

Press **Ctrl-b**, then **d** to detach. goose keeps working on the VM when
you disconnect. On your computer, use this command to hop back in:

```bash
ssh -t my-goose.exe.xyz 'tmux new -A -s goose -c ~/project'
```

A VM restart ends the running session but not the conversation, which goose
keeps in `~/.local/share/goose/sessions`. Reconnect and pick it up where
you left off:

```bash
goose session --resume -n main
```

`goose session list` shows every conversation, including the ones recipes
started.

## Keep goose running

`goose serve` is goose's server: the same agent, for apps such as goose
Desktop, with a scheduler that runs recipes on time. On the VM, give it a
secret, which apps send to connect, and start it whenever the VM boots. It
listens on localhost only, so nothing outside the VM can reach it:

```bash
(umask 077; printf 'GOOSE_SERVER__SECRET_KEY=%s\n' "$(openssl rand -hex 32)" > ~/.config/goose/serve.env)
sudo tee /etc/systemd/system/goose.service >/dev/null <<'EOF'
[Unit]
Description=goose server and recipe scheduler
After=network-online.target
Wants=network-online.target

[Service]
User=exedev
WorkingDirectory=/home/exedev/project
EnvironmentFile=/home/exedev/.config/goose/serve.env
ExecStart=/home/exedev/.local/bin/goose serve --platform desktop --enable-scheduler --host 127.0.0.1 --port 3284
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now goose
```

Check it. This prints `ok`:

```bash
curl -s http://127.0.0.1:3284/status
```

## Run recipes on a schedule

A recipe is a task in a YAML file: instructions, a prompt, and parameters
you fill in when you run it. This one summarizes the last day of commits
in `~/project` and emails the summary to you with exe.dev's
[email API](/docs/send-email), which can only write to you. On the VM:

```bash
mkdir -p ~/recipes
cat > ~/recipes/daily-digest.yaml <<'EOF'
version: 1.0.0
title: Daily digest
description: Summarize the last day of commits in ~/project and email the summary to you
parameters:
  - key: email
    input_type: string
    requirement: required
    description: Your exe.dev email address
instructions: |
  You run unattended on an exe.dev VM. Nobody is watching, so never ask
  questions; make a reasonable choice and say what you chose.
prompt: |
  1. In ~/project, run `git log --since="24 hours ago" --stat`.
  2. Write a short plain-text summary of what changed and anything that
     looks unfinished. If nothing changed, say so in one line.
  3. Email the summary to {{ email }} with the subject "Daily digest", by
     sending JSON with `to`, `subject` and `body` fields to
     http://169.254.169.254/gateway/email/send with curl
     (`-H "Content-Type: application/json"`). Build the JSON with jq so the
     text is escaped properly.
  4. Reply with the HTTP status of that request.
EOF
goose recipe validate ~/recipes/daily-digest.yaml
```

Run it once now, with your exe.dev email address, and check your inbox:

```bash
goose run --recipe ~/recipes/daily-digest.yaml --params email=you@example.com
```

Then schedule it for 9:00 every day. The VM's clock is UTC, so adjust the
hour to your time zone. Stop the server while you change schedules: it
keeps its own copy of the list and writes it back after each run, which
would undo a change made while it runs.

```bash
sudo systemctl stop goose
goose schedule add --schedule-id daily-digest --cron "0 9 * * *" \
  --recipe-source ~/recipes/daily-digest.yaml --params email=you@example.com
sudo systemctl start goose
```

`goose schedule list` shows each schedule and when it last ran, and
`goose schedule sessions --schedule-id daily-digest` lists its runs. Open
one with `goose session --resume --session-id <id> --history` to read what
goose did. To drop a schedule, stop the server again and run
`goose schedule remove --schedule-id daily-digest`.

Each run is a full agent session billed like any other, so keep schedules
to what you'd read. goose's [recipe guide](https://goose-docs.ai/docs/guides/recipes/session-recipes/)
covers sub-recipes, retries, and structured output.

## Add extensions

goose's tools come from extensions, which are MCP servers. It starts with
its built-in ones, such as `developer` for the shell and files. To add a
remote MCP server for good, add it under `extensions:` in
`~/.config/goose/config.yaml`. For example, DeepWiki, which answers
questions about public GitHub repositories and needs no sign-in:

```yaml
extensions:
  deepwiki:
    type: streamable_http
    name: deepwiki
    enabled: true
    uri: https://mcp.deepwiki.com/mcp
    timeout: 300
```

The built-in extensions stay on. For a single session, pass the server on
the command line instead. Python servers run with `uvx`, which the VM
already has:

```bash
goose session --with-streamable-http-extension https://mcp.deepwiki.com/mcp
goose session --with-extension "fetch:uvx mcp-server-fetch"
```

Servers that start with `npx` need Node.js, which a new VM doesn't have.
`goose configure` → **Add Extension** walks through the same settings, and
goose's [extensions directory](https://goose-docs.ai/extensions/) lists
more. Restart the server (`sudo systemctl restart goose`) so scheduled
recipes see new extensions.

## Use goose Desktop with the VM

goose Desktop can drive the server on the VM instead of one on your
computer, so its chats and schedules run on the VM. The server listens
only on the VM's localhost, so reach it through SSH. On your computer,
print the secret, then open a tunnel and leave it running:

```bash
ssh my-goose.exe.xyz cat .config/goose/serve.env
ssh -N -L 3284:localhost:3284 my-goose.exe.xyz
```

In goose Desktop, open **Settings → goose Server**, turn on
**Use external server**, and enter `http://localhost:3284` as the URL and
the value after `GOOSE_SERVER__SECRET_KEY=` as the secret key. goose's
[remote server guide](https://goose-docs.ai/docs/guides/remote-goose-server/)
describes these settings.

> [!WARNING]
> Whoever has the secret and can reach port 3284 can run any command on
> the VM. Keep the server on `127.0.0.1` and use the tunnel rather than
> exposing the port.

## Make yourself at home

- **Pick a model:** in a session, type
  `/model --provider exe_openai gpt-6.1-sol` for GPT, or
  `/model --provider exe_claude claude-opus-5-5` for Claude Opus. Change
  `active_provider` and `model` in `~/.config/goose/config.yaml` to set the
  default.
  To add another model, add it to the provider's file in
  `~/.config/goose/custom_providers`; exe.dev keeps a
  [list of available models and prices](/llm-gateway-models).
- **Bring your code:** [connect a GitHub repo](/docs/integrations-github),
  clone it onto the VM, and run goose from its directory. Use that folder
  instead of `~/project` in the commands above. `goose review` reviews
  your uncommitted changes, or a range such as `main...HEAD`.
- **Peek at your app:** ask goose to serve it on `0.0.0.0:8000`, then
  open `https://my-goose.exe.xyz/`. It's private by default.
  [More about previews](/docs/proxy).
- **Give it more VMs:** add [exe.dev's MCP server](/deploy/exe-mcp) as an
  extension and goose can create VMs of its own, to try something risky
  on a copy or to host what it builds. Recipes run unattended, so use a
  token limited to one tag, as
  [that page shows](/deploy/exe-mcp#limit-what-the-agent-can-touch), in
  the extension's `headers`.
- **Script it:** `goose run -t "Summarize the TODOs in this repo"` runs
  one task without the interactive screen; add `--output-format json` for
  output a program can read.

For everything else, see [the goose docs](https://goose-docs.ai/docs/quickstart/).

## Frequently asked questions

### Can I use my own API key or subscription instead?

Yes. Run `goose configure` on the VM, choose **Configure Providers**, and pick a provider such as Anthropic, OpenAI, OpenRouter, or ChatGPT Codex; see goose's [provider docs](https://goose-docs.ai/docs/getting-started/providers/). On a VM there is no system keyring, so goose keeps keys in `~/.config/goose/secrets.yaml`. To keep keys off the VM entirely, put them in your [LLM integration](/docs/integrations-llm) instead and keep the `exe_*` providers from this page.

### How do I update goose?

On the VM, run `goose update`, then `sudo systemctl restart goose` so the server and its scheduler use the new version. Your settings, sessions, and schedules stay put.

### Something's not working. Where do I look?

`goose info -v` shows which config files, provider, and extensions goose is using. goose's own logs are in `~/.local/state/goose/logs`, and `journalctl -u goose` shows the server. `goose doctor` starts a short session in which goose checks its own setup and explains what it finds. If a schedule you added has vanished, see [Run recipes on a schedule](#run-recipes-on-a-schedule).

### Can I talk to goose from my phone?

goose has an experimental [Telegram gateway](https://goose-docs.ai/docs/experimental/remote-access/telegram-gateway/) (`goose gateway start telegram`) that needs the computer running goose to stay awake, which a VM does. It takes a bot token from [@BotFather](https://t.me/BotFather) on the command line, so the token lives on the VM. We haven't tested it on exe.dev.

### How do I back up my work?

Commit and push your code. `goose session export -n main --format json -o main.json` saves one conversation. For a copy of the whole VM, including sessions, recipes, and schedules, run `ssh exe.dev cp my-goose my-goose-backup` on your computer (choose a free backup name), and connect to the copy with `ssh my-goose-backup.exe.xyz`. Reattach any [VM-specific integrations](/docs/integrations-attach).


## Related

- [Give any agent a sandbox over MCP](https://exe-staging.dev/deploy/exe-mcp.md): One URL gives your agent real VMs to run code on, host apps from, and hand work to.
- [Run OpenCode on a remote server](https://exe-staging.dev/deploy/opencode.md): Every model, one VM, and an agent that works while your laptop sleeps.
- [Run Codex on a remote server](https://exe-staging.dev/deploy/codex.md): A computer for Codex. An early night for your laptop.
- [Run Claude Code on a remote server](https://exe-staging.dev/deploy/claude-code.md): A computer for Claude. A breather for your laptop.
- [Host OpenClaw](https://exe-staging.dev/deploy/openclaw.md): An AI sidekick with its own computer. Your laptop can take a nap.
- [Run the Pi coding agent on a remote server](https://exe-staging.dev/deploy/pi.md): An agent that doesn't ask first, on a computer that can take it.
