Skip to content

IPC mechanism / lightweight background server in the event loop for external editor support #112

Closed

Description

@randy3k

Description

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.

Additional context

No response

Activity

  1. randy3k commented on Mar 10, 2026

    @randy3k
    Author

    Also see my comment in ManuelHentschel/VSCode-R-Debugger#156 (comment) on implementing a hook to support Debug Adapter Protocol.

  2. eitsupi commented on Mar 11, 2026

    @eitsupi
    Owner

    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.

  3. eitsupi commented on Mar 11, 2026

    @eitsupi
    Owner

    @randy3k A MVP is there #113.
    Could you take a look at that?

  4. randy3k commented on Mar 11, 2026

    @randy3k
    Author

    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.

  5. randy3k commented on Mar 21, 2026

    @randy3k
    Author

    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.

  6. eitsupi commented on Mar 22, 2026

    @eitsupi
    Owner

    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.

  7. eitsupi commented on Mar 22, 2026

    @eitsupi
    Owner
  8. eitsupi commented on Apr 25, 2026

    @eitsupi
    Owner

    I believe the basic functions are implemented, so I will close this issue. If you have any further issues, please open a new issue.

  9. eitsupi commented on May 3, 2026

    @eitsupi
    Owner

    @randy3k I saw REditorSupport/vscode-R#1684 was merged.
    Are there any plans for integration with arf?

  10. randy3k commented on May 3, 2026

    @randy3k
    Author

    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.

  11. eitsupi commented on May 4, 2026

    @eitsupi
    Owner

    @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.

  12. randy3k commented on May 4, 2026

    @randy3k
    Author

    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).

  13. randy3k commented on May 4, 2026

    @randy3k
    Author

    It was the summary by gemini: https://gist.github.com/randy3k/e341364350c14fe5b8d8dc97a9132449.
    The TLDR is that: Calling conn_read_chars(con, n) or conn_read_lines(con, n=1) on an empty pipe freezes the R thread.

  14. eitsupi commented on May 5, 2026

    @eitsupi
    Owner

    @randy3k Have you tried conn_connect_unix_socket() instead of conn_create_file()?
    Based on my research, this might work.

  15. randy3k commented on May 5, 2026

    @randy3k
    Author

    @randy3k Have you tried conn_connect_unix_socket() instead of conn_create_file()?
    Based on my research, this might work.

    for windows named pipe?

  16. eitsupi commented on May 5, 2026

    @eitsupi
    Owner

    That's right. processx uses named pipes instead of UDS on Windows.
    https://processx.r-lib.org/reference/processx_sockets.html

  17. eitsupi commented on May 5, 2026

    @eitsupi
    Owner
  18. eitsupi commented on May 6, 2026

    @eitsupi
    Owner

    Posted by Claude Code on behalf of @eitsupi

    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.

    User types → [arf REPL] ←──IPC socket──→ [vscode-R TypeScript client]
                      ↕ evaluate wrappers: workspace / completion / hover / events
    
    [jgd R package] ←──independent path──→ [jgd VS Code ext] → plot panel
    

    What arf already provides

    • 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.

    What is handled elsewhere

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions