You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
IPC mechanism / lightweight background server in the event loop for external editor support #112
Disclaimer: While I used an LLM to help draft the text of this issue, the core ideas and feature requests are entirely my own.
I am currently planning a rework of the IPC and background communication mechanisms in vscode-R. Historically, vscode-R has relied on a set of very ad-hoc servers and workarounds to allow communication between the R session and VSCode (summarized here: vscode-R IPC mechanisms). Maintaining these custom R-level server implementations is quite difficult and prone to edge-case bugs.
Motivation
Since arf is a modern R console written in Rust that manages its own execution environment, it would be fantastic if it could expose a feature in its event loop to run a lightweight server or IPC mechanism (e.g., TCP or Unix domain sockets).
The goal is to build a stable R <-> arf <-> VSCode communication channel directly in Rust's event loop, replacing fragile pure-R background servers.
I propose using JSON-RPC for this connection because it is lightweight and standard. Implementation-wise, since arf already wraps the R session in Rust, I imagine this IPC listener could be multiplexed within the ptr_R_ReadConsole hook. By awaiting both terminal input and JSON-RPC requests concurrently, editor queries could be handled while R is idle at the prompt. Additionally, hooking a non-blocking check into R_PolledEvents would allow the server to remain responsive to editor requests or interrupt signals even while R is busy executing long scripts.
I would love to hear your thoughts on whether this fits into the roadmap or scope of arf. I am also happy to discuss what a minimal protocol or integration point for this might look like!
Alternatives considered
I have looked into how the ark kernel uses amalthea to allow R to talk with Jupyter. While it's a great framework, adopting it would require an architecture like R <-> amalthea <-> jupyter <-> vscode.
For our specific needs in vscode-R, wrapping everything in the Jupyter protocol feels entirely too heavy. We would prefer to implement a much simpler, custom protocol suited strictly for editor-to-R communication, which a lightweight IPC server in arf would perfectly facilitate.
To be honest, I'm hesitant to implement features for specific tools (like vscode-R), but I think your suggestions could be essentially the same as the features I'd like to use for AI agents.
You move fast! It is exactly what I was asking. Of course, it makes sense to have a client agnostic server! My prototype for DAP predated the LLM/AI agents, but I glad to learn that similar proposals could be used in AI agents/ MCP.
Sorry that I didn't have the time to look at the IPC server, it seems that the server is not protected by any mean of authentication, I would suggest at least you want to implement a simple token based authentication like jupyter notebook.
Sorry that I didn't have the time to look at the IPC server, it seems that the server is not protected by any mean of authentication, I would suggest at least you want to implement a simple token based authentication like jupyter notebook.
Don't worry about it. Take a look when you have time.
Authentication is intentionally absent, and TCP communication has also been intentionally omitted.
IIUC, by limiting communication to Unix domain sockets and Windows named pipes, the implementation is kept simple while maintaining security.
If necessary, a proxy server will need to convert to TCP.
Thank you for following up with it. arf makes connection based on socket/pipe. In 3.0, we want to continue to support plain R, it means that we would need to replicate the approach with R packages. Unfortunately, i couldn't really able to find a way to make socket/pipe based connection works asynchronously in R. I tried the R package nanonext but the ts counterpart is not working.
At the end, I have given up the socket/pipe based approach and use websocket instead. Additionally,i have found that it is easier to manage connection when R is the client but not the server.
Ark promised to bring lsp/dap to other editors but it is still not the case.
At the current form, arf is still not very useful. It will be great if we can somehow bridge the gap between lsp and dap to other editors.
I also tried processx, I cannot recall the exact issue that I had, but it was not able to make processx to read/write non-blockingly to a windows named pipe (if I recalled correctly, unix socket worked well).
We investigated whether arf can substitute the sess package's functionality to reduce R package dependencies in the vscode-R integration. Here are the findings.
Background
This picks up from @randy3k's earlier comments about R needing to be a client (not a server), and the difficulty of making socket/pipe communication work asynchronously in plain R. Our conclusion is that this constraint applies to plain R, but not to arf.
Why "R must be client" does not apply to arf
Randy's constraint has two layers:
Technical: plain R cannot easily accept() new connections in its event loop. arf (Rust/tokio) already runs an async IPC server — this layer doesn't apply.
Lifecycle: when vscode-R spawns R, vscode-R exists first and must be the server. But when the user launches arf directly, arf exists first — arf naturally stays as server.
Proposed architecture
vscode-R configures arf as the R terminal (r.rterm.*), launches it with --with-ipc, and discovers the IPC socket via ~/.cache/arf/sessions/{pid}.json (already written by arf on IPC startup — no new arf code needed). vscode-R then connects as a JSON-RPC client to arf's existing IPC socket.
evaluate (with visible=false): runs R code silently and returns stdout/stderr. This is sufficient for all metadata queries.
Session discovery: ~/.cache/arf/sessions/{pid}.json with socket_path — already implemented.
What can be done via the existing evaluate method
workspace: evaluate R code that cat(jsonlite::toJSON(lapply(ls(.GlobalEnv), ...))) → parse stdout as JSON.
hover: same pattern with str(eval(expr)).
member completion ($/@): same pattern with .DollarNames / slotNames.
View / help event routing: at connect time, vscode-R sends an initialization evaluate that sets up an R-side event queue (an environment with a list) and overrides utils::View / registerS3method("print", "help_files_with_topic", ...) to push events into it. A subsequent evaluate call drains the queue — no new Rust infrastructure needed.
rstudioapi compatibility: remains an R package concern (sess or equivalent).
Summary
No new features need to be added to arf itself. The existing IPC evaluate method and session file mechanism are sufficient for a full vscode-R integration that requires only jsonlite and jgd as R packages (vs. the current processx + later + jsonlite + svglite + rstudioapi stack). The remaining work is entirely on the vscode-R TypeScript side.
This also aligns with REditorSupport/vscode-R#1699, which improves the transport layer for the plain-R path independently.
Activity
randy3k commentedon Mar 10, 2026
Also see my comment in ManuelHentschel/VSCode-R-Debugger#156 (comment) on implementing a hook to support Debug Adapter Protocol.
eitsupi commentedon Mar 11, 2026
Thank you for your comment.
To be honest, I'm hesitant to implement features for specific tools (like vscode-R), but I think your suggestions could be essentially the same as the features I'd like to use for AI agents.
These are the closest to what I have in mind.
https://github.com/hexaeder/MCPRepl.jl
https://github.com/kahliburke/Kaimon.jl
I'll do a bit more research and then try making a prototype.
eitsupi commentedon Mar 11, 2026
@randy3k A MVP is there #113.
Could you take a look at that?
randy3k commentedon Mar 11, 2026
You move fast! It is exactly what I was asking. Of course, it makes sense to have a client agnostic server! My prototype for DAP predated the LLM/AI agents, but I glad to learn that similar proposals could be used in AI agents/ MCP.
randy3k commentedon Mar 21, 2026
Sorry that I didn't have the time to look at the IPC server, it seems that the server is not protected by any mean of authentication, I would suggest at least you want to implement a simple token based authentication like jupyter notebook.
eitsupi commentedon Mar 22, 2026
Don't worry about it. Take a look when you have time.
Authentication is intentionally absent, and TCP communication has also been intentionally omitted.
IIUC, by limiting communication to Unix domain sockets and Windows named pipes, the implementation is kept simple while maintaining security.
If necessary, a proxy server will need to convert to TCP.
eitsupi commentedon Mar 22, 2026
I've add a document about this: https://github.com/eitsupi/arf/blob/main/docs/ipc.md
eitsupi commentedon Apr 25, 2026
I believe the basic functions are implemented, so I will close this issue. If you have any further issues, please open a new issue.
eitsupi commentedon May 3, 2026
@randy3k I saw REditorSupport/vscode-R#1684 was merged.
Are there any plans for integration with arf?
randy3k commentedon May 3, 2026
Thank you for following up with it. arf makes connection based on socket/pipe. In 3.0, we want to continue to support plain R, it means that we would need to replicate the approach with R packages. Unfortunately, i couldn't really able to find a way to make socket/pipe based connection works asynchronously in R. I tried the R package nanonext but the ts counterpart is not working.
At the end, I have given up the socket/pipe based approach and use websocket instead. Additionally,i have found that it is easier to manage connection when R is the client but not the server.
Ark promised to bring lsp/dap to other editors but it is still not the case.
At the current form, arf is still not very useful. It will be great if we can somehow bridge the gap between lsp and dap to other editors.
eitsupi commentedon May 4, 2026
@randy3k Have you seen the processx package?
https://processx.r-lib.org/
Based on my experience with jgd, I thought that the processx package could support socket communication.
randy3k commentedon May 4, 2026
I also tried processx, I cannot recall the exact issue that I had, but it was not able to make processx to read/write non-blockingly to a windows named pipe (if I recalled correctly, unix socket worked well).
randy3k commentedon May 4, 2026
It was the summary by gemini: https://gist.github.com/randy3k/e341364350c14fe5b8d8dc97a9132449.
The TLDR is that: Calling
conn_read_chars(con, n)orconn_read_lines(con, n=1)on an empty pipe freezes the R thread.eitsupi commentedon May 5, 2026
@randy3k Have you tried
conn_connect_unix_socket()instead ofconn_create_file()?Based on my research, this might work.
randy3k commentedon May 5, 2026
for windows named pipe?
eitsupi commentedon May 5, 2026
That's right. processx uses named pipes instead of UDS on Windows.
https://processx.r-lib.org/reference/processx_sockets.html
eitsupi commentedon May 5, 2026
I opened a PR REditorSupport/vscode-R#1699
eitsupi commentedon May 6, 2026
We investigated whether arf can substitute the sess package's functionality to reduce R package dependencies in the vscode-R integration. Here are the findings.
Background
This picks up from @randy3k's earlier comments about R needing to be a client (not a server), and the difficulty of making socket/pipe communication work asynchronously in plain R. Our conclusion is that this constraint applies to plain R, but not to arf.
Why "R must be client" does not apply to arf
Randy's constraint has two layers:
accept()new connections in its event loop. arf (Rust/tokio) already runs an async IPC server — this layer doesn't apply.Proposed architecture
vscode-R configures arf as the R terminal (
r.rterm.*), launches it with--with-ipc, and discovers the IPC socket via~/.cache/arf/sessions/{pid}.json(already written by arf on IPC startup — no new arf code needed). vscode-R then connects as a JSON-RPC client to arf's existing IPC socket.What arf already provides
evaluate(withvisible=false): runs R code silently and returns stdout/stderr. This is sufficient for all metadata queries.~/.cache/arf/sessions/{pid}.jsonwithsocket_path— already implemented.What can be done via the existing
evaluatemethodevaluateR code thatcat(jsonlite::toJSON(lapply(ls(.GlobalEnv), ...)))→ parse stdout as JSON.str(eval(expr)).$/@): same pattern with.DollarNames/slotNames.evaluatethat sets up an R-side event queue (an environment with a list) and overridesutils::View/registerS3method("print", "help_files_with_topic", ...)to push events into it. A subsequentevaluatecall drains the queue — no new Rust infrastructure needed.What is handled elsewhere
jgdas an alternative graphics device REditorSupport/vscode-R#1679.Summary
No new features need to be added to arf itself. The existing IPC
evaluatemethod and session file mechanism are sufficient for a full vscode-R integration that requires onlyjsonliteandjgdas R packages (vs. the currentprocessx+later+jsonlite+svglite+rstudioapistack). The remaining work is entirely on the vscode-R TypeScript side.This also aligns with REditorSupport/vscode-R#1699, which improves the transport layer for the plain-R path independently.