Repository: tidewave-ai/tidewave_phoenix
Pull request #75 (2025-05-13 20:25:53)

Split claude docs in claude code and claude desktop
A user on Discord got confused about instructions. Was following the docs for Claude, and thought that had to follow everything inside the previous Claude docs.

It seems people got confused about Claude Desktop and Claude Code being two different tools.

josevalim: I have added comments but I wonder if perhaps the best option is to add links and screenshots of the products, and also add a bit more docs.

Patch:
diff --git a/lib/tidewave/mcp/tools/fs.ex b/lib/tidewave/mcp/tools/fs.ex
index c02faf7..8888550 100644
--- a/lib/tidewave/mcp/tools/fs.ex
+++ b/lib/tidewave/mcp/tools/fs.ex
@@ -380,20 +380,23 @@ defmodule Tidewave.MCP.Tools.FS do
   defp maybe_apply_offset_and_count(content, 0, nil), do: content
 
   defp maybe_apply_offset_and_count(content, offset, count) do
-    splitter_and_joiner =
-      case Utils.detect_line_endings(content) do
-        :lf -> "\n"
-        :crlf -> "\r\n"
-      end
-
-    lines = String.split(content, splitter_and_joiner)
-
-    lines
+    content
+    |> lines(<<>>)
     |> Enum.drop(offset)
     |> take_all_or(count)
-    |> Enum.join(splitter_and_joiner)
+    |> IO.iodata_to_binary()
   end
 
+  # TODO: Use Code.lines/1 when we require Elixir v1.19+
+  defp lines(<<?\n, rest::binary>>, acc),
+    do: [<<acc::binary, ?\n>> | lines(rest, <<>>)]
+
+  defp lines(<<char, rest::binary>>, acc),
+    do: lines(rest, <<acc::binary, char>>)
+
+  defp lines(<<>>, acc),
+    do: [acc]
+
   defp take_all_or(list, nil), do: list
   defp take_all_or(list, count), do: Enum.take(list, count)
 
diff --git a/mix.exs b/mix.exs
index 55b417e..529118c 100644
--- a/mix.exs
+++ b/mix.exs
@@ -56,6 +56,7 @@ defmodule Tidewave.MixProject do
       extras: [
         "pages/installation.md",
         "pages/editors/mcp.md",
+        "pages/editors/claude_code.md",
         "pages/editors/claude.md",
         "pages/editors/cursor.md",
         "pages/editors/neovim.md",
diff --git a/pages/editors/claude.md b/pages/editors/claude.md
index 33d1d8e..d4b7fe1 100644
--- a/pages/editors/claude.md
+++ b/pages/editors/claude.md
@@ -1,8 +1,6 @@
-# Claude
+# Claude Desktop
 
-You can use Tidewave with Claude Desktop and Claude Code.
-
-## Claude Desktop
+> To use Tidewave with Claude Code, [see here](claude_code.md).
 
 To use Tidewave with Claude Desktop, you must first install
 a [`mcp-proxy`](../guides/mcp_proxy.md).
@@ -45,20 +43,3 @@ as Claude Desktop does not support any filesystem operation out of the box.
 If your application uses a SQL database, you can verify it all works
 by asking it to run `SELECT 1` as database query. If it fails,
 check out [our Troubleshooting guide](troubleshooting.md).
-
-## Claude Code
-
-Adding Tidewave to [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview)
-is straight-forward, just run:
-
-```shell
-$ claude mcp add --transport sse tidewave http://localhost:$PORT/tidewave/mcp
-```
-
-To use it with [the `mcp-proxy`](guides/mcp_proxy.md), run:
-
-```shell
-$ claude mcp add --transport stdio tidewave /path/to/mcp-proxy http://localhost:$PORT/tidewave/mcp
-```
-
-Where `$PORT` is the port your web application is running on. And you are good to go!
diff --git a/pages/editors/claude_code.md b/pages/editors/claude_code.md
new file mode 100644
index 0000000..24c68d6
--- /dev/null
+++ b/pages/editors/claude_code.md
@@ -0,0 +1,18 @@
+# Claude Code
+
+> To use Tidewave with Claude Desktop, [see here](claude.md).
+
+Adding Tidewave to [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview)
+is straight-forward, just run:
+
+```shell
+$ claude mcp add --transport sse tidewave http://localhost:$PORT/tidewave/mcp
+```
+
+To use it with [the `mcp-proxy`](guides/mcp_proxy.md), run:
+
+```shell
+$ claude mcp add --transport stdio tidewave /path/to/mcp-proxy http://localhost:$PORT/tidewave/mcp
+```
+
+Where `$PORT` is the port your web application is running on. And you are good to go!
diff --git a/pages/guides/mcp_proxy.md b/pages/guides/mcp_proxy.md
index ea115b4..ab05445 100644
--- a/pages/guides/mcp_proxy.md
+++ b/pages/guides/mcp_proxy.md
@@ -15,10 +15,13 @@ the `mcp-proxy` was installed at. It will be necessary
 in most scenarios in order to use Tidewave. Note on Windows
 the executable will also have the `.exe` extension.
 
-## Other proxies
+## Python-based proxy
 
-There are also other proxies available, for example [an implementation in Python](https://github.com/sparfenyuk/mcp-proxy),
-but it did not handle reconnects last time we tried. The Rust proxy is also simpler to install.
+An alternative MCP Proxy if the Rust version is not working as expected.
+Requires Python tooling on your machine. See [the installation instructions
+on GitHub](https://github.com/sparfenyuk/mcp-proxy).
 
-We also provided an [Elixir based proxy](https://github.com/tidewave-ai/mcp_proxy_elixir) in the past,
-but it is now deprecated as the Rust proxy is simpler to install (as it does not require Elixir).
+Once installation concludes, take note of the full path
+the `mcp-proxy` was installed at. It will be necessary
+in most scenarios in order to use Tidewave. Note on Windows
+the executable will also have the `.exe` extension.


Test patch:
diff --git a/test/mcp/tools/fs_test.exs b/test/mcp/tools/fs_test.exs
index b464a90..395705a 100644
--- a/test/mcp/tools/fs_test.exs
+++ b/test/mcp/tools/fs_test.exs
@@ -103,10 +103,10 @@ defmodule Tidewave.MCP.Tools.FSTest do
       content = Enum.map_join(1..1000, "\n", &to_string/1) <> "\nmore content\n"
       File.write!(file_path, content)
 
-      assert {:ok, "1\n2\n3\n4\n5\n6", _state, _metadata} =
+      assert {:ok, "1\n2\n3\n4\n5\n6\n", _state, _metadata} =
                FS.read_project_file(%{"path" => file_path, "count" => 6}, %{})
 
-      assert {:ok, "501\n502\n503\n504\n505", _state, _metadata} =
+      assert {:ok, "501\n502\n503\n504\n505\n", _state, _metadata} =
                FS.read_project_file(
                  %{"path" => file_path, "line_offset" => 500, "count" => 5},
                  %{}