Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
56914f3
feat: implement cli
jpoehnelt Mar 2, 2026
6725ac7
style: formatting
jpoehnelt Mar 2, 2026
cb525eb
fix: address comments
jpoehnelt Mar 2, 2026
5357fde
fix: address comments and release plan failure
jpoehnelt Mar 2, 2026
c0286c8
docs: readme add shared skill
jpoehnelt Mar 2, 2026
633707a
feat: Introduce lefthook for pre-commit/pre-push hooks, update pnpm d…
jpoehnelt Mar 2, 2026
6c5fdd1
feat: update README to mention AI agent skills
jpoehnelt Mar 2, 2026
93bc7c9
chore: Upgrade cargo-dist to v0.31.0, update CI workflows to use the …
jpoehnelt Mar 2, 2026
d56d09a
update smoketest and mask auth export
jpoehnelt Mar 2, 2026
949adfd
docs: add instructions for updating smoketest credentials
jpoehnelt Mar 2, 2026
8f626e7
docs: clarify authentication capabilities and precedence
jpoehnelt Mar 2, 2026
98b44f6
feat: add `export` to auth command validation and update README examp…
jpoehnelt Mar 2, 2026
95faafd
feat: Implement OS keyring-backed encrypted token storage for OAuth2 …
jpoehnelt Mar 2, 2026
a2ad641
ci: Remove unnecessary `contents: write` and `id-token: write` permis…
jpoehnelt Mar 2, 2026
79f963b
test: add `serial_test` dependency and apply `#[serial_test::serial]`…
jpoehnelt Mar 2, 2026
61c6506
ci: remove Tasks tasklists smoketest
jpoehnelt Mar 2, 2026
dcbdb2c
refactor: Use `serial_test` for test serialization and mark `std::env…
jpoehnelt Mar 2, 2026
a90795c
feat: retry and concurrent requests
jpoehnelt Mar 2, 2026
9413027
refactor: Replace custom RFC 3339 timestamp parsing with the `chrono`…
jpoehnelt Mar 2, 2026
9550727
feat: introduce `SetupContext` to manage shared state and implement i…
jpoehnelt Mar 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions .agent/skills/vhs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
description: Writing and editing VHS `.tape` files for terminal demo GIFs
---

# VHS Tape Files

[VHS](https://github.com/charmbracelet/vhs) records terminal sessions into GIFs/MP4s/WebMs from `.tape` scripts. Run with `vhs demo.tape`.

## Critical Syntax Rules

### Type command and inline directives

`Type`, `Sleep`, `Enter` are **separate directives on the same line**, delimited by the closing `"` of the `Type` string. The most common bug is forgetting to close the `Type` string, which causes `Sleep`/`Enter` to be typed literally into the terminal.

```
# ✅ CORRECT — closing " before Sleep
Type "echo hello" Sleep 300ms Enter

# ❌ WRONG — Sleep and Enter are typed as literal text
Type "echo hello Sleep 300ms Enter
```

### Type with @speed override

Override typing speed per-command with `@<time>` immediately after `Type` (no space):

```
Type@80ms '{"pageSize": 2}' Sleep 100ms
```

### Quoting

- Double quotes `"..."` are the standard Type delimiter
- Single quotes `'...'` also work and are useful when the typed content contains double quotes (e.g. JSON)
- Escape quotes inside strings with backticks: `` Type `VAR="value"` ``
- When building shell commands with nested quotes, split across multiple `Type` lines:

```
Type "gws drive files list --params '" Sleep 100ms
Type@80ms '{"pageSize": 2, "fields": "nextPageToken,files(id)"}' Sleep 100ms
Type "' --page-all" Sleep 300ms Enter
```

> **Pitfall**: Every `Type` line that is followed by `Sleep` or `Enter` on the same line MUST close its string first. Audit each line to ensure the quote is closed before any directive.

## Settings (top of file only)

