Hacker Newsnew | past | comments | ask | show | jobs | submit | t-kalinowski's commentslogin

Very cool!

We’ve been exploring a similar direction too, but with a plain REPL and a much thinner tool surface. In our case, it’s basically one tool for sending input, with interrupts and restarts handled through that same path. Marimo seems to expose much richer notebook structure and notebook-manipulation semantics, which is a pretty different point in the design space.

It seems like the tradeoff is between keeping the interaction model simple and the context small, versus introducing notebook structure earlier so the model works toward an artifact at the same time it iterates and explores. Curious how you think about that balance.

Repo: https://github.com/posit-dev/mcp-repl


Thanks for sharing!

I think the tradeoff is less stark than it seems. Our tool surface is also basically just "run Python", but the model may additionally use a semi-private API ("code mode") within that execution context to inspect and modify the notebook itself. So the notebook structure isn't something the model has to manage. Marimo's reactivity handles the graph automatically, and the model gets artifact construction as a side effect of exploration.

Where I'd imagine the approaches diverge more is in what the runtime gives back. In a plain REPL, the model carries state in its context. In marimo, it can offload state to the notebook and query it back: inspect variables, read cell outputs, check the dependency graph. That turns the notebook into working memory the model can use without it all living in the conversation. Over longer sessions especially, that matters.


interesting, i also went the same direction with https://github.com/danieltanfh95/replsh because i needed to support existing legacy python codebases.

I agree that at first glance, it seems like tmux, or even long-running PTY shell calls in harnesses like Claude, solve this. They do keep processes alive across discrete interactions. But in practice, it’s kind of terrible, because the interaction model presented to the LLM is basically polling. Polling is slow and bloats context.

To avoid polling, you need to run the process with some knowledge of the internal interpreter state. Then a surprising number of edge cases start showing up once you start using it for real data science workflows. How do you support built-in debuggers? How do you handle in-band help? How do you handle long-running commands, interrupts, restarts, or segfaults in the interpreter? How do you deal with echo in multi-line inputs? How do you handle large outputs without filling the context window? Do you spill them to the filesystem somewhere instead of just truncating them, so the model can navigate them? What if the harness doesn’t have file tools? And so on.

Then there is sandboxing, which becomes another layer of complexity wrapped into the same tool.

I’ve been building a tool around this problem: `mcp-repl` https://github.com/posit-dev/mcp-repl

So tmux helps, but even with a skill and some shims, it does not really solve the core problem.


Posit offers something similar to Microsoft’s CRAN Time Machine, but it works not only for CRAN, but also for Bioconductor and PyPI. You can add a date to the Public Posit Package Manager URL to access a snapshot of all packages from that day.

For example: https://packagemanager.posit.co/cran/2025-03-02

You can browse available snapshot dates here: https://packagemanager.posit.co/client/#/repos/cran/setup?sn...

This also works for PyPI and Python packages: https://packagemanager.posit.co/pypi/2025-03-04/simple


Or, don't even write the fortran manually, just transpile the R function to fortran: https://github.com/t-kalinowski/quickr


This was the main reason I wrote promptdown. I want to be able to edit the full chat history every turn, and the append-only standard chat interfaces don't make that easy.

https://github.com/t-kalinowski/promptdown


The Python interop is in the blog post because it makes for convenient and compact examples, not because it motivated any of the features.

If you're interested in what motivated S7, you may enjoy this talk Hadley gave: https://www.youtube.com/watch?v=P3FxCvSueag (R7 was the working name for the package at the time)


R does have namespaces. Take a look at the NAMESPACE file found at the root of every R package, which defines the symbols and methods exported by the package.

Note for many R packages, the NAMESPACE file is autogenerated from roxygen docs: https://cran.r-project.org/web/packages/roxygen2/vignettes/n...


> which defines the symbols and methods exported by the package

Which are all dumped into the one single global namespace regardless if you want everything or not.

I can't remember the exact number, but tidyverse package imports literally thousands of things into your global namespace on package load, coupled with any other dependencies and you have a hell of a time figuring out where any function or constant came from.


Calling library() is kind of an antipattern in production R code. You can either call namespaced functions (like say dplyr::mutate()), or use roxygen.

https://roxygen2.r-lib.org/articles/namespace.html


Agreed but the GP isn't wrong. It's much much nicer to import a library with an alias in Python.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: