gas, the AAC Apps Script self-deploy that replaces clasp. Use to adopt it in a repo still on clasp or whose clasp credential died, to run a function on the script or promote PROD, or when a gas/deploy or gas/promote status is red.
Install
npx skillscat add surreptakos/claude-dotfiles/gas-deploy Install via the SkillsCat registry.
SKILL.md
gas-deploy
The package lives in claude-dotfiles/gas/: a vendored SelfDeploy.js, deploy/* refs on
GitHub, one time trigger. gas/README.md is the reference; read it once. gas --help lists every
command and flag. Every command below is node <claude-dotfiles>/gas/cli/gas.js …,
written gas … here.
Which job is this? Decide first
- A repo still on clasp, or its
CLASPRC_JSONjust died → Adopt (below). Adopting retires that
secret instead of re-minting it: the seven-day death belongs to the client, not the token. - A red
gas/deployorgas/promotestatus, or CI's wait timed out → Diagnose. - "Run X on the script" →
gas run owner/repo X '[args]' --wait 10. The result prints; the function
ran on HEAD. Latency is the tick (five minutes). - "Promote PROD now" → dispatch the repo's
promote.yml(freeze guard applies), orgas ref owner/repo deploy/prod <sha> --wait 20for a commitdeploy/testalready verified.
Adopt (once per repo)
gas whoami. No credential →gas login(in a cloud container:gas login --paste, hand the URL to
the owner, paste back the localhost URL).gas loginrather thanclasp login: the latter mints the
machine-wide credentialaac-google-accessguards, and is the wrong client for anything CI-shaped.gas init <repo> --script-id <id> --root-dir <dir>; editgas.json:include/exclude(mirror the
repo's.claspignore),prod.deploymentIdif there is a PROD,hooks.postDeployif the project has
something to check (write that function in the project: throw on a bad deploy, return a one-line
summary on a good one), andpreserve: init prefills it with every file HEAD holds that the repo
does not (hand-pushed, gitignored data files). Keep the ones the script needs; a deploy that would
delete an unlisted one refuses, by design.gas pull <id>and a CR-stripped diff againstrootDir
shows what else differs — a repo ahead of its script means the first push is a real release.gas vendor <repo>; commitgas.jsonand<rootDir>/SelfDeploy.js.- Manifest scopes:
script.external_request,script.scriptapp,drive,userinfo.email, a mail
scope. The AAC canonical block has them all. gas seed <scriptId> --repo owner/name --github-token-env GAS_PAT(the owner supplies the PAT once;
classicrepo, or fine-grained Contents read + Commit statuses write + Contents write for run comments).- Ask the owner to run
gasInstall()once in the editor — or, if the project already has a trigger
that runs HEAD, addgasEnsureTrigger_();to it and let the next run install the tick. Say which. - If HEAD has never carried the library:
gas push <scriptId> --dir <rootDir> --sha <commit>. - Copy
gas/templates/deploy.yml(andpromote.yml) into.github/workflows/, substitute the branch
and the test command. Delete the clasp workflows and theCLASPRC_JSONsecret's readers. Removetools/clasp-auth.jsand theclasp-authrelease gate from.claude/session.jsonif present. - Note in the repo's CLAUDE.md: the script deploys itself from
deploy/test;gas runreplacesclasp run;gas logs --project <gcp>replacesclasp logs. - Prove it: push a commit, then
gas status owner/repountildeploy/testshowssuccess, and
read the status description alongside the colour. Adopt is done when that status is green
for the pushed commit.
Diagnose
gas status owner/repo— the three refs and the latest status on each, with its description.gas logs --project gpt-sheets-access-475817 --minutes 60— the[gas]lines.--allfor everything.- No status at all after the wait → the tick trigger is not installed, or the seed was never ingested
([gas] no GAS_REPO propertyin the log), or the GitHub token cannot write statuses. could not be verified … bound to a versioned deployment→ the trigger was created from a web app.gasUninstall()thengasInstall()from the editor.Service invoked too many times for one day: urlfetch→ another project on the account spent the
allowance; the tick retries in five minutes and mails nothing. Find the spender (Cloud Logging shows
it) rather than waiting it out.Google token refresh failed … re-seed→ the refresh token was revoked (password change, explicit
revocation, six months unused).gas loginthengas seedagain.promote refused: … of 200 versions→ the owner deletes old versions in the editor's project history.
Hard rails
- The only secret this design puts in GitHub is
GAS_PAT. Google credentials stay out of the
repo and out of Actions, whichever client minted them. - The tick trigger is installed from the editor (
gasInstall()), so it runs HEAD. One created
from a versioned deployment's execution is thebound to a versioned deploymentfailure above. SelfDeploy.jsis edited at source —claude-dotfiles/gas/lib/SelfDeploy.js. Run its tests
(node --test gas/tests/*.test.js), bumpgas/VERSION, thengas vendorin each repo; the copy
in a repo is output.