Settings must appear before any non-setting command (except `Output`). `TypingSpeed` is the only setting that can be changed mid-tape.

```
Output demo.gif

Set Shell "bash"
Set FontSize 14
Set Width 1200
Set Height 1200
Set Theme "Catppuccin Mocha"
Set WindowBar Colorful
Set WindowBarSize 40
Set TypingSpeed 40ms
Set Padding 20
```

## Common Commands

| Command | Example | Notes |
|---|---|---|
| `Output` | `Output demo.gif` | `.gif`, `.mp4`, `.webm` |
| `Type` | `Type "ls -la"` | Type characters |
| `Type@<time>` | `Type@80ms "slow"` | Override typing speed |
| `Sleep` | `Sleep 2s`, `Sleep 300ms` | Pause recording |
| `Enter` | `Enter` | Press enter |
| `Hide` / `Show` | `Hide` ... `Show` | Hide setup commands |
| `Ctrl+<key>` | `Ctrl+C` | Key combos |
| `Tab`, `Space`, `Backspace` | `Tab 2` | Optional repeat count |
| `Up`, `Down`, `Left`, `Right` | `Up 3` | Arrow keys |
| `Wait` | `Wait /pattern/` | Wait for regex on screen |
| `Screenshot` | `Screenshot out.png` | Capture frame |
| `Env` | `Env FOO "bar"` | Set env var |
| `Source` | `Source other.tape` | Include another tape |
| `Require` | `Require jq` | Assert program exists |

## Hide/Show for Setup

Use `Hide`/`Show` to run setup commands (e.g. setting `$PATH`, clearing screen) without recording them:

```
Hide
Type "export PATH=$PWD/target/release:$PATH" Enter
Type "clear" Enter
Sleep 2s
Show
```

## Checklist When Editing Tape Files

