HNHacker News
TopNewBestAskShowJobs

josevalim

4,367 karma · joined January 12, 2008

submissionscomments
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
I hear you. I'd love to integrate with whatever model subscription is available but it seems using Max outside of Claude products is against their terms. I suggest reaching out to Anthropic and letting them know you would like to use your Max subscription with other coding agents.
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Can you ping me on Tidewave's Discord or send me an email (you can find on github.com/josevalim)? We did test it on https recently and it worked fine, so there is something more going on. I'd be glad to see this ironed out!
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Yes!
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
As you said, the best would be for you to give it a try and see the benefits in practice (if any). Beyond that, I can add to two points you brought up:

First, Playwright MCP is really not enough. For example, imagine you are building a project management software and you are working on a feature for transferring tasks between projects. Testing this feature requires at least a user who is admin and at least two projects. When it is time for Playwright to test this feature, you need to automate the account creation, then it has to set up two projects, add the task, etc, and it often gets stuck.

When you are using Tidewave, you naturally do this setup as part of your development, which Tidewave has direct access to during tests. So it just interacts with the same page. Furthermore, if you see any bugs or places you could improve, you can't really tell Playwright or regular coding agent to fix them, you have to translate what you want. With Tidewave you just point and click and it works across browsers. I talk more about this in the announcement post: https://tidewave.ai/blog/tidewave-web-phoenix-rails

Other than that, I am really curious about the handoff between Tidewave and the editor that you mentioned. At some point, you will need the editor indeed, but how to best do this transaction? Should you be able to review and do tiny tweaks within Tidewave first? Regardless, moving the agent to the browser for web applications bring enough benefits to justify going one lever higher. :)

josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
You are first redirected for authentication purposes. Once authenticated, it redirects back to your app.
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
We are working on React integration, first within Rails and Phoenix, but then also standalone. How are you serving/running your React apps in development?
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
It is both. There is a Tidewave server (which will play a more meaningful role once we introduce agent coordination) but we also hope the limit will be enough for people to see value in the tool and convert into paying users (so we can continue improving it).
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
We log basic request metadata (timestamps, model used, token counts). Prompts and messages are not logged unless you explicitly opt-in. We don't store tool results. Note the underlying model provider you use may store data separately depending on your user agreement with them.
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Phoenix.new is about remote agents, while Tidewave integrates with your app running on your machine!
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
You can think of Tidewave MCP as integrating the agent with the language runtime, while Tidewave Web integrates the agent with your actual app and its interface. It knows your views and templates, it can correlate it with the rendered page, and then automate the browser to implement and validate features.

Our announcement post goes more into detail and explains why moving the agent to the browser means you (the developer) can spend more time out of the loop: https://tidewave.ai/blog/tidewave-web-phoenix-rails

josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Hi folks! Great to see our work on the front page, and I'm happy to answer questions.

Regarding next steps, we're currently working on React integration, with Python and JavaScript server-side web frameworks coming next. If you're interested, here's our survey/waiting list: https://forms.gle/8MeXwGjpBFDeGNQw9

josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
There are two main reasons why being framework specific can be a big boost:

1. We annotate and understand your template language. So when you select an element, we not only know its tag and attributes, but we also know which template file rendered it. The more structured the template language is (JSX, HEEx, etc), the better job we can do, which means LLMs don't have to guess.

2. We also run code within the web framework. This means database access, built-in documentation using the exact versions in your project, access to language and framework reflection/introspection APIs, etc. So the agents have more, err, agency.

I hope this clarifies it a bit!

josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Thank you `kawsper` for the feedback!

We are going to introduce more visibility into the context limit and make it easier to summarize.

Regarding the on-hover, do you still have the snippets around that it tried? We instruct the model to dispatch events using the proper browser APIs and I wonder what it tried to do. I would love to hear more! You can ping me on Tidewave's Discord (https://discord.gg/5GhK7E54yA) or send me an email (see github.com/josevalim).

josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Thanks! We plan to do so eventually. It is listed in our roadmap but not currently assigned to any milestone. OpenRouter support will likely land first (which will help us get feedback on which other models it works well with).
josevalim··on Tidewave Web: in-browser coding agent for Rails and Phoenix
Hi everyone! I am representing the team behind Tidewave. Glad to answer any questions.
josevalim··on Don't “let it crash”, let it heal
Processes can be marked as temporary, which means they are not restarted, and that’s what is used when managing http connections, as you can’t really restart a request on the server without the client. So the scenario above wouldn’t happen.

You still want those processes to crash though, as it allows it to automatically clean up any concurrent work. For example, if during a request you start three processes to do concurrent work, like fetching APIs, then the request process crashes, the concurrent processes are automatically cleaned up.

