Stata 19 MP with Zed Editor

Run Stata 19 MP from Zed editor on Linux using task automation — an alternative to the VS Code workflow.

Intermediate Verified Working Updated 13 min read Tested on Zorin OS 18.1 Pro (Ubuntu 24.04 Noble base) Hardware Lenovo ThinkPad L14 Gen 2

Run Do-Files and Selections from Zed — No Extensions Required


What This Guide Achieves

FeatureStatus
Ctrl+Enter in Zed runs the whole .do file in Stata GUIYes
Shift+Enter in Zed runs selected line(s) or chunk in Stata GUIYes
Comments, globals, backticks, block comments all work in selectionYes
Stata launches automatically if not already openYes
No Zed extension requiredYes
Keybindings scoped to .do files only (won’t interfere elsewhere)Yes
File is auto-saved before running whole fileYes
Terminal panel stays hidden (no visual noise)Yes

What This Guide Does NOT Cover

Installation of Stata, desktop integration, file icons, or the Wayland resize fix. Those are all in the VS Code complete guide — Parts 1 through 4 apply identically to Zed.


Prerequisites

Before starting this guide, you must have:

RequirementHow to verify
Stata 19 MP installedls /usr/local/stata19/xstata-mp
Xorg session (not Wayland)echo $XDG_SESSION_TYPE → must print x11
wmctrl, xdotool, xclip installedwhich wmctrl xdotool xclip
Zed editor installedzed --version
stata_run_do.sh from VS Code guidewhich stata_run_do.sh
~/.local/bin on PATHecho $PATH should include /home/mohsin/.local/bin

If any of these are missing, complete Parts 1–5 of the VS Code complete guide first. The whole-file runner script (stata_run_do.sh) is shared between both editors.


Architecture: How It Works

VS Code approach (for comparison)

VS Code cannot safely pass selected text to a shell script because ${selectedText} is shell-interpolated. The workaround requires:

  1. The multi-command extension to chain two VS Code actions
  2. Action 1: Copy selection to clipboard internally
  3. Action 2: Run a task that reads the clipboard via xclip

Zed approach (simpler)

