app
Google Antigravity
Public Made by Adomby adom
Google Antigravity in Adom Hydrogen: the editor extension, the agy CLI and a dock dashboard that installs both into your container.
← Commit history
0.1.8: the sign-in LED and single-copy CLI install that 0.1.7 was missing
4 files changed
+66−9
adom_antigravity.py+59−4@@ -21,7 +21,7 @@ from pathlib import Path from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer ROOT = Path(__file__).resolve().parent-VERSION = '0.1.7'+VERSION = '0.1.8' EXT_ID = 'Google.google-antigravity' CLI_INSTALL = 'https://antigravity.google/cli/install.sh' EXT_DIRS = [Path.home() / '.local/share/code-server/extensions', Path.home() / '.vscode-server/extensions']@@ -58,6 +58,39 @@ def extension_state(): return {'id': EXT_ID, 'installed': bool(hits), 'versions': versions, 'paths': hits} +def _token_state(path):+ """An Antigravity OAuth token file: {token:{access_token,refresh_token,expiry}, id_token}.+ Signed in = a refresh token is there. The email comes from the id_token's payload."""+ try:+ d = json.loads(Path(path).read_text())+ except Exception:+ return {'signedIn': False, 'email': None}+ tok = d.get('token') or {}+ email = None+ try:+ import base64+ seg = d['id_token'].split('.')[1]+ seg += '=' * (-len(seg) % 4)+ email = json.loads(base64.urlsafe_b64decode(seg)).get('email')+ except Exception:+ pass+ return {'signedIn': bool(tok.get('refresh_token') or tok.get('access_token')), 'email': email, 'expiry': tok.get('expiry')}+++def signin_state():+ """Both sides of the sign-in. The extension's agy server keeps its Google login in+ ~/.gemini/jetski-standalone-oauth-token; the CLI keeps ~/.gemini/antigravity-cli/+ antigravity-oauth-token. Same OAuth client and JSON (VERIFIED 2026-09-20), and Hydrogen's+ sign-in check copies whichever exists to the missing side, so in a Hydrogen workspace one+ sign-in covers both. Never a live prompt: a 429 quota answer is not "signed out"."""+ g = Path.home() / '.gemini'+ ext = _token_state(g / 'jetski-standalone-oauth-token')+ cli = _token_state(g / 'antigravity-cli' / 'antigravity-oauth-token')+ return {'extension': ext, 'cli': cli, 'signedIn': ext['signedIn'] or cli['signedIn'],+ 'email': ext.get('email') or cli.get('email'),+ 'sharedByHydrogen': (Path.home() / '.adom' / 'hydrogen-control-url').exists()}++ def cli_state(): agy = shutil.which('agy') or (str(Path.home() / '.local/bin/agy') if (Path.home() / '.local/bin/agy').exists() else None) version = None@@ -70,7 +103,14 @@ def cli_state(): settings = json.loads((cfg / 'settings.json').read_text()) except Exception: pass+ ext_copy = Path.home() / '.gemini' / 'bin' / 'agy'+ real = Path(agy).resolve() if agy else None return {'installed': bool(agy), 'path': agy, 'version': version,+ # The VS Code extension downloads its own agy to ~/.gemini/bin. The PATH command+ # should be a link onto it, never a second 214 MB download (no-duplicates rule).+ 'extensionCopy': str(ext_copy) if ext_copy.exists() else None,+ 'linkedToExtensionCopy': bool(real and ext_copy.exists() and real == ext_copy.resolve()),+ 'duplicate': bool(real and ext_copy.exists() and real != ext_copy.resolve() and real.is_file()), 'configDir': str(cfg), 'configDirExists': cfg.exists(), 'modelProvider': settings.get('modelProvider'), 'geminiApiKeySet': bool(os.environ.get('GEMINI_API_KEY'))}@@ -159,10 +199,25 @@ def install_extension(): def install_cli():- code, out = sh(f'curl -fsSL {CLI_INSTALL} | bash', timeout=300)+ """One copy of agy, ever. The extension downloads its own to ~/.gemini/bin/agy; when it is+ there, ~/.local/bin/agy becomes a link onto it (the same rule Hydrogen's Manage AIs and+ hydrogen-bootstrap apply). The public installer runs only when no copy exists anywhere."""+ bindir = Path.home() / '.local/bin'+ bindir.mkdir(parents=True, exist_ok=True)+ link = bindir / 'agy'+ ext_copy = Path.home() / '.gemini' / 'bin' / 'agy'+ if ext_copy.exists() and os.access(ext_copy, os.X_OK):+ if link.is_symlink() or link.exists():+ link.unlink()+ link.symlink_to(ext_copy)+ code, out = 0, f'linked {link} -> {ext_copy} (the copy the Antigravity extension downloaded; nothing downloaded again)'+ else:+ code, out = sh(f'curl -fsSL {CLI_INSTALL} | bash -s -- -d "{bindir}"', timeout=300) st = cli_state()- return {'ok': st['installed'], 'exit': code, 'output': out[-1500:], 'cli': st,- 'next': 'Run `agy` in a terminal tab to sign in: it prints a Google sign-in link when no browser can open. For headless use set GEMINI_API_KEY and modelProvider=gemini in ~/.gemini/antigravity-cli/settings.json.' if st['installed'] else 'The installer did not leave ~/.local/bin/agy; the output above says why.'}+ si = signin_state()+ nxt = ('Signed in as %s; the CLI shares the extension\'s sign-in.' % si['email']) if si['signedIn'] else 'Sign in inside the Antigravity side bar (Continue with Google); in a Hydrogen workspace the CLI picks that sign-in up on its own. Or run `agy` in a terminal and paste the code it asks for.'+ return {'ok': st['installed'], 'exit': code, 'output': out[-1500:], 'cli': st, 'signin': si,+ 'next': nxt if st['installed'] else 'The installer did not leave ~/.local/bin/agy; the output above says why.'} def vscode_command(command, args=None, timeout=20):
dashboard/index.html+5−3@@ -15,13 +15,14 @@ dialog{width:min(900px,95vw);background:var(--surface);color:var(--text);border: <div class="leds" id="leds" role="status" aria-label="Antigravity status"> <span class="led-pill" data-state="" id="led-ext"><i class="dot"></i><b>Extension</b><span>checking</span></span> <span class="led-pill" data-state="" id="led-cli"><i class="dot"></i><b>CLI</b><span>checking</span></span>+ <span class="led-pill" data-state="" id="led-signin"><i class="dot"></i><b>Sign-in</b><span>checking</span></span> <span class="led-pill" data-state="" id="led-editor"><i class="dot"></i><b>Editor</b><span>checking</span></span> <span class="led-pill" data-state="" id="led-rt"><i class="dot"></i><b>Runtime</b><span>checking</span></span> </div> <h1>Try Google Antigravity, inside your Adom workspace.</h1> <p>Antigravity is Google's agent-first coding tool. This installs its VS Code extension into your Hydrogen editor and its <code>agy</code> command line into your container, so it sits next to Claude Code, Codex and Kimi. Nothing touches Windows or macOS itself.</p> <div class="grid">- <section class="card"><h2>1. The editor extension</h2><p>Puts the Antigravity side bar in your editor (its own icon on the activity bar). Sign in with your Google account inside that panel.</p>+ <section class="card"><h2>1. The editor extension</h2><p>Puts the Antigravity side bar in your editor (its own icon on the activity bar). Sign in with your Google account inside that panel; in a Hydrogen workspace that same sign-in covers the CLI.</p> <div class="row"><button class="primary" id="install-ext">Install the extension</button><button id="reload">Reload the editor</button></div> <div class="hint" id="ext-hint">From Open VSX (Google.google-antigravity). A fresh install needs one editor reload.</div></section> <section class="card"><h2>2. The command line</h2><p>The <code>agy</code> CLI runs Antigravity's agent in a terminal, the way Claude and Codex have their TUIs.</p>@@ -43,13 +44,14 @@ const panel=AdomNewbiePanel.mount({mount:'#newbie',app:'antigravity',ai:'antigra function led(id,state,text){const e=$(id);e.dataset.state=state;e.querySelector('span').textContent=text} function render(s){$('#machine').textContent=(s.runtime==='wsl2'?'WSL2':s.runtime==='lima'?'Lima':'Linux')+' · '+s.container.hostname; led('#led-ext',s.extension.installed?'ok':'bad',s.extension.installed?('installed '+(s.extension.versions[0]||'')):'not installed');- led('#led-cli',s.cli.installed?'ok':'bad',s.cli.installed?(s.cli.version||'installed'):'not installed');+ led('#led-cli',s.cli.installed?(s.cli.duplicate?'busy':'ok'):'bad',s.cli.installed?((s.cli.version||'installed')+(s.cli.linkedToExtensionCopy?' · the extension\'s copy':s.cli.duplicate?' · second copy, click Link the CLI':'')):'not installed');+ led('#led-signin',s.signin&&s.signin.signedIn?'ok':'bad',s.signin&&s.signin.signedIn?('signed in'+(s.signin.email?' as '+s.signin.email:'')+(s.signin.extension.signedIn&&s.signin.cli.signedIn?' · extension + CLI':s.signin.extension.signedIn?' · extension':' · CLI')):'not signed in'); led('#led-editor',s.editor.reachable?'ok':'busy',s.editor.reachable?('adom-vscode '+s.editor.adomVscode):'editor not reachable'); led('#led-rt','ok',s.runtime==='wsl2'?'WSL2 container':s.runtime==='lima'?'Lima container':'Linux container'); $('#open').disabled=!s.extension.installed;$('#open').title=s.panelWorks?'Opens the Antigravity side bar in the editor':(s.hub&&s.hub.up?'This editor path-proxies ports (panel blank): opens Antigravity\'s UI as a tab':'Install the extension and reload the editor first'); $('#open-hint').textContent=s.panelWorks?'The side bar renders here (Hydrogen serves forwarded ports as <port>.localhost). Ctrl+Shift+L starts a new conversation; Ctrl+L adds a selection.':'This editor still path-proxies ports, so the side-bar panel is blank; Open Antigravity shows the same UI as a tab. Hydrogen 1.0.224+ fixes the panel.'; $('#install-ext').textContent=s.extension.installed?'Reinstall / update the extension':'Install the extension';- $('#install-cli').textContent=s.cli.installed?'Reinstall the CLI':'Install the CLI';window.__ag=s}+ $('#install-cli').textContent=s.cli.installed?(s.cli.duplicate?'Link the CLI to the extension\'s copy':'Relink the CLI'):(s.cli.extensionCopy?'Link the CLI to the extension\'s copy':'Install the CLI');window.__ag=s} async function refresh(){try{const r=await fetch('/api/status');render(await r.json())}catch(e){toast('Status unavailable: '+e.message,'err')}} async function post(path,body,btn,busyText){const old=btn?btn.textContent:'';if(btn){btn.disabled=true;btn.textContent=busyText||'Working…'}try{const r=await fetch(path,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body||{})});const j=await r.json();if(j.ok===false)toast(j.error||j.output||'failed','err');else toast(j.next||j.note||'Done','ok');await refresh();return j}catch(e){toast(e.message,'err')}finally{if(btn){btn.disabled=false;btn.textContent=old}}} $('#install-ext').onclick=e=>post('/api/install-extension',{},e.currentTarget,'Installing the extension…');
package.json+1−1@@ -4,7 +4,7 @@ "type": "app", "title": "Google Antigravity", "brief": "Google Antigravity in Adom Hydrogen: the editor extension, the agy CLI and a dock dashboard that installs both into your container.",- "version": "0.1.7",+ "version": "0.1.8", "description": "Try Google Antigravity inside your Adom workspace. The dock dashboard installs the Google Antigravity VS Code extension into Hydrogen's editor and the agy command line into your WSL2 or Lima container, opens the panel, and reports what is installed and signed in.", "org": "adom", "needs_sudo": false,
page.json+1−1@@ -4,7 +4,7 @@ "type": "app", "title": "Google Antigravity", "brief": "Google Antigravity in Adom Hydrogen: the editor extension, the agy CLI and a dock dashboard that installs both into your container.",- "version": "0.1.7",+ "version": "0.1.8", "hero": { "type": "image", "path": "screenshots/hero.png"