josevalim··on Don't “let it crash”, let it heal
That’s actually a good example. Imagine someone forgot to check the error code from an API response. In some languages, they may attempt to parse it as if it was successful request, and succeed, leading to a result with nulls, empty arrays, or missing data that then spreads through the system. In Elixir, parsing would most likely fail thanks to pattern matching [1] and if it by any chance that fails in a core part of the system, that failure will be isolated and that particular component can be restarted.

Elixir is not about willingly ignoring error codes or failure scenarios. It is about naturally limiting the blast radius of errors without a need to program defensively (as in writing code for scenarios you don’t know “just in case”).

1: https://dashbit.co/blog/writing-assertive-code-with-elixir

josevalim··on AI coding agents are removing programming language barriers
Phoenix.new is a good example of a coding agent that can fully bootstrap realtime Elixir apps using Phoenix LiveView: https://phoenix.new/

I also use coding agents with Elixir daily without issues.

josevalim··on Ada Continues to Climb in June Tiobe Index and PYPL
My understanding (which may be wrong) from the exchange is that they literally search for "elixir programming" on several websites, including Amazon. So it is very sensitive to whatever changes those websites do to their own search engines. I can no longer reproduce the behaviour from back then but it is very understandable that websites like Amazon are optimizing their search results for sales and other key metrics rather than term precision.
josevalim··on Ada Continues to Climb in June Tiobe Index and PYPL
I have a fun anecdote. About 5-6 years ago, Elixir completely disappeared from the top 100 after spending some time in the top 50. People reached out to me and then I reached out to TIOBE to understand why and the reason given was "bad presence on Amazon".

After further investigation, the root cause seemed to be that we finally had enough published Elixir books. At the time, if you searched for "xyz programming" on Amazon and only found a few results, Amazon would pad those results with non-relevant entries. However, because Elixir reached about 20-30 books, we were no longer padded, so we suddenly got worse rankings than every other language with only a handful of books. This happened on every Amazon domain they searched on, so it compounded and effectively kicked us out of the top 100 altogether. This all happened at a time Elixir language activity had already reached top 25 on GitHub PRs/stars.

josevalim··on Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers
Oh, that’s exciting to hear! I would love to exchange notes and I know one of the lead researchers of set theoretic types would love to learn more about your uses too. If that sounds fun to you, you can find me on Gmail (same username).

In our case, we implement a bidirectional system where before applying x to Integer.to_string, we compute the domain of Integer.to_string (which is integer) and pass it up. If x is a dynamic type, then we refine it. So on the first call, x refines to `dynamic & integer`, then we apply it.

The second refinement fails because it becomes none, so we discard it, but it means the application on Atom.to_string will fail anyway. So yes, we check for emptiness and discard none.

josevalim··on Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers
For us type inference is the same as type checking where all parameters are given the dynamic type. So even if you explicitly added a signature that said dynamic, we would still find a violation, where others would not. The point is that dynamic does not have to mean “anything goes”.
josevalim··on Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers
> Gradual typing means that an implicit "any" (unknown type) anywhere in your code base is not an error or even a warning.

That depends on the implementation of gradual typing. Elixir implements gradual set-theoretic types where dynamic types are a range of existing types and can be refined for typing violations. Here is a trivial example:

    def example(x) do
      {Integer.to_string(x), Atom.to_string(x)}
    end
Since the function is untyped, `x` gets an initial value of `dynamic()`, but it still reports a typing violation because it first gets refined as `dynamic(integer())` which is then incompatible with the `atom()` type.

We also introduced the concept of strong arrows, which allows dynamic and static parts of a codebase to interact without introducing runtime checks and remaining sound. More information here: https://elixir-lang.org/blog/2023/09/20/strong-arrows-gradua...

josevalim··on Unauthenticated Remote Code Execution in Erlang/OTP SSH
Using macros when a function would do is a legit anti-pattern (and documented as such [1]) but unrelated to the security aspect as they are compile-time constructs.

The reason they were added to the language was precisely so meta and dynamic programming is done at compile time, which you can introspect before you deploy, versus doing it at runtime, which is how most dynamic languages tackle this. And those languages are most likely not using eval either, but intrinsic features that allow you to define classes, attributes, methods, and so on programmatically.

I’d say eval is discouraged in most languages, although it is useful for building things like REPLs and interactive environments.

[1]: https://hexdocs.pm/elixir/macro-anti-patterns.html#unnecessa...

josevalim··on Coordinating the Superbowl's visual fidelity with Elixir
I am sorry to hear. I understand it may be something out of your control but it seems you have clearly identified some "smells" that would be worth spending some time investigating.

