From e3e94118193ebc4b7367646b0a54f0c8f2fd3928 Mon Sep 17 00:00:00 2001
From: AyhamBD
Date: Sat, 2 May 2026 19:16:04 +0300
Subject: [PATCH 1/3] feat: add VS Code and Antigravity MCP host setup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Both register through the existing agentWiring registry, so cmd_setup,
cmd_doctor, and cmd_uninstall pick them up without changes.
- VS Code: writes /Code/User/mcp.json under the "servers"
top-level key (the only host using MCP-spec-native naming rather than
"mcpServers"). Generalized mergeJSONMCPServer into mergeJSONMCPServerAt
to parameterize the key; original wrapper is byte-identical for the
other hosts.
- Antigravity: writes ~/.gemini/antigravity/mcp_config.json under
"mcpServers". The helper now also tolerates zero-byte stub config
files Antigravity creates on first install (caught against a real
install — json.Unmarshal of empty bytes errored).
- Brand colors in setup output: VS Code blue (#007ACC) and a
per-character rainbow gradient for Antigravity matching its product
mark.
- README/site/AGENTS.md/npm: enumerated the two new hosts in the
supported-host list. Antigravity uses Google's official press-kit
PNG, committed to site/antigravity-mark.png.
Co-Authored-By: Claude Opus 4.7
---
AGENTS.md | 3 +-
README.md | 2 +
cmd/clawdchan/agents.go | 13 ++-
cmd/clawdchan/colors.go | 75 ++++++++++++++-
cmd/clawdchan/setup_agent_antigravity.go | 106 +++++++++++++++++++++
cmd/clawdchan/setup_agent_vscode.go | 112 +++++++++++++++++++++++
cmd/clawdchan/setup_agents_test.go | 92 +++++++++++++++++++
cmd/clawdchan/setup_helpers.go | 31 ++++---
npm/README.md | 2 +-
site/antigravity-mark.png | Bin 0 -> 16849 bytes
site/index.html | 2 +
11 files changed, 418 insertions(+), 20 deletions(-)
create mode 100644 cmd/clawdchan/setup_agent_antigravity.go
create mode 100644 cmd/clawdchan/setup_agent_vscode.go
create mode 100644 site/antigravity-mark.png
diff --git a/AGENTS.md b/AGENTS.md
index 595b63e..d89097f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -35,7 +35,8 @@ and you **must** pause there — do not bypass prompts or run with
it themselves** — you should not pipe input into it.
Up front the user picks which MCP hosts to wire: Claude Code,
- Gemini CLI, Codex CLI, GitHub Copilot CLI, Cursor, or none.
+ Gemini CLI, Codex CLI, GitHub Copilot CLI, Cursor, VS Code,
+ Antigravity, or none.
OpenClaw is a separate yes/no step later in setup. If Claude Code is
selected, there are two scope decisions that only the user can make:
diff --git a/README.md b/README.md
index b5a3bfd..afcd114 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,8 @@
+
+
diff --git a/cmd/clawdchan/agents.go b/cmd/clawdchan/agents.go
index a0728dd..5d316b9 100644
--- a/cmd/clawdchan/agents.go
+++ b/cmd/clawdchan/agents.go
@@ -58,6 +58,8 @@ func allAgents() []*agentWiring {
codexAgent(),
copilotAgent(),
cursorAgent(),
+ vscodeAgent(),
+ antigravityAgent(),
}
}
@@ -99,15 +101,18 @@ func describeScopeFlag(a *agentWiring, scope string) string {
}
// mcpScopeChoices returns the MCP-registration scope names the agent
-// supports. Gemini and CC support user+project; Codex and Copilot are
-// user-only (per their upstream docs).
+// supports. Gemini and CC support user+project; the rest are user-only
+// (per their upstream docs).
func mcpScopeChoices(a *agentWiring) []string {
switch a.key {
case "cc", "gemini":
return []string{"user", "project"}
default:
- // Codex, Copilot, and Cursor are user-scope only. Cursor specifically
- // ignores project-level .cursor/mcp.json — only ~/.cursor/mcp.json loads.
+ // Codex, Copilot, Cursor, VS Code, and Antigravity are user-scope only.
+ // Cursor specifically ignores project-level .cursor/mcp.json — only
+ // ~/.cursor/mcp.json loads. VS Code and Antigravity also support a
+ // workspace file (.vscode/mcp.json, etc.) but registering at user
+ // scope means a single setup run covers every project the user opens.
return []string{"user"}
}
}
diff --git a/cmd/clawdchan/colors.go b/cmd/clawdchan/colors.go
index 0591768..d1a4691 100644
--- a/cmd/clawdchan/colors.go
+++ b/cmd/clawdchan/colors.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"strconv"
+ "strings"
"github.com/mattn/go-isatty"
)
@@ -106,10 +107,27 @@ const (
// documented for the in-tree OpenClaw host. Change when we adopt
// a real brand color.
openclawRed = "#E34234"
+ // vscodeBlue is the published "VS Code Blue" used in the product
+ // icon. Source: https://code.visualstudio.com/brand
+ vscodeBlue = "#007ACC"
)
-// agentColor returns the brand hex for an agent key ("cc", "gemini",
-// "codex", "copilot", "openclaw"). Returns "" for unknown keys.
+// antigravityGradient is the per-character color sweep used for
+// Google Antigravity. Antigravity's brand identity is a gradient
+// (pink → purple → blue → cyan → mint), not a single hex; rendering
+// it as an interpolated sweep across the display name is the
+// closest the terminal can get to the actual product mark.
+var antigravityGradient = []string{
+ "#FF5A8A", // rose
+ "#A155F0", // purple
+ "#5B7FFF", // blue
+ "#00C8FF", // cyan
+ "#34F5C5", // mint
+}
+
+// agentColor returns the brand hex for an agent key. Returns "" for
+// unknown keys, or for keys whose brand identity is a gradient rather
+// than a single hex (Antigravity — see antigravityGradient).
func agentColor(key string) string {
switch key {
case "cc":
@@ -122,17 +140,23 @@ func agentColor(key string) string {
return copilotPurple
case "openclaw":
return openclawRed
+ case "vscode":
+ return vscodeBlue
}
return ""
}
// agentStyle wraps s in bold + the agent's brand color, using 24-bit
// ANSI truecolor. Falls back to plain bold when color is disabled or
-// the key is unknown.
+// the key is unknown. Antigravity is a gradient, not a single color,
+// so it routes through agentGradient.
func agentStyle(key, s string) string {
if !colorEnabled {
return s
}
+ if key == "antigravity" {
+ return agentGradient(s, antigravityGradient)
+ }
h := agentColor(key)
if h == "" {
return bold(s)
@@ -144,6 +168,51 @@ func agentStyle(key, s string) string {
return fmt.Sprintf("\x1b[1;38;2;%d;%d;%dm%s\x1b[0m", r, g, b, s)
}
+// agentGradient renders s with a per-character color sweep across the
+// supplied hex stops, linearly interpolated in RGB. Bold attribute is
+// applied across the whole run so the gradient still reads as a label.
+// Returns plain s when color is disabled, falls back to plain bold on
+// malformed stops or empty input.
+func agentGradient(s string, stops []string) string {
+ if !colorEnabled || len(stops) < 2 {
+ return bold(s)
+ }
+ type rgb struct{ r, g, b int }
+ pal := make([]rgb, 0, len(stops))
+ for _, h := range stops {
+ r, g, b, ok := parseHex(h)
+ if !ok {
+ return bold(s)
+ }
+ pal = append(pal, rgb{r, g, b})
+ }
+ runes := []rune(s)
+ if len(runes) == 0 {
+ return s
+ }
+ var out strings.Builder
+ out.WriteString("\x1b[1m")
+ for i, ch := range runes {
+ pos := 0.0
+ if len(runes) > 1 {
+ pos = float64(i) / float64(len(runes)-1)
+ }
+ seg := pos * float64(len(pal)-1)
+ a := int(seg)
+ b := a + 1
+ if b >= len(pal) {
+ b = len(pal) - 1
+ }
+ t := seg - float64(a)
+ r := pal[a].r + int(float64(pal[b].r-pal[a].r)*t)
+ g := pal[a].g + int(float64(pal[b].g-pal[a].g)*t)
+ bl := pal[a].b + int(float64(pal[b].b-pal[a].b)*t)
+ fmt.Fprintf(&out, "\x1b[38;2;%d;%d;%dm%c", r, g, bl, ch)
+ }
+ out.WriteString("\x1b[0m")
+ return out.String()
+}
+
// parseHex parses a "#RRGGBB" string into 0..255 components.
func parseHex(h string) (r, g, b int, ok bool) {
if len(h) != 7 || h[0] != '#' {
diff --git a/cmd/clawdchan/setup_agent_antigravity.go b/cmd/clawdchan/setup_agent_antigravity.go
new file mode 100644
index 0000000..f25bed5
--- /dev/null
+++ b/cmd/clawdchan/setup_agent_antigravity.go
@@ -0,0 +1,106 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// antigravityAgent wires the Google Antigravity host. Antigravity is a
+// VS Code-derived editor in Google's Gemini ecosystem; its MCP config
+// lives under the parent ~/.gemini directory, not its own home, which
+// is why the path is ~/.gemini/antigravity/mcp_config.json on every
+// platform. The schema reuses the "mcpServers" convention shared with
+// Cursor, Gemini CLI, and GitHub Copilot CLI.
+//
+// User-scope only — Antigravity's documented entry point ("Manage MCP
+// Servers" → "View raw config") opens a single file, with no project
+// scope mentioned in the upstream docs.
+//
+// Reference: https://antigravity.google (Editor → MCP Integration).
+func antigravityAgent() *agentWiring {
+ return &agentWiring{
+ key: "antigravity",
+ flagName: "antigravity",
+ displayName: "Antigravity",
+ defaultOn: false,
+ scopeFlags: []string{"mcp"},
+ setup: setupAntigravity,
+ doctorReport: doctorAntigravity,
+ uninstallHints: uninstallHintsAntigravity,
+ }
+}
+
+// antigravityUserMCPPath returns the user-scope mcp_config.json path
+// for Antigravity. Layout matches the docs verbatim on every platform:
+// ~/.gemini/antigravity/mcp_config.json.
+func antigravityUserMCPPath() (string, error) {
+ home, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(home, ".gemini", "antigravity", "mcp_config.json"), nil
+}
+
+func setupAntigravity(yes bool, scopes map[string]string) error {
+ scope := strings.ToLower(strings.TrimSpace(scopes["mcp"]))
+ if scope == "" && (yes || !stdinIsTTY()) {
+ scope = "user"
+ }
+ if scope == "" {
+ fmt.Println(" MCP scope " + dim("(~/.gemini/antigravity/mcp_config.json — user only)") + ":")
+ fmt.Printf(" %s user %s\n", cyan("[1]"), green("(recommended)"))
+ fmt.Printf(" %s skip\n", cyan("[2]"))
+ switch promptChoice(" Choice [1]: ", 1, 2) {
+ case 2:
+ scope = "skip"
+ default:
+ scope = "user"
+ }
+ }
+
+ switch scope {
+ case "user":
+ mcpBin, err := requireMCPBinary()
+ if err != nil {
+ return err
+ }
+ path, err := antigravityUserMCPPath()
+ if err != nil {
+ return err
+ }
+ _, err = mergeJSONMCPServer(path, map[string]any{
+ "command": mcpBin,
+ }, "(user)")
+ return err
+ case "skip":
+ fmt.Printf(" %s MCP %s %s\n", okTag(), dim("→"), dim("skipped"))
+ return nil
+ default:
+ return fmt.Errorf("unknown -antigravity-mcp-scope %q (use user|skip)", scope)
+ }
+}
+
+func doctorAntigravity() []string {
+ path, err := antigravityUserMCPPath()
+ if err != nil {
+ return nil
+ }
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return nil
+ }
+ if strings.Contains(string(data), `"clawdchan"`) {
+ return []string{"Antigravity: MCP registered (user scope, " + path + ")"}
+ }
+ return nil
+}
+
+func uninstallHintsAntigravity() []string {
+ return []string{
+ "If you wired Antigravity, remove the clawdchan entry from:",
+ " ~/.gemini/antigravity/mcp_config.json",
+ "Delete the \"clawdchan\" key under the \"mcpServers\" object.",
+ }
+}
diff --git a/cmd/clawdchan/setup_agent_vscode.go b/cmd/clawdchan/setup_agent_vscode.go
new file mode 100644
index 0000000..3d295ef
--- /dev/null
+++ b/cmd/clawdchan/setup_agent_vscode.go
@@ -0,0 +1,112 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// vscodeAgent is the Visual Studio Code wiring. VS Code 1.102+ supports
+// MCP servers natively. User-scope config lives at
+// `/Code/User/mcp.json` — the same User profile dir that
+// holds settings.json/keybindings.json — and uses a top-level "servers"
+// key rather than the "mcpServers" convention shared by the other hosts.
+//
+// We register at user scope only. Workspace `.vscode/mcp.json` is also
+// supported by VS Code, but matching the Cursor/Codex/Copilot pattern
+// keeps the setup flow consistent and means a single registration works
+// across every project the user opens.
+//
+// Reference: https://code.visualstudio.com/docs/copilot/customization/mcp-servers
+func vscodeAgent() *agentWiring {
+ return &agentWiring{
+ key: "vscode",
+ flagName: "vscode",
+ displayName: "VS Code",
+ defaultOn: false,
+ scopeFlags: []string{"mcp"},
+ setup: setupVSCode,
+ doctorReport: doctorVSCode,
+ uninstallHints: uninstallHintsVSCode,
+ }
+}
+
+// vscodeUserMCPPath returns the user-scope mcp.json path for VS Code
+// Stable. The User folder under the OS-specific config dir is where VS
+// Code stores per-user settings.json and keybindings.json; mcp.json
+// lives alongside them.
+func vscodeUserMCPPath() (string, error) {
+ cfg, err := os.UserConfigDir()
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(cfg, "Code", "User", "mcp.json"), nil
+}
+
+func setupVSCode(yes bool, scopes map[string]string) error {
+ scope := strings.ToLower(strings.TrimSpace(scopes["mcp"]))
+ if scope == "" && (yes || !stdinIsTTY()) {
+ scope = "user"
+ }
+ if scope == "" {
+ fmt.Println(" MCP scope " + dim("(VS Code user profile — Code/User/mcp.json)") + ":")
+ fmt.Printf(" %s user %s\n", cyan("[1]"), green("(recommended)"))
+ fmt.Printf(" %s skip\n", cyan("[2]"))
+ switch promptChoice(" Choice [1]: ", 1, 2) {
+ case 2:
+ scope = "skip"
+ default:
+ scope = "user"
+ }
+ }
+
+ switch scope {
+ case "user":
+ mcpBin, err := requireMCPBinary()
+ if err != nil {
+ return err
+ }
+ path, err := vscodeUserMCPPath()
+ if err != nil {
+ return err
+ }
+ if _, err := mergeJSONMCPServerAt(path, "servers", map[string]any{
+ "command": mcpBin,
+ }, "(user)"); err != nil {
+ return err
+ }
+ fmt.Printf(" %s Reload VS Code %s to pick up the new server.\n",
+ warnTag(), dim("(Command Palette → \"Developer: Reload Window\")"))
+ return nil
+ case "skip":
+ fmt.Printf(" %s MCP %s %s\n", okTag(), dim("→"), dim("skipped"))
+ return nil
+ default:
+ return fmt.Errorf("unknown -vscode-mcp-scope %q (use user|skip)", scope)
+ }
+}
+
+func doctorVSCode() []string {
+ path, err := vscodeUserMCPPath()
+ if err != nil {
+ return nil
+ }
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return nil
+ }
+ if strings.Contains(string(data), `"clawdchan"`) {
+ return []string{"VS Code: MCP registered (user scope, " + path + ")"}
+ }
+ return nil
+}
+
+func uninstallHintsVSCode() []string {
+ return []string{
+ "If you wired VS Code, remove the clawdchan entry from the user mcp.json:",
+ " Command Palette → \"MCP: Open User Configuration\"",
+ " (or edit the file at /Code/User/mcp.json)",
+ "Delete the \"clawdchan\" key under the \"servers\" object.",
+ }
+}
diff --git a/cmd/clawdchan/setup_agents_test.go b/cmd/clawdchan/setup_agents_test.go
index e323f77..6dee994 100644
--- a/cmd/clawdchan/setup_agents_test.go
+++ b/cmd/clawdchan/setup_agents_test.go
@@ -201,6 +201,98 @@ key = "y"
}
}
+// TestMergeJSONMCPServerAt_EmptyFile guards against a real install
+// case: Antigravity (and likely others) create a zero-byte stub
+// mcp_config.json on first run. json.Unmarshal of empty bytes errors
+// with "unexpected end of JSON input"; the helper has to treat
+// zero-length files as if they were "{}".
+func TestMergeJSONMCPServerAt_EmptyFile(t *testing.T) {
+ dir := t.TempDir()
+ path := filepath.Join(dir, "mcp_config.json")
+ if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := mergeJSONMCPServer(path, map[string]any{
+ "command": "/bin/clawdchan-mcp",
+ }, "(user)"); err != nil {
+ t.Fatalf("mergeJSONMCPServer on empty file: %v", err)
+ }
+ data, _ := os.ReadFile(path)
+ var obj map[string]any
+ if err := json.Unmarshal(data, &obj); err != nil {
+ t.Fatalf("result not valid JSON: %v\n%s", err, string(data))
+ }
+ servers, _ := obj["mcpServers"].(map[string]any)
+ if _, ok := servers["clawdchan"]; !ok {
+ t.Errorf("clawdchan entry missing: %s", string(data))
+ }
+}
+
+// TestMergeJSONMCPServerAt_VSCodeKey verifies that VS Code's "servers"
+// top-level key is honored end-to-end: the entry lands under "servers",
+// the wrong key "mcpServers" is NOT created as a sibling, and any
+// pre-existing "servers" siblings survive.
+func TestMergeJSONMCPServerAt_VSCodeKey(t *testing.T) {
+ dir := t.TempDir()
+ path := filepath.Join(dir, "mcp.json")
+ existing := `{"servers":{"playwright":{"command":"npx","args":["-y","@microsoft/mcp-server-playwright"]}}}`
+ if err := os.WriteFile(path, []byte(existing), 0o644); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := mergeJSONMCPServerAt(path, "servers", map[string]any{
+ "command": "/bin/clawdchan-mcp",
+ }, "(user)"); err != nil {
+ t.Fatalf("mergeJSONMCPServerAt: %v", err)
+ }
+ data, _ := os.ReadFile(path)
+ var obj map[string]any
+ if err := json.Unmarshal(data, &obj); err != nil {
+ t.Fatalf("unmarshal: %v", err)
+ }
+ if _, wrong := obj["mcpServers"]; wrong {
+ t.Errorf("must not create mcpServers when topKey is servers: %s", string(data))
+ }
+ servers, ok := obj["servers"].(map[string]any)
+ if !ok {
+ t.Fatalf("servers missing: %s", string(data))
+ }
+ if _, ok := servers["playwright"]; !ok {
+ t.Errorf("sibling 'playwright' dropped")
+ }
+ entry, ok := servers["clawdchan"].(map[string]any)
+ if !ok {
+ t.Fatalf("no clawdchan entry: %s", string(data))
+ }
+ if entry["command"] != "/bin/clawdchan-mcp" {
+ t.Errorf("command=%v", entry["command"])
+ }
+}
+
+// TestVSCodeUserMCPPath_Layout pins the mcp.json path under the OS
+// config dir's Code/User folder — the location VS Code uses for
+// user-profile settings.
+func TestVSCodeUserMCPPath_Layout(t *testing.T) {
+ got, err := vscodeUserMCPPath()
+ if err != nil {
+ t.Fatalf("vscodeUserMCPPath: %v", err)
+ }
+ if !strings.HasSuffix(filepath.ToSlash(got), "Code/User/mcp.json") {
+ t.Errorf("path = %q, want suffix Code/User/mcp.json", got)
+ }
+}
+
+// TestAntigravityUserMCPPath_Layout pins the gemini-rooted layout
+// documented by Antigravity (.gemini/antigravity/mcp_config.json).
+func TestAntigravityUserMCPPath_Layout(t *testing.T) {
+ got, err := antigravityUserMCPPath()
+ if err != nil {
+ t.Fatalf("antigravityUserMCPPath: %v", err)
+ }
+ if !strings.HasSuffix(filepath.ToSlash(got), ".gemini/antigravity/mcp_config.json") {
+ t.Errorf("path = %q, want suffix .gemini/antigravity/mcp_config.json", got)
+ }
+}
+
// TestAgentRegistryUnique guards against copy-paste mistakes where two
// agents share a flag name — which would silently break CLI parsing.
func TestAgentRegistryUnique(t *testing.T) {
diff --git a/cmd/clawdchan/setup_helpers.go b/cmd/clawdchan/setup_helpers.go
index 7395674..e4e2715 100644
--- a/cmd/clawdchan/setup_helpers.go
+++ b/cmd/clawdchan/setup_helpers.go
@@ -28,17 +28,26 @@ func requireMCPBinary() (string, error) {
// sibling field. Creates the file (and its parent dir) if missing.
//
// Used by hosts whose config format is a plain JSON object keyed by
-// mcpServers (Gemini CLI, GitHub Copilot CLI, Cursor). Returns whether
-// the clawdchan entry was newly added (true) or updated in place
-// (false). The logSuffix is the parenthetical shown at the end of the
-// success line, e.g. "(trust=true)" for Gemini or `(tools=["*"])` for
-// Copilot.
+// mcpServers (Gemini CLI, GitHub Copilot CLI, Cursor, Antigravity).
+// Returns whether the clawdchan entry was newly added (true) or
+// updated in place (false). The logSuffix is the parenthetical shown
+// at the end of the success line, e.g. "(trust=true)" for Gemini or
+// `(tools=["*"])` for Copilot.
func mergeJSONMCPServer(path string, entry map[string]any, logSuffix string) (bool, error) {
+ return mergeJSONMCPServerAt(path, "mcpServers", entry, logSuffix)
+}
+
+// mergeJSONMCPServerAt is the general form. VS Code is the one host
+// that nests its servers under the top-level "servers" key (matching
+// the MCP spec's native naming) instead of "mcpServers".
+func mergeJSONMCPServerAt(path, topKey string, entry map[string]any, logSuffix string) (bool, error) {
data, err := os.ReadFile(path)
- if err != nil {
- if !os.IsNotExist(err) {
- return false, err
- }
+ if err != nil && !os.IsNotExist(err) {
+ return false, err
+ }
+ // Missing file and empty-stub file (some hosts — e.g. Antigravity —
+ // create a zero-byte placeholder on first run) both decode as {}.
+ if len(data) == 0 {
data = []byte("{}")
}
var obj map[string]any
@@ -48,13 +57,13 @@ func mergeJSONMCPServer(path string, entry map[string]any, logSuffix string) (bo
if obj == nil {
obj = map[string]any{}
}
- servers, _ := obj["mcpServers"].(map[string]any)
+ servers, _ := obj[topKey].(map[string]any)
if servers == nil {
servers = map[string]any{}
}
_, existed := servers["clawdchan"]
servers["clawdchan"] = entry
- obj["mcpServers"] = servers
+ obj[topKey] = servers
out, err := json.MarshalIndent(obj, "", " ")
if err != nil {
diff --git a/npm/README.md b/npm/README.md
index ef8af7a..7d402b0 100644
--- a/npm/README.md
+++ b/npm/README.md
@@ -2,7 +2,7 @@
Let your Claude talk to mine — private channel between two (human, agent)
pairs. Today the setup flow wires Claude Code, Gemini CLI, Codex CLI,
-GitHub Copilot CLI, Cursor, and OpenClaw.
+GitHub Copilot CLI, Cursor, VS Code, Antigravity, and OpenClaw.
```sh
npm i -g clawdchan
diff --git a/site/antigravity-mark.png b/site/antigravity-mark.png
new file mode 100644
index 0000000000000000000000000000000000000000..c677e4f5f75ba256f0b1fc2e6e1f48d1ac23c0eb
GIT binary patch
literal 16849
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 your Claude talk to mine.
+
+
From 24854b1ef77b5c74b1ad7f3e4e4fc643e96fe106 Mon Sep 17 00:00:00 2001
From: Ayham Badarneh
Date: Sat, 2 May 2026 19:24:25 +0300
Subject: [PATCH 2/3] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
npm/README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/npm/README.md b/npm/README.md
index 7d402b0..cb4f3fc 100644
--- a/npm/README.md
+++ b/npm/README.md
@@ -2,7 +2,8 @@
Let your Claude talk to mine — private channel between two (human, agent)
pairs. Today the setup flow wires Claude Code, Gemini CLI, Codex CLI,
-GitHub Copilot CLI, Cursor, VS Code, Antigravity, and OpenClaw.
+GitHub Copilot CLI, Cursor, VS Code, and Antigravity, with an optional
+OpenClaw gateway step.
```sh
npm i -g clawdchan
From aeed2c65c57c2aa4c733b808c4dbc6cfeaabd657 Mon Sep 17 00:00:00 2001
From: Ayham Badarneh
Date: Sat, 2 May 2026 19:24:46 +0300
Subject: [PATCH 3/3] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
site/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/site/index.html b/site/index.html
index 73ccdc4..c31f114 100644
--- a/site/index.html
+++ b/site/index.html
@@ -54,7 +54,7 @@ Let your Claude talk to mine.
-
+