Bidirectional bridge between Cinema 4D's Script Manager and your code editor. Write and run C4D Python scripts from Zed or Emacs without leaving your editor.
Supports execute, debug (via debugpy), load-in-manager, re-run,
pull-from-C4D, and interactive REPL.
pip install -e .
# or
make installMerge keymap_c4d.json into %APPDATA%\Zed\keymap.json by copy-pasting the
keybinding entries.
Copy c4d.el into your Doom modules/ or lisp/ directory, or load it from
config.el. Bindings are under SPC m c and C-c C-c.
If Emacs runs inside WSL2 while C4D + bridge run on Windows:
-
Install
c4dbridgeon Windows (where C4D lives):pip install -e .This runs the bridge server.
-
Install
c4dbridgeinside WSL2 (where Emacs lives):# Clone or copy the repo into WSL2, same command: pip install -e .
Only the CLI client is used here — no server, no C4D.
-
Allow port 7789 through Windows Firewall so WSL2 can reach the bridge:
New-NetFirewallRule -DisplayName "c4dbridge" ` -Direction Inbound -Protocol TCP -LocalPort 7789 -Action AllowRun this on Windows as Administrator (one-time setup). WSL2 connects via a virtual Ethernet interface, not
127.0.0.1. -
Start the bridge on Windows (manually or via a startup script):
c4dbridge start
Do NOT try to start it from WSL2 —
c4dbridgeinside WSL2 is a client only. The bridge must run on the same machine as C4D. -
Use Emacs normally —
c4d.eldetects the bridge viac4dbridge status(which auto-resolves the Windows gateway IP from inside WSL2). No manual IP configuration needed.
constants.py detects WSL2 via /proc/version (_is_wsl()), then
resolves the Windows host IP by parsing ip route show for the default
gateway (_detect_windows_host_ip()). This gateway IP is exactly the
Windows machine's address on the WSL2 virtual network.
export C4DBRIDGE_HOST=192.168.1.42 # Replace with your Windows LAN IPOr set it per-invocation in your editor's task config.
| Aspect | Windows-only | WSL2 |
|---|---|---|
| Bridge start | Auto-start from editor | Manual start on Windows |
| Stop command | c4dbridge stop |
Same (works cross-OS) |
| Marker file | %TEMP%\c4d_last_file.txt |
\tmp\c4d_last_file.txt (different paths, same role) |
open-from-c4d |
Opens zed/emacs on Windows | Opens Emacs in WSL2 via C4DBRIDGE_EDITOR |
| REPL | c4dbridge repl |
Same — works transparently |
- C4D: Open Script Manager → launch Code Exchanger (listens on port 7788)
- Start bridge:
c4dbridge start, orCtrl+Alt+Bin Zed, orSPC m c sin Emacs - Open a
.pyfile and run it
Since v0.6.0, three addresses are managed independently:
| Variable | Default | Role |
|---|---|---|
C4D_HOST |
127.0.0.1 |
WebSocket bridge → C4D (always local, both on Windows) |
CTRL_BIND_HOST |
0.0.0.0 |
Bridge listens here (all interfaces — needed for WSL2) |
CTRL_CONNECT_HOST |
auto-detected | Client connects here (127.0.0.1 on Windows, gateway IP on WSL2) |
Override any of these via environment variables:
| Env var | What it overrides |
|---|---|
C4DBRIDGE_HOST |
CTRL_CONNECT_HOST — client connects here |
C4DBRIDGE_CTRL_BIND |
CTRL_BIND_HOST — bridge binds here |
C4DBRIDGE_EDITOR |
Editor command for open-from-c4d |
| Zed Key | Emacs Key | Action | What it does |
|---|---|---|---|
Ctrl+Alt+B |
SPC m c s |
Start Bridge | Launch the persistent bridge process |
Alt+B |
SPC m c e / C-c C-c |
Execute | Send script to C4D and run it |
Shift+F5 |
SPC m c d |
Debug | Start debugpy, then attach at 127.0.0.1:5678 |
Ctrl+F6 |
SPC m c l |
Load | Load script into Script Manager (don't run) |
Alt+Shift+B |
SPC m c r |
Re-run | Re-execute the last script |
Alt+V |
SPC m c f |
Pull from C4D | Fetch C4D's current script into your editor |
| — | SPC m c R / C-c C-z |
REPL | Interactive C4D Python REPL (Emacs only) |
| — | c4dbridge repl |
REPL | Interactive REPL from any terminal |
Ctrl+Alt+Shift+B |
SPC m c x |
Stop Bridge | Stop the bridge gracefully |
Editor (Emacs) → CTRL_CONNECT_HOST:7789 → bridge (async) → C4D_HOST:7788 → C4D
- The bridge (
c4dbridge) is a persistent Python process that maintains a WebSocket connection to C4D (port 7788) and a TCP command server (CTRL_BIND_HOST:7789). - Editor tasks are short-lived CLI processes (
c4dbridge execute <file>etc.) that send one JSON command to the bridge and exit. - The bridge translates between the editor's synchronous-per-invocation model and C4D's persistent WebSocket protocol.
The REPL (c4dbridge repl) maintains a persistent Python namespace in C4D via
builtins._c4dbridge_repl_ns. Variables defined at one prompt survive to the
next. The result arrives inside a __C4DBRIDGE_REPL__ marker line in the
console stream; server.py intercepts it and routes it back through a dedicated
queue instead of printing it.
- Start:
c4dbridge start— connects to C4D with auto-retry (2s–15s exponential backoff); binds onCTRL_BIND_HOST:CTRL_PORT - Stop:
c4dbridge stop— sends polite stop via TCP; bridgeos._exit(0)(no netstat/taskkill — client and server may be on different OSes under WSL2) - Auto-reconnect: If C4D disconnects, the bridge reconnects automatically
- Keepalive: Sends
get_pidevery 25s to prevent C4D's Code Exchanger from idle-disconnecting
| Variable | Default | Description |
|---|---|---|
C4DBRIDGE_HOST |
auto-detected | Override control-port connect host (WSL2 gateway IP) |
C4DBRIDGE_CTRL_BIND |
0.0.0.0 |
Override control-server bind address |
C4DBRIDGE_EDITOR |
zed |
Editor command for open-from-c4d |
C4D's protocol expects paths in file:///C:/path/to/file.py format (forward
slashes, uppercase drive letter). The bridge handles this automatically.
| Symptom | Fix |
|---|---|
Bridge is already running |
Run c4dbridge stop |
Bridge is not running |
Start the bridge with c4dbridge start |
C4D not connected |
Make sure Code Exchanger is running in C4D |
Script not found in C4D |
Load first, then pull |
Editor not found |
export C4DBRIDGE_EDITOR=emacsclient -n |
Connection refused from WSL2 |
Check Windows Firewall rule for port 7789 |
C4D_HOST is wrong |
Never changes — bridge + C4D are both on Windows |
c4dbridge/ — Python package (the bridge)
__init__.py — exports main()
__main__.py — python -m c4dbridge
constants.py — ports, paths, colors, WSL detection
log.py — console output helpers
protocol.py — Maxon protocol messages + REPL eval script
client.py — synchronous CLI commands (execute, load, repl, …)
server.py — async WebSocket client + TCP control server
tasks.json — Zed task definitions
keymap_c4d.json — Zed keybindings (reference)
c4d.el — Emacs integration (REPL, keybindings)
templates/ — C4D script templates
AGENTS.md — Project rules for AI assistants
ARCHITECTURE.md — Full system documentation