Antigrav cli - #7
Conversation
- Add zsh wrapper function for agy to automatically add CWD/git root to trustedWorkspaces in settings.json - Add git clean filter (clean-trusted-workspaces) using jq to strip local workspace paths from settings.json before staging/committing - Add .gitattributes to apply the filter to settings.json - Clean up old static trustedWorkspaces from settings.json
There was a problem hiding this comment.
Code Review
This pull request adds the mcp-datadog script to serve as an MCP stdio transport, introduces Gemini/Antigravity CLI settings and skills (including humanizer and gh-cli documentation), and refactors install.sh and Zsh helpers for improved portability. The review feedback identifies several key areas for improvement: mcp-datadog needs robust error handling to prevent client hangs, proper home directory resolution, and clearer error messages; install.sh should avoid hardcoding 'master' as a fallback, include jq in its dependencies, and support non-interactive execution; the gowt Zsh function must be safer to prevent destroying branch history; and the gitconfig clean filter should handle null values gracefully.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (res.statusCode >= 200 && res.statusCode < 300) { | ||
| if (body.trim()) { | ||
| process.stdout.write(body.trim() + '\n'); | ||
| } | ||
| } else { | ||
| console.error(body); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| req.on('error', (e) => { | ||
| console.error(e.message); | ||
| }); |
There was a problem hiding this comment.
If the HTTPS request fails (e.g., due to a network error) or returns a non-2xx status code, the script logs the error to console.error but does not write anything to process.stdout. Since this script acts as an MCP stdio transport, failing to return a response to stdout will cause the calling client (such as Claude or Gemini) to hang indefinitely waiting for a response to its request ID. To prevent this, you should parse the request ID from the incoming line and write a valid JSON-RPC error response to stdout when a failure occurs.
if (res.statusCode >= 200 && res.statusCode < 300) {
if (body.trim()) {
process.stdout.write(body.trim() + '\n');
}
} else {
console.error(body);
try {
const reqId = JSON.parse(line).id;
if (reqId !== undefined) {
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: reqId, error: { code: -32603, message: 'Datadog API error: ' + res.statusCode } }) + '\n');
}
} catch (err) {}
}
});
});
req.on('error', (e) => {
console.error(e.message);
try {
const reqId = JSON.parse(line).id;
if (reqId !== undefined) {
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: reqId, error: { code: -32603, message: 'Network error: ' + e.message } }) + '\n');
}
} catch (err) {}
});
| git fetch origin | ||
| local remote_head | ||
| remote_head=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null) | ||
| local default_branch=${remote_head#refs/remotes/origin/} | ||
| default_branch=${default_branch:-main} | ||
| git reset --hard "origin/${default_branch}" |
There was a problem hiding this comment.
If the branch already exists on origin (e.g., a remote branch you want to work on), resetting it to origin/${default_branch} (usually origin/main or origin/master) will destroy the branch's history and overwrite it with the default branch. It is much safer to check if origin/${branch} exists and reset to it, only falling back to the default branch if it is a completely new branch.
git fetch origin
if git rev-parse --verify "origin/${branch}" >/dev/null 2>&1; then
git reset --hard "origin/${branch}"
else
local remote_head
remote_head=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null)
local default_branch=${remote_head#refs/remotes/origin/}
default_branch=${default_branch:-main}
git reset --hard "origin/${default_branch}"
fi
| const path = require('path'); | ||
| const readline = require('readline'); | ||
|
|
||
| const envPath = path.join(process.env.HOME, '.env'); |
| if (!apiKey || !appKey || !site) { | ||
| process.exit(1); | ||
| } |
There was a problem hiding this comment.
When the required environment variables (DD_API_KEY, DD_APP_KEY, or DD_SITE) are missing, the script exits silently with code 1. It is highly recommended to print a descriptive error message to console.error before exiting so that users or MCP clients can easily diagnose the configuration issue.
if (!apiKey || !appKey || !site) {
console.error('Error: Missing required environment variables. Please ensure DD_API_KEY, DD_APP_KEY, and DD_SITE are set.');
process.exit(1);
}
|
|
||
| DOT_FILES=$(git ls-tree '@{u}' | awk '{print $4}' | grep -Ev '(/|LICENSE|README|install.sh|shlibs|test.sh|.gitignore|.gitmodules|bashrc|^vim|vimrc|screenrc)') | ||
| # Check for upstream branch, but don't exit if it fails (first install might not have it) | ||
| UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo "master") |
There was a problem hiding this comment.
Defaulting to 'master' when there is no upstream branch can cause the installation to fail if the repository's default branch is 'main' (which is standard for modern repositories). It is safer to fall back to the current local branch name using git rev-parse --abbrev-ref HEAD before defaulting to 'main'.
| UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo "master") | |
| UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main") |
| DEB_DEPS="zip unzip curl exuberant-ctags wget tmux zsh zsh-common vim git xclip zlib1g zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \ | ||
| libncurses5-dev libssl-dev build-essential htop libffi-dev libffi7 xz-utils" |
There was a problem hiding this comment.
The newly added gitconfig clean filter and the agy Zsh function both rely on jq to parse and manipulate JSON settings. However, jq is not included in DEB_DEPS, which means Linux users on Debian/Ubuntu-based systems might not have jq installed, causing these features to fail. Please add jq to DEB_DEPS.
| DEB_DEPS="zip unzip curl exuberant-ctags wget tmux zsh zsh-common vim git xclip zlib1g zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \ | |
| libncurses5-dev libssl-dev build-essential htop libffi-dev libffi7 xz-utils" | |
| DEB_DEPS="zip unzip curl exuberant-ctags wget tmux zsh zsh-common vim git xclip zlib1g zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \ | |
| libncurses5-dev libssl-dev build-essential htop libffi-dev libffi7 xz-utils jq" |
| echo -n "File ${dst} already exists and is not a symlink. [B]ackup, [O]verwrite, [S]kip? (B/o/s) " | ||
| local action | ||
| read -n 1 -r action |
There was a problem hiding this comment.
When running the installer in a non-interactive environment (e.g., automated scripts, CI, or SSH provisioning), the read -n 1 -r action command will fail or hang because there is no TTY. It is safer to check if stdin is a terminal using [[ -t 0 ]] and default to backing up the file if it is non-interactive.
| echo -n "File ${dst} already exists and is not a symlink. [B]ackup, [O]verwrite, [S]kip? (B/o/s) " | |
| local action | |
| read -n 1 -r action | |
| local action="" | |
| if [[ -t 0 ]]; then | |
| echo -n "File ${dst} already exists and is not a symlink. [B]ackup, [O]verwrite, [S]kip? (B/o/s) " | |
| read -n 1 -r action | |
| echo | |
| else | |
| echo "Non-interactive shell detected. Defaulting to Backup for ${dst}." | |
| action="b" | |
| fi |
| syncmain = "!f() { CURRENT_BRANCH=$(git symbolic-ref --short HEAD); if [ \"$CURRENT_BRANCH\" = main ]; then echo 'Error: cannot run syncmain on main branch.' >&2; exit 1; fi; git checkout main && git pull origin main && git checkout \"$CURRENT_BRANCH\" && git rebase origin/main && git push origin \"$CURRENT_BRANCH\" --force-with-lease; }; f" | ||
|
|
||
| [filter "clean-trusted-workspaces"] | ||
| clean = "if command -v jq >/dev/null 2>&1; then jq --arg home \"$HOME\" '.trustedWorkspaces = [.trustedWorkspaces[] | select(. == ($home + \"/repos/jaybocc2/dotfiles\") or . == $home or (startswith($home + \"/repos/\") | not))]'; else cat; fi" |
There was a problem hiding this comment.
If trustedWorkspaces is missing or null in settings.json, jq will throw a 'cannot iterate over null' error and fail. Using the optional object identifier-index .trustedWorkspaces[]? instead of .trustedWorkspaces[] prevents this error and makes the clean filter more robust.
clean = "if command -v jq >/dev/null 2>&1; then jq --arg home \"$HOME\" '.trustedWorkspaces = [.trustedWorkspaces[]? | select(. == ($home + \"/repos/jaybocc2/dotfiles\") or . == $home or (startswith($home + \"/repos/\") | not))]'; else cat; fi"
| gh codespace logs | ||
|
|
||
| --tail 100 |
There was a problem hiding this comment.
| > | ||
| > None of this means the tools are useless. It means they are tools. They do not replace judgment, and they do not eliminate the need for tests. If you do not have tests, you cannot tell whether the suggestion is right. | ||
|
|
||
| **What makes the below so obviously AI generated?** |
There was a problem hiding this comment.
No description provided.