1. **Every `Type` string must be closed** before `Sleep`/`Enter` on the same line
2. **Multi-line Type sequences** that build a single shell command: ensure the final line closes its string and includes `Enter`
3. **Sleep durations** after commands should be long enough for the command to finish (network calls may need 8s+)
4. **Settings go at the top** — only `TypingSpeed` can appear later
5. **Test locally** with `vhs <file>.tape` before committing
73 changes: 73 additions & 0 deletions .agent/workflows/verify-skills.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
description: Verify all skills/*/SKILL.md files against actual CLI output for accuracy
---

# Verify Skills

Ensure every `skills/*/SKILL.md` file is accurate and optimized for AI agent consumption.

## Steps

1. **List all skill files**

```bash
find skills -name SKILL.md | sort
```

2. **Get top-level help for every service**

// turbo
```bash
for svc in drive sheets gmail calendar admin admin-reports docs slides tasks people chat vault groupssettings reseller licensing apps-script; do
echo "=== $svc ==="
./target/debug/gws $svc --help 2>&1
echo
done
```

3. **Get sub-resource help for key services** (spot-check method names used in examples)

// turbo
```bash
./target/debug/gws drive files --help 2>&1
./target/debug/gws gmail users messages --help 2>&1
./target/debug/gws sheets spreadsheets --help 2>&1
./target/debug/gws sheets spreadsheets values --help 2>&1
./target/debug/gws calendar events --help 2>&1
./target/debug/gws people people --help 2>&1
./target/debug/gws chat spaces --help 2>&1
./target/debug/gws vault matters --help 2>&1
./target/debug/gws admin users --help 2>&1
./target/debug/gws tasks tasks --help 2>&1
```

4. **For each SKILL.md, verify the following against the CLI `--help` output:**

- [ ] **Resource names** match exactly (e.g., `files`, `spreadsheets`, `users`)
- [ ] **Method names** match exactly (e.g., `list`, `insert`, `batchUpdate`, `getContent`)
- [ ] **Nested resource paths** are correct (e.g., `spreadsheets values get`, not `values get`)
- [ ] **Alias** mentioned in the file matches `services.rs` (e.g., `gws script` for apps-script)
- [ ] **API version** in the header is correct
- [ ] **Example commands** use valid `--params` and `--json` flag syntax
- [ ] **No OAuth scopes section** — scopes should not be listed in skill files
- [ ] **Tips section** contains accurate, actionable advice

5. **Cross-check `shared/SKILL.md`** covers:

- [ ] `--fields` / field mask syntax
- [ ] CLI syntax (`--params`, `--json`, `--output`, `--upload`, `--page-all`, `--page-limit`, `--page-delay`)
- [ ] Authentication (`GOOGLE_WORKSPACE_CLI_CREDENTIALS`, `GOOGLE_WORKSPACE_API_KEY`)
- [ ] Auto-pagination (`--page-all`) with NDJSON output
- [ ] `gws schema <method>` introspection
- [ ] Error handling JSON structure
- [ ] Binary download with `--output`
- [ ] Version override (`--api-version`, colon syntax)

6. **Fix any issues found** — update the SKILL.md files directly.

7. **Rebuild and re-verify** if any examples were changed.

// turbo
```bash
cargo build 2>&1
```
8 changes: 8 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
18 changes: 18 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# OAuth Client Credentials
# Create these at https://console.cloud.google.com/apis/credentials
GOOGLE_WORKSPACE_CLI_CLIENT_ID=
GOOGLE_WORKSPACE_CLI_CLIENT_SECRET=

# Authentication
# Path to a service account JSON key file or user credentials
# GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=

# Impersonation (Domain-Wide Delegation)
# Email address of the user to impersonate when using a service account
# GOOGLE_WORKSPACE_CLI_IMPERSONATED_USER=

# Model Armor Sanitization
# Default template resource name for --sanitize
# GOOGLE_WORKSPACE_CLI_SANITIZE_TEMPLATE=projects/my-project/locations/us-central1/templates/my-template
# Sanitization mode: 'warn' (default) or 'block'
# GOOGLE_WORKSPACE_CLI_SANITIZE_MODE=warn
10 changes: 10 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Codeowners

# Core engine code strictly requires your review
# Isolates agents to `skills/` or `src/helpers/` unless absolutely necessary
/src/main.rs @jpoehnelt
/src/executor.rs @jpoehnelt
/src/discovery.rs @jpoehnelt
/src/commands.rs @jpoehnelt
/src/auth.rs @jpoehnelt
/src/schema.rs @jpoehnelt
16 changes: 16 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Description

Please include a summary of the change and which issue is fixed. If adding a new feature or command, please include the output of running it with `--dry-run` to prove the JSON request body matches the Discovery Document schema.

**Dry Run Output:**
```json
// Paste --dry-run output here if applicable
```

## Checklist:

- [ ] My code follows the `AGENTS.md` guidelines (no generated `google-*` crates).
- [ ] I have run `cargo fmt --all` to format the code perfectly.
- [ ] I have run `cargo clippy -- -D warnings` and resolved all warnings.
- [ ] I have added tests that prove my fix is effective or that my feature works.
- [ ] I have provided a Changeset file (e.g. via `pnpx changeset`) to document my changes.
40 changes: 40 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

area: schema:
- 'src/schema.rs'
area: auth:
- 'src/auth.rs'
area: execution:
- 'src/executor.rs'
- 'src/commands.rs'
- 'src/main.rs'
area: discovery:
- 'src/discovery.rs'
skill: docs:
- 'src/helpers/docs.rs'
skill: drive:
- 'src/helpers/drive.rs'
skill: events:
- 'src/helpers/events.rs'
skill: gmail:
- 'src/helpers/gmail.rs'
skill: script:
- 'src/helpers/script.rs'
skill: sheets:
- 'src/helpers/sheets.rs'
core: docs:
- '**/*.md'
core: ci:
- '.github/**/*'
Loading