For example, you can't have loops in deps, and therefore ~250 deps should not print a 6500 thousand entries long tree. At least, for this particular problem, you can isolate your project structure, without any code, and try to reproduce it externally. And, while you can override deps, the goal of an umbrella is to share dependencies, so overriding an umbrella sibling dependency is a smell too.

You said it's an enormous Jenga tower that's risky to breath around but it seems at the same time no one wants to invest on an air purifier. If it is of any help, you can look at the Remote case on the Elixir website (https://elixir-lang.org/blog/2025/01/21/remote-elixir-case/), they have a large codebase, around 15k files, 300 engineers (several dozens being Elixir ones), and while their codebase is healthy, you can see they had to invest on some "bottlenecks" that appeared along the way, such as CI times. And the need to invest in the code base itself will be true of any language as time passes. Best of luck!

josevalim··on Coordinating the Superbowl's visual fidelity with Elixir
> And yes, code is at fault, but I’d expect ecosystem to help fixing it, but we have none. E.g. circular dependendencies in umbrella. You can have them. You can print them. There is no warning.

Can you reproduce this in any way? Because I cannot:

    mix new parent --umbrella
    cd parent
    mix new apps/foo
    mix new apps/bar
Now change `Foo.hello` to call `Bar.hello` and vice-versa. When you run `mix compile`, you will get warnings like this:

    warning: Bar.hello/0 is undefined (module Bar is not available or is yet to be defined). Make sure the module name is correct and has been specified in full (or that an alias has been defined)
But of course, the `foo` and `bar` applications do not depend on each other, you can add explicit dependencies, such as `foo` depending on `bar` or `bar` depending on `foo`, but you always get warnings. And if you literally make it a dependency cycle, the app doesn't even boot:

    ** (Mix) Could not sort dependencies. The following dependencies form a cycle: foo, bar
Apps have to be compiled in order and one will by definition be compiled before the other, so it is really unclear how you could have those circular dependencies.

But even then, let's say that somehow you have an undeclared and undefined cycle between `foo` and `bar`. The point of umbrella projects is that each app can be compiled in isolation, so you should be able to go to `bar` and compile it in isolation without `foo`, and if it is trying to invoke `foo` somehow, it will be made visible.

So yes, I would need a way to reproduce this, because there are warnings and tooling in place to deal with those. Thanks!

josevalim··on Coordinating the Superbowl's visual fidelity with Elixir
> Yet given very static download count of Jason on Hex I think that rarely new projects are started in Elixir

So you are getting the download count of one package, one that has been added to Erlang/OTP (and Elixir itself) and is more than expected to decrease in download count, to estimate the popularity of the whole language and a ecosystem of 20k+ packages? And over what time period exactly?

> (ExDocs breaking) ... please give an example In screenshot - happened with Chromium,Safari and Firefox ~6 months ago. Often with OTEL libraries.

Got it. I was reminded that there was unfortunately one version of ExDoc with a sidebar bug and they probably were still using it. If you ask the package authors to update `ex_doc` and republish the docs, it should take 2 minutes to fix it. They might already have done it though.

Regarding ExDoc's search, people have been asked for improvements, such as searching on latest version by default and searching across packages. I am glad to say there is work happening towards this area (including soon the ability to search across all of the dependencies of your own project).

The other bug in your screenshot, about Ecto.Query, please report it if you can reproduce it. It is indeed a "wat" bug but I am not sure what could be causing it. EDIT: I was told this may happen if you are using a mocking library, here is a reproduction and a bug report: https://github.com/jjh42/mock/issues/151 - if you are using mocking libraries, please double check if they can be the root cause.

> I made a mental shortcut - i.e it's using only one core right now, and it's taking approx. 2-3 minutes. Looks like PR would resolve it, but not sure when we'll be able to use it.

It should not be using one core, even it if compiles one dependency at a time. My whole point is that you get parallelism from within the dependency/project.

> when doing umbrella tests on non compiled code seed influences order of compilation

Honestly, I have no idea how this could possibly be the case. Elixir's seed is applied per process and, in this case, it is only applied to the process running your tests, which is not the process related to compilation at all. I will drop a comment in your other thread about cycles in your umbrellas, which is also not possible.

> I can see popular libraries spread across 3-4 different major versions)

This is also something that should not be possible. I mean, you can specify different major versions, but the dependency resolution will guarantee they all agree on a single one. For example, you can't have different versions of `Jason` in the same umbrella, unless there is something really unconventional or undesired on how you are building your umbrella apps. So I would need a mechanism to reproduce it in order to pinpoint what. I would double and triple check your apps configuration, it seems there is something really unexpected going on.

josevalim··on Coordinating the Superbowl's visual fidelity with Elixir
Thanks for the feedback! I'd like to comment on some points:

- There seems to be some confusion in relation to warnings. There are two types of warnings, compile-time warnings and runtime warnings. Compile-time warnings are emitted during compilation time and therefore should not affect test runs, aka, when you run code. Runtime warnings can be captured during tests, using `ExUnit.CaptureIO`. Deprecating modules and functions are compile-time warnings

- Indeed you need to enable `--warnings-as-errors` to halt compilation due to warnings in CI. Our philosophy here is to emit compilation warnings instead of compilation errors whenever possible, so you can run, debug, and test your code, instead of forcing your code to be pristine while you are still working on it. The focus here is precisely to provide a better developer experience. Then if you do want them to fail upfront, as in CI, you pass the flag

- "when doing umbrella tests on non compiled code seed influences order of compilation" - I am not sure what this means, sorry. Can you expand? But generally speaking our test framework randomizes test order by default, because you should not depend on order between tests or have dependencies between test files

- "dependency compilation is not parallelized" - when a dependency is compiled, the files in a dependency are parallelized, but not the dependencies themselves, so I'd very surprised if it only used 10% CPU before. In any case, a PR adding this feature was merged this week: https://github.com/elixir-lang/elixir/pull/14340. In my machine, compiling a project like Livebook uses 350% CPU without the flag above (showing some parallelism), and with the flag above set to 4, it is about 800% (250% + 250% + 150% + 150%). Note my machine has 8 performance cores and I don't get additional gains beyond 4 partitions

- "compilation process can break and Elixir isn’t aware that it was interrupted" - our tooling has code to deal precisely with this: https://github.com/elixir-lang/elixir/blob/c5c87a661efac6809.... If it still happens, it is a bug and must be reported, so we can fix it

- "try checking if you can dynamically add children to a Supervisor" - the top 4 results for "dynamically add children to a Supervisor in elixir" in Google and Ecosia lead to correct answers in the ElixirForum, StackOverflow, and the documentation. For completeness, I have also asked Claude, which gave a perfect answer (IMO): https://claude.ai/share/9d1e2ad4-2e43-4c32-a293-6fff32dd7001

- "there isn’t even a link to „open newest”" - this has been added to ExDoc, here is one example: https://hexdocs.pm/req/0.5.9/readme.html - but note we have always listed the versions in the sidebar

- "sidebar with new ExDocs break for some reason so there is no navigation" - please give an example, as this would be a bug and should be fixed, and I am not aware of any reports at the moment. Also note docs are available in the terminal, both inside `iex` or by doing `mix help SomeModule`

josevalim··on Data evolution with set-theoretic types
While it is a bit unfortunate that the time spent to write the article continues to be used as a criticism, and perhaps as a dig, I’ll only add that I have no formal background on type theory or logic. So much of the 15 months was also spent on learning the underlying concepts, mostly on my free time, and I am quite happy to even produce _something_ on a topic I have only recently got into. I am sure people smarter or more familiar with the theory than me would produce more in less time.
josevalim··on Data evolution with set-theoretic types
> This kind of breaks my mental model of major version bumps.

If you want, you can reset the revisions in a major version, as you could rename all modules and change the behavior of all functions, but that's hardly a good idea. Revisions are not any different. If you give a revision a new meaning in a major version, it is going to be as confusing as giving a new implementation to a function: users upgrading will have to figure out why something has subtly changed, instead of a clear error that something has gone away.

> The expectation here would be that a struct revision would be a minor version bump, correct?

We could make either minor and major versions (as described by semver) work. For example, if we want to allow new revisions to be minor versions, we could make it so every time you install a dependency, we automatically lock all structs it provides. This way, if a new version is out, you have to explicitly upgrade any new revision too.

Of course, you could also release a new major version of the library once you introduce a new revision and _that's fine_. The goal is not to avoid major versions of the library that defines a struct, the goal is to avoid forcing its dependents to release major versions, which has a cascading effect in the ecosystem. Putting in Elixir terms, I want to be able to release Phoenix v2 without forcing LiveView to immediately become v2. LiveView should be able to stay on v1.x and say it supports both Phoenix v1 and v2 at once. But in most typed languages, if you change a field definition, it is game over.

The guarantees you need to provide are not that many: as long as two revisions overlap at one point in time, you can offer a better upgrading experience to everyone, instead of assuming *all code must be updated at once*.

Thanks for the convo!

← PreviousPage 2 of 15Next →