Zed sets $ZED_SELECTED_TEXT as a real environment variable before running the task. The script reads this variable — bash never shell-interprets its contents. This means:

  • No extension required — Zed handles it natively
  • No clipboard manipulation for selection — the text goes directly from Zed to the script via the environment
  • Backticks (`c(os)'), dollar signs ($main), block comments (/* ... */) — all survive intact

The whole-file workflow is identical to VS Code: the script copies do "/path/to/file.do" to the clipboard, focuses Stata, pastes, and presses Enter.


Part 1 — Create the Selection Runner Script (Zed-Specific)

This script is different from the VS Code version because it reads from $ZED_SELECTED_TEXT instead of the clipboard.

mkdir -p ~/.local/bin
nano ~/.local/bin/stata_run_selection_zed.sh

Paste:

#!/usr/bin/env bash
set -euo pipefail

# ---------------------------------------------------------------
# stata_run_selection_zed.sh
# Run selected Stata code from Zed editor in Stata GUI
#
# Reads the selection from Zed's $ZED_SELECTED_TEXT env var,
# writes it to a temp .do file, and sends it to Stata.
#
# Safe for: backticks, globals, block comments, macros — all
# Stata syntax survives because the env var is never shell-parsed.
# ---------------------------------------------------------------

STATA_BIN="/usr/local/stata19/xstata-mp"
STATA_WMCLASS="Xstata-mp"
EDITOR_WMCLASS="zed"

TMPDO="/tmp/stata_selection_run.do"

# Read selected text from Zed's environment variable
if [[ -z "${ZED_SELECTED_TEXT:-}" ]]; then
  echo "No text selected in Zed — nothing to run." >&2
  exit 1
fi

# Write selection to temp do-file (printf %s does NOT interpret
# backticks, $, or escape sequences in the variable value)
printf '%s\n' "$ZED_SELECTED_TEXT" > "$TMPDO"

# Verify file is non-empty
if [[ ! -s "$TMPDO" ]]; then
  echo "Temp do-file is empty after write — aborting." >&2
  exit 1
fi

# Launch Stata GUI if not already running
if ! wmctrl -x -l | grep -qi "${STATA_WMCLASS}"; then
  "${STATA_BIN}" >/dev/null 2>&1 &
  for i in {1..50}; do
    wmctrl -x -l | grep -qi "${STATA_WMCLASS}" && break
    sleep 0.2
  done
  # Wait for Stata to fully initialize before sending input
  sleep 4
fi

# Put the do command (not the raw code) on the clipboard
printf 'do "%s"\n' "$TMPDO" | xclip -selection clipboard

# Focus Stata and run
wmctrl -xa "${STATA_WMCLASS}"
sleep 0.3
xdotool key --clearmodifiers ctrl+v Return

# Return focus to Zed (uncomment below to enable)
# sleep 0.5
# wmctrl -xa "${EDITOR_WMCLASS}"

Make executable:

chmod +x ~/.local/bin/stata_run_selection_zed.sh

Verify:

which stata_run_selection_zed.sh
# Should print: /home/mohsin/.local/bin/stata_run_selection_zed.sh

Why printf '%s\n' "$ZED_SELECTED_TEXT" is safe

When bash expands "$ZED_SELECTED_TEXT", it performs a single-pass parameter expansion. The resulting string is treated as literal text — bash does not re-interpret backticks, dollar signs, or any other special characters inside the value. Combined with printf '%s' (which does not process escape sequences in its arguments), this guarantees that every byte of your Stata code reaches the temp file exactly as written.


Part 2 — Create Global Zed Tasks

Zed tasks can be project-local (.zed/tasks.json) or global (~/.config/zed/tasks.json). Global is better here — you want Stata integration in every project.

nano ~/.config/zed/tasks.json

Paste:

[
  {
    "label": "Run do-file in Stata GUI",
    "command": "/home/mohsin/.local/bin/stata_run_do.sh",
    "args": ["$ZED_FILE"],
    "reveal": "never",
    "hide": "never",
    "use_new_terminal": false,
    "allow_concurrent_runs": false,
    "save": "current",
    "show_summary": false,
    "show_command": false
  },
  {
    "label": "Run selection in Stata GUI",
    "command": "/home/mohsin/.local/bin/stata_run_selection_zed.sh",
    "reveal": "never",
    "hide": "never",
    "use_new_terminal": false,
    "allow_concurrent_runs": false,
    "save": "none",
    "show_summary": false,
    "show_command": false
  }
]

What each setting does

SettingValuePurpose
commandFull script pathNo ~ — Zed tasks run in a login shell but full paths are safer
args["$ZED_FILE"]Passes the current file’s absolute path as argument 1
reveal"never"Do not show Zed’s terminal panel (output goes to Stata GUI)
save"current" / "none"Auto-save current file before whole-file run; skip for selection
show_summaryfalseSuppress task summary line in terminal output
show_commandfalseSuppress command echo in terminal output
allow_concurrent_runsfalseWait for previous Stata run to finish before starting another

Note: The “Run selection in Stata GUI” task uses $ZED_SELECTED_TEXT implicitly — Zed sets it as an environment variable that the script reads. It does not appear in args because passing it as an argument would expose it to shell interpretation.


Part 3 — Set Keybindings

nano ~/.config/zed/keymap.json

Paste:

[
  {
    "context": "Editor && extension == do",
    "bindings": {
      "ctrl-enter": ["task::Spawn", { "task_name": "Run do-file in Stata GUI" }],
      "shift-enter": ["task::Spawn", { "task_name": "Run selection in Stata GUI" }]
    }
  }
]

What the context does

"context": "Editor && extension == do" means these keybindings are only active when editing a .do file. In all other file types — .tex, .md, .py — Ctrl+Enter and Shift+Enter retain their default Zed behaviour. This scoping is more precise than the VS Code setup, where the keybindings were global.


Daily Usage

StepAction
1Log in → gear icon → your X11/Xorg session (labeled “Zorin OS on Xorg” on Zorin OS, “Ubuntu on Xorg” on standard Ubuntu — look for “Xorg” in the name)
2Open Stata GUI once at the start of your session
3Open your .do file in Zed
4Ctrl+Enter — runs the entire file in Stata GUI
5Select any lines → Shift+Enter — runs selection in Stata GUI

Tip: For a single line, use Ctrl+L to select the entire line first, then Shift+Enter.

Tip: Leave Stata open for your entire session. The first run after boot may take ~4 seconds while Stata initializes. Every subsequent run is near-instant.


How It Works End to End

Ctrl+Enter (Run Whole File)

Ctrl+Enter pressed in .do file
  └─→ Zed auto-saves the file (save: "current")
  └─→ Zed spawns task: "Run do-file in Stata GUI"
        └─→ stata_run_do.sh "$ZED_FILE" runs
              ├─→ Puts  do "/path/to/file.do"  on clipboard
              ├─→ Launches Stata if not running (waits ~4s)
              ├─→ Focuses Stata window via wmctrl
              ├─→ Pastes + Enter via xdotool
              └─→ Stata executes the do-file

Shift+Enter (Run Selection)

Shift+Enter pressed with text selected in .do file
  └─→ Zed spawns task: "Run selection in Stata GUI"
        └─→ stata_run_selection_zed.sh runs
              ├─→ Reads $ZED_SELECTED_TEXT (environment variable)
              │   No clipboard involved — no shell interpretation
              ├─→ Writes raw bytes to /tmp/stata_selection_run.do
              │     Comments      Supported
              │     Globals ($)   Supported
              │     Backticks     Supported
              │     Block comments Supported
              │     Macros        Supported
              ├─→ Puts  do "/tmp/stata_selection_run.do"  on clipboard
              ├─→ Launches Stata if not running
              ├─→ Focuses Stata window
              ├─→ Pastes + Enter
              └─→ Stata runs the temp do-file

Running from Terminal or AI Agent

The same stata_run_do.sh script works in all contexts:

# From terminal
stata_run_do.sh /mmh/Dropbox/Projects/rwh_wp/5_do/Clean/00_run.do

# From AI agent (always use full path — no ~)
/home/mohsin/.local/bin/stata_run_do.sh /mmh/Dropbox/Projects/rwh_wp/5_do/Clean/00_run.do

Keybinding Reference

KeybindingContextAction
Ctrl+Enter.do files onlyRun the entire file in Stata GUI
Shift+Enter.do files onlyRun the selected text in Stata GUI
Ctrl+LAny editorSelect current line (use before Shift+Enter for a single line)
Ctrl+Shift+PAnywhereCommand palette (search “task” to see/run tasks manually)

File Locations Reference

FilePath
Stata binary/usr/local/stata19/xstata-mp
Whole-file runner (shared with VS Code)~/.local/bin/stata_run_do.sh
Selection runner (Zed-specific)~/.local/bin/stata_run_selection_zed.sh
Selection temp do-file/tmp/stata_selection_run.do
Zed global tasks~/.config/zed/tasks.json
Zed keybindings~/.config/zed/keymap.json
Zed settings~/.config/zed/settings.json

Differences from VS Code Guide

AspectVS CodeZed
Extension requiredYesryuta46.multi-commandNo — native task variables
How selection reaches the scriptClipboard (copy action → xclip reads)Environment variable ($ZED_SELECTED_TEXT)
Keybinding scopeGlobal (all file types)Scoped to .do files via extension == do
Config files.vscode/tasks.json + keybindings.json + settings.jsontasks.json + keymap.json (both in ~/.config/zed/)
Task output visibilityTerminal panel (can configure reveal)Hidden by default ("reveal": "never")
Auto-save before runNot built inBuilt in ("save": "current")
Selection runner scriptstata_run_selection.sh (reads clipboard)stata_run_selection_zed.sh (reads env var)
Whole-file runner scriptstata_run_do.shSame stata_run_do.sh (shared)

Troubleshooting

ProblemCauseFix
Ctrl+Enter does nothingKeybinding not loadedRestart Zed: Ctrl+Shift+P → “zed: reload”
Ctrl+Enter works in .py but not .doContext mismatchCheck keymap.json has extension == do
Shift+Enter says “No text selected”Nothing highlightedSelect text first (Ctrl+L for a line)
Shift+Enter does nothing at allTask not foundCheck tasks.json label matches exactly: "Run selection in Stata GUI"
Stata flashes open then closesNot enough init timeIncrease sleep 4 to sleep 6 in both scripts
Terminal panel keeps appearingreveal setting wrongSet "reveal": "never" in tasks.json
Script not foundNot on PATHVerify: which stata_run_selection_zed.sh
wmctrl/xdotool fail silentlyWayland sessionLog out → gear → your X11/Xorg session (look for “Xorg” in the session name — “Zorin OS on Xorg” on Zorin, “Ubuntu on Xorg” on Ubuntu)
Focus does not return to ZedReturn lines commentedUncomment last 2 lines in the script
Old task keeps rerunningZed caches last task for task::RerunUse task::Spawn (not Rerun) via the keybinding

FAQ

Q: Can I use both VS Code and Zed with Stata? A: Yes. They share the same stata_run_do.sh for whole-file runs. The selection scripts are separate (stata_run_selection.sh for VS Code, stata_run_selection_zed.sh for Zed) and do not interfere with each other.


Q: Why a separate script instead of reusing the VS Code selection script? A: The VS Code script reads from the X11 clipboard (because VS Code copies there first). The Zed script reads from the $ZED_SELECTED_TEXT environment variable. Different input source, same output: a temp .do file sent to Stata.


Q: What if my selection is very large? A: Environment variables have a size limit (typically 128 KB to 2 MB on Linux). Normal Stata do-file selections will never hit this. If you need to run a 500-line block, use Ctrl+Enter to run the whole file instead.


Q: Will Shift+Enter work if nothing is selected? A: No. The script exits with an error message. Zed may also filter the task from its task picker when no text is selected. Always select text first.


Q: Can I make these keybindings work in ALL file types, not just .do? A: Yes. Remove the context restriction:

[
  {
    "bindings": {
      "ctrl-enter": ["task::Spawn", { "task_name": "Run do-file in Stata GUI" }],
      "shift-enter": ["task::Spawn", { "task_name": "Run selection in Stata GUI" }]
    }
  }
]

But this will override Shift+Enter in every file type, which is usually not desirable.


Q: After running, should focus stay on Stata or return to Zed? A: Personal preference. By default, focus stays on Stata so you can immediately read output. To auto-return to Zed, uncomment these two lines at the bottom of both scripts:

# sleep 0.5
# wmctrl -xa "${EDITOR_WMCLASS}"

In the Zed-specific script, EDITOR_WMCLASS is already set to "zed".


Complete Removal

To remove only the Zed-specific Stata integration (without affecting VS Code or Stata itself):

# Remove Zed-specific selection script
rm -f ~/.local/bin/stata_run_selection_zed.sh

# Remove Zed task and keybinding configs
rm -f ~/.config/zed/tasks.json
rm -f ~/.config/zed/keymap.json

To also remove the shared whole-file runner (affects VS Code too):

rm -f ~/.local/bin/stata_run_do.sh

Quick Verification Checklist

# 1. Confirm Xorg session
echo $XDG_SESSION_TYPE
# Expected: x11

# 2. Confirm Stata binary exists
ls /usr/local/stata19/xstata-mp

# 3. Confirm both scripts are on PATH
which stata_run_do.sh
# Expected: /home/mohsin/.local/bin/stata_run_do.sh
which stata_run_selection_zed.sh
# Expected: /home/mohsin/.local/bin/stata_run_selection_zed.sh

# 4. Confirm Zed tasks exist
cat ~/.config/zed/tasks.json
# Expected: two task definitions

# 5. Confirm Zed keybindings exist
cat ~/.config/zed/keymap.json
# Expected: ctrl-enter and shift-enter bindings

# 6. Open a .do file in Zed, press Ctrl+Enter
# Expected: Stata opens and runs the file

# 7. Select lines including block comments, press Shift+Enter
# Expected: runs correctly in Stata with no r(199) errors

All seven passing means everything is correctly configured.


Companion guide to stata19-complete-guide.md and the Antigravity Stata integration guide Built on the tested Zorin OS 18.1 Pro setup · Zed 0.231.2 · April 2026

Discussion