Push Revit schedules, site assessments, and warning logs directly into shared Google Sheets — no manual export, no copy-paste, no formatting by hand. Read values from a shared Doc and pipe them into Revit parameters. One-time sign-in; every subsequent call is silent.
Read and write Google Sheets and Docs from the command line. No manual export, no copy-paste.
One-time browser sign-in. Credentials cached locally. Your agent runs bim google login; a browser window opens, you click Allow, done. Every subsequent call refreshes the token silently.
bim google login # opens browser — one-time setup
bim google whoami # verify signed in
bim google doctor --json
Requires a network connection at login time and at each API call. All data stays in your Google account.
| Verb | What it does |
|---|---|
bim google login [--readonly] [--client-id-file CLIENT-ID-FILE] [--start] [--finish FINISH] [--default] | Authenticate with Google via OAuth. Opens your browser once; credentials are cached locally and refreshed automatically. When the human is not at this machine (Slack, SSH, phone), use the two-step form instead: `login --start` returns {auth_url, human_steps}; relay auth_url, have the human click Allow and paste back the failed 127.0.0.1 redirect URL, then run `login --finish <url>`. |
bim google logout [--account ACCOUNT] | Remove saved Google credentials. |
bim google whoami [--account ACCOUNT] | Show the current authentication state. Returns {signed_in, email, scopes, expires_at}. If the token is near expiry, also returns {token_expired: true, hint}; the token refreshes automatically on the next API call. |
bim google doctor | Check environment readiness. |
bim google version | Print driver version. |
| Verb | What it does |
|---|---|
bim google auth status [--account ACCOUNT] | Alias for whoami. Show the current authentication state. Returns the same payload as whoami. |
| Verb | What it does |
|---|---|
bim google accounts list | List saved Google accounts and their scopes, default marker, and token expiration. |
bim google accounts use --email EMAIL | Set the default Google account used when --account and BIM_GOOGLE_ACCOUNT are absent. |
| Verb | What it does |
|---|---|
bim google sheets read --spreadsheet SPREADSHEET [--id ID] [--range RANGE] [--sheet SHEET] [--formulas] [--grid] [--account ACCOUNT] | Read values from a Google Sheet and stream as NDJSON. Default: first row is treated as column headers, each data row emitted as one JSON object with header keys. With --grid: emit a clean 2D grid instead — one JSON array per row in column order, header row included as the first line (lossless; use for column order, the raw header, an irregular/blank header, or a single-row range, which the default mode reports as rows:0). The final line is a summary object {range, rows} — not a data row. |
bim google sheets audit --spreadsheet SPREADSHEET [--id ID] [--range RANGE] [--sheet SHEET] [--all] [--account ACCOUNT] | Inspect a sheet range for formula coverage. Reads with valueRenderOption=FORMULA and emits NDJSON: one line per literal-value cell (type=value), then a summary {range, total_cells, formula_cells, value_cells, empty_cells}. Use to find cells that should be formulas but contain hard-coded values. Pass --all to include formula cells in the output too. |
bim google sheets errors --spreadsheet SPREADSHEET [--id ID] [--range RANGE] [--account ACCOUNT] | Sweep a spreadsheet for cells in an error state and return {count, errors} with each cell's tab, A1 reference, error type, and API error message. |
bim google sheets append --spreadsheet SPREADSHEET [--id ID] [--sheet SHEET] [--with-header] [--input-mode INPUT-MODE] [--account ACCOUNT] | Append rows to a Google Sheet from NDJSON stdin. Reads one JSON object per line; object keys become column values. By default Sheets uses user-entered parsing; pass --input-mode raw to store literal text unchanged. |
bim google sheets write --spreadsheet SPREADSHEET [--id ID] --range RANGE [--grid] [--input-mode INPUT-MODE] [--account ACCOUNT] | Overwrite a specific range in a Google Sheet from stdin. Default mode: NDJSON objects (keys become columns). Grid mode (--grid): stdin must be a JSON 2D array e.g. [["a","=B1+1"],[2,3]]. By default Sheets uses user-entered parsing in both modes; pass --input-mode raw to store literal text unchanged. |
bim google sheets clear --spreadsheet SPREADSHEET [--id ID] --range RANGE [--account ACCOUNT] | Clear cell values from a range, preserving formatting and structure. |
bim google sheets sort --spreadsheet SPREADSHEET [--id ID] --range RANGE --col COL [--desc] [--account ACCOUNT] | Sort a range by a single column. Range must include the sheet name (e.g. Sheet1!A2:F100). Use --desc for descending order. |
bim google sheets find-replace --spreadsheet SPREADSHEET [--id ID] --find FIND [--replace REPLACE] [--sheet SHEET] [--match-case] [--match-entire-cell] [--account ACCOUNT] | Find and replace text across the spreadsheet or a specific tab. |
bim google sheets fill-down --spreadsheet SPREADSHEET [--id ID] --range RANGE --formula FORMULA [--auto-extent] [--key-column KEY-COLUMN] [--account ACCOUNT] | Fill every cell in a range with a formula, auto-adjusting relative row/column references. Range must include sheet name. Use an open end (e.g. Sheet1!B2:B) or --auto-extent to auto-detect the last populated row. |
bim google sheets format --spreadsheet SPREADSHEET [--id ID] --range RANGE [--number-format NUMBER-FORMAT] [--bold] [--italic] [--fg-color FG-COLOR] [--bg-color BG-COLOR] [--halign HALIGN] [--freeze-rows FREEZE-ROWS] [--freeze-cols FREEZE-COLS] [--merge] [--col-width COL-WIDTH] [--account ACCOUNT] | Apply cell and sheet-level formatting to a range. Translates flags to repeatCell / updateSheetProperties / mergeCells / updateDimensionProperties batchUpdate requests. Only specified options are applied; unspecified options are left unchanged. |
bim google sheets conditional-format --spreadsheet SPREADSHEET [--id ID] --range RANGE [--condition CONDITION] [--value VALUE] [--formula FORMULA] [--bg-color BG-COLOR] [--text-color TEXT-COLOR] [--gradient] [--min MIN] [--mid MID] [--max MAX] [--min-color MIN-COLOR] [--mid-color MID-COLOR] [--max-color MAX-COLOR] [--clear] [--account ACCOUNT] | Add or clear a conditional format rule on a range. Supports boolean rules (NUMBER_LESS, NUMBER_GREATER, NUMBER_EQ, NUMBER_NOT_EQ, TEXT_CONTAINS, TEXT_EQ, TEXT_NOT_EQ, BLANK, NOT_BLANK, CUSTOM_FORMULA) and 3-point color-scale gradient rules (--gradient). NOTE: use NUMBER_LESS not NUMBER_LESS_THAN; use TEXT_EQ for exact string match (TEXT_CONTAINS matches substrings). Pass --clear to delete all existing CF rules from the sheet before adding. |
bim google sheets note --spreadsheet SPREADSHEET [--id ID] --range RANGE [--text TEXT] [--clear] [--account ACCOUNT] | Set or clear a hover note (annotation) on every cell in a range. Uses repeatCell with fields=note so existing cell values and formatting are untouched. Idempotent: re-setting the same note is a no-op. Pass --text "" or --clear to remove notes. |
bim google sheets tabs list --spreadsheet SPREADSHEET [--id ID] [--account ACCOUNT] | List all tabs in a spreadsheet. Returns {tabs: [{sheet_id, title, index}], count}. |
bim google sheets tabs add --spreadsheet SPREADSHEET [--id ID] --name NAME [--account ACCOUNT] | Add a new tab to an existing spreadsheet. |
bim google sheets tabs delete --spreadsheet SPREADSHEET [--id ID] --name NAME [--account ACCOUNT] | Delete a tab by name. Irreversible. |
bim google sheets tabs rename --spreadsheet SPREADSHEET [--id ID] --from FROM --to TO [--account ACCOUNT] | Rename a tab. |
bim google sheets tabs duplicate --spreadsheet SPREADSHEET [--id ID] --name NAME [--new-name NEW-NAME] [--account ACCOUNT] | Duplicate a tab within the same spreadsheet. |
| Verb | What it does |
|---|---|
bim google docs create --title TITLE [--parent PARENT] [--account ACCOUNT] | Create a blank Google Doc. With --parent, move the new document into that Drive folder. Returns the document ID and edit URL. |
bim google docs read --doc DOC [--raw] [--account ACCOUNT] | Read a Google Doc and return plain text with title, word count, and character count. |
bim google docs append --doc DOC [--text TEXT] [--account ACCOUNT] | Append plain text to the end of a Google Doc. |
bim google docs write --doc DOC [--account ACCOUNT] | Write structured content blocks to a Google Doc from NDJSON stdin. Supports heading levels 1-3, paragraph, bullet, and table blocks. |
bim google docs clear --doc DOC [--account ACCOUNT] | Clear a Google Doc body while keeping the document ID, edit URL, and Drive comment threads. |
| Verb | What it does |
|---|---|
bim google drive list [--parent PARENT] [--account ACCOUNT] | List files in Google Drive. Streams one JSON object per file to stdout; returns {count} as summary. With drive.metadata.readonly scope this lists all of the user's files; pass --parent to list only the files directly inside a specific folder. Reads file metadata only (names/ids/types) — read sheet contents with sheets read by id. |
bim google drive pick [--account ACCOUNT] | Open the Google Drive Picker in the user's browser (at picker.bimcli.com) and wait for a file selection. Returns {file_id, name}. Requires an active bim google login. Shows only files accessible under the current drive.file scope (files created by this app). Interactive: opens a browser window; resolves when the user picks a file or cancels. |
bim google drive download --file FILE --output OUTPUT [--account ACCOUNT] | Download a Drive file by ID and save it to a local path. Only files created by this app are accessible (drive.file scope). |
bim google drive export --file FILE --mime-type MIME-TYPE [--output OUTPUT] [--account ACCOUNT] | Convert a native Google file (Docs, Sheets, Slides) to a portable format using the Drive files.export endpoint. Pass --output to write to a file; omit it to stream the content to stdout. Returns metadata including source_mime_type, exported_as, and bytes_written. |
bim google drive upload [--input INPUT] [--name NAME] [--mime-type MIME-TYPE] [--parent PARENT] [--account ACCOUNT] | Upload a file to Google Drive. Reads from a local path (--input) or stdin. With --parent, the file is created inside that folder; otherwise it lands in Drive root. Returns the new file ID and web link. |
bim google drive mkdir --name NAME [--parent PARENT] [--account ACCOUNT] | Create a folder in Google Drive. With --parent, the folder is created inside that folder; otherwise at Drive root. Returns the new folder's ID. Not idempotent (Drive allows duplicate folder names) -- list first if you need get-or-create. |
bim google drive rm --file FILE [--account ACCOUNT] | Move a Drive file or folder to the trash (recoverable). Trashing a folder trashes its contents. Returns the item's id/name. |
bim google drive revisions list --file FILE [--account ACCOUNT] | List the revision history of a Drive file as NDJSON. Each line is {id, modified_time, last_modifying_user, keep_forever}. Note: revisions are coalesced by Google -- three consecutive edits may produce only two revision entries. |
bim google drive revisions get --file FILE --revision REVISION [--mime-type MIME-TYPE] [--account ACCOUNT] | Fetch the content of a Drive file at a specific revision and write it to stdout. Supported for Google Sheets (returns CSV by default; use --mime-type to select another format). Google Docs are not supported: the Drive v3 export endpoint silently ignores the revision parameter and returns current content, so this verb returns a structured error instead of misleading output. |
| Verb | What it does |
|---|---|
bim google comments list --file FILE [--include-resolved] [--account ACCOUNT] | List Drive comment threads on a file as NDJSON. By default only unresolved threads are emitted; pass --include-resolved to include resolved threads. Anchors are emitted as raw opaque strings. |
bim google comments reply --file FILE --comment COMMENT [--text TEXT] [--account ACCOUNT] | Post a plain text reply to a Drive comment thread. |
bim google comments resolve --file FILE --comment COMMENT [--text TEXT] [--account ACCOUNT] | Resolve a Drive comment thread by posting a resolve reply action, then re-reading the thread to verify it is resolved. |
| Verb | What it does |
|---|---|
bim google ga run-report --property PROPERTY --metrics METRICS [--dimensions DIMENSIONS] [--start-date START-DATE] [--end-date END-DATE] [--account ACCOUNT] | Run a GA4 Analytics Data API report for a property. Returns {property, dimensions, metrics, rows, row_count} where rows is an array of objects keyed by dimension and metric names. |
| Verb | What it does |
|---|---|
bim google script list --parent PARENT [--account ACCOUNT] | List Apps Script projects bound to a container Drive file (e.g. a spreadsheet). Returns {scripts, count} where scripts is an array of {script_id, name}. An empty scripts array means no bound script exists -- exit 0. |
bim google script push --parent PARENT --name NAME --file FILE [--account ACCOUNT] | Create or update a container-bound Apps Script project. Creates the project if none exists for the parent (idempotent: re-running with the same parent keeps the same scriptId). A minimal appsscript.json manifest is injected automatically when none is supplied. Returns {script_id, parent_id, title, action, files}. |
bim google script pull --script SCRIPT [--out OUT] [--account ACCOUNT] | Fetch the source files of an Apps Script project and write them to disk. Streams one NDJSON entry per file, then emits the summary envelope {script_id, out_dir, files, count}. Content is byte-identical to what was last pushed. |
| Verb | What it does |
|---|---|
bim google calendar list [--account ACCOUNT] | List the calendars on the signed-in account's calendar list. Returns {calendars, count}; each calendar is {id, name, timezone, access_role, primary}. Use an id as --calendar on the other calendar verbs. |
bim google calendar events list [--calendar CALENDAR] [--from FROM] [--to TO] [--query QUERY] [--max N] [--timezone TIMEZONE] [--account ACCOUNT] | Stream events in a time window as NDJSON (recurring events expanded, ordered by start), then a summary {calendar, from, to, count, truncated}. Each event is {id, calendar, summary, start, end, all_day, status, location, description, organizer, attendees, html_link}. Defaults to the next 7 days of the primary calendar. |
bim google calendar events get --event EVENT [--calendar CALENDAR] [--account ACCOUNT] | Fetch one event by ID. Returns the same event object as calendar events list. |
bim google calendar events create --summary SUMMARY --start START [--end END] [--calendar CALENDAR] [--description DESCRIPTION] [--location LOCATION] [--attendee ATTENDEE] [--timezone TIMEZONE] [--notify] [--account ACCOUNT] | Create an event. A date-only --start makes an all-day event. Without --end, timed events last 1 hour and all-day events 1 day. Attendees are NOT emailed unless --notify is set. Returns the created event. |
bim google calendar events update --event EVENT [--calendar CALENDAR] [--summary SUMMARY] [--start START] [--end END] [--description DESCRIPTION] [--location LOCATION] [--attendee ATTENDEE] [--timezone TIMEZONE] [--notify] [--account ACCOUNT] | Change an event's fields; anything not passed is left alone. Moving --start without --end keeps the event's duration. --attendee replaces the whole attendee list. Attendees are NOT emailed unless --notify is set. Returns the updated event. |
bim google calendar events delete --event EVENT [--calendar CALENDAR] [--notify] [--account ACCOUNT] | Delete an event. Attendees are NOT emailed unless --notify is set. Returns {calendar, event, deleted}. |
bim google calendar freebusy [--calendar CALENDAR] [--from FROM] [--to TO] [--timezone TIMEZONE] [--account ACCOUNT] | Busy intervals for one or more calendars in a time window. Returns {from, to, calendars}; each entry is {calendar, busy: [{start, end}], error?}. |
| Verb | What it does |
|---|---|
bim google gmail search [--query QUERY] [--label LABEL] [--max N] [--include-spam-trash] [--account ACCOUNT] | Search Gmail messages with Gmail search syntax. Streams one metadata-only NDJSON line per message, then returns {count, truncated, next_page_token}. Search never fetches full message bodies. |
bim google gmail get --message MESSAGE [--html] [--format FORMAT] [--account ACCOUNT] | Fetch one Gmail message envelope. Returns headers, body_text, attachment metadata, labels and snippet. With --html, includes body_html; with --format raw, returns the RFC822 source. |
bim google gmail thread --thread THREAD [--html] [--account ACCOUNT] | Fetch a Gmail thread with messages in order. Each message has the same envelope shape as gmail get. |
bim google gmail labels list [--no-counts] [--account ACCOUNT] | List Gmail labels. Returns {labels, count}; each label includes id, name, type, unread_count and total_count. |
bim google gmail labels create --name NAME [--color COLOR] [--account ACCOUNT] | Create a Gmail label. With --color, the driver sets the label background and chooses a readable text color. |
bim google gmail filters list [--account ACCOUNT] | List Gmail filters as NDJSON, then returns {count}. Label IDs in filter actions are resolved to label names. |
bim google gmail filters get --filter FILTER [--account ACCOUNT] | Fetch one Gmail filter by ID. Returns criteria and action labels using label names. |
bim google gmail filters create [--from FROM] [--to TO] [--subject SUBJECT] [--query QUERY] [--negated-query NEGATED-QUERY] [--has-attachment] [--add-label ADD-LABEL] [--remove-label REMOVE-LABEL] [--create-labels] [--skip-inbox] [--mark-read] [--star] [--important] [--never-important] [--trash] [--never-spam] [--forward FORWARD] [--apply-existing] [--dry-run] [--account ACCOUNT] | Create a Gmail filter. Requires at least one criterion and one action. With --apply-existing, also applies the action to messages that already match; --dry-run prints the filter body and match count without changing Gmail. |
bim google gmail filters delete --filter FILTER [--account ACCOUNT] | Delete a Gmail filter. Deleting a filter does not undo labels already applied. |
bim google gmail modify [--message MESSAGE] [--thread THREAD] [--add-label ADD-LABEL] [--remove-label REMOVE-LABEL] [--account ACCOUNT] | Add or remove labels on messages or a thread. Label names are resolved to IDs; unknown names return an invalid-input error with close matches. |
bim google gmail archive [--message MESSAGE] [--thread THREAD] [--account ACCOUNT] | Archive messages or a thread by removing INBOX. Takes the same target args as gmail modify. |
bim google gmail mark-read [--message MESSAGE] [--thread THREAD] [--account ACCOUNT] | Mark messages or a thread read by removing UNREAD. |
bim google gmail mark-unread [--message MESSAGE] [--thread THREAD] [--account ACCOUNT] | Mark messages or a thread unread by adding UNREAD. |
bim google gmail drafts create [--to TO] [--cc CC] [--bcc BCC] [--subject SUBJECT] [--body BODY] [--body-file BODY-FILE] [--html HTML] [--reply-to REPLY-TO] [--attach ATTACH] [--account ACCOUNT] | Create a Gmail draft. Provide recipients, subject and either --body or --body-file; --html creates multipart/alternative. --reply-to fills thread headers, subject and recipient when omitted. |
bim google gmail drafts list [--max N] [--account ACCOUNT] | List Gmail drafts as NDJSON, then returns {count, truncated, next_page_token}. |
bim google gmail drafts send --draft DRAFT [--account ACCOUNT] | Send an existing Gmail draft. |
bim google gmail send [--to TO] [--cc CC] [--bcc BCC] [--subject SUBJECT] [--body BODY] [--body-file BODY-FILE] [--html HTML] [--reply-to REPLY-TO] [--attach ATTACH] --confirm [--account ACCOUNT] | Send a Gmail message with the same composition args as gmail drafts create. Refuses to send unless --confirm is passed. |
# Push a Revit sheet list into a shared tracker
bim revit schedule export Sheets | bim google sheets append --spreadsheet <id> --with-header
# Push model warnings into a Sheet for review
bim revit warnings list | bim google sheets append --spreadsheet <id> --with-header
# Read spec values from a Doc and push into Revit parameters
bim google docs read --doc <id> | bim revit param set --by Mark
# Read a Sheet, write matching params to Revit
bim google sheets read --spreadsheet <id> | bim revit param set --by Mark
By default, bim-google authenticates using Everbeach's built-in Google Cloud project. If your org requires its own OAuth app — for compliance, quota isolation, or Google Workspace policy enforcement — you can supply your own client credentials at login time.
Step 1 — Create a Cloud project and OAuth client
{
"installed": {
"client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"client_secret": "YOUR_SECRET",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"redirect_uris": ["http://localhost"]
}
}
Step 2 — Login with your credential file
bim google login --client-id-file /path/to/client_secret.json
The flag overrides the built-in client ID for this login session only. The resulting token is cached locally and auto-refreshed on subsequent calls — you do not need to pass --client-id-file again until you log out and re-authenticate.
Note: Tokens issued by your own client ID are stored in the same cache location as the default ones. Running bim google logout clears them. If you switch between client IDs, log out first to avoid using a token issued by the previous client.
sheets read treats the first row as column headers. A sheet with no header row will use the first data row as key names.docs append inserts at end-of-body with no automatic line break. Include \n at the start of your text for a blank line before new content.sheets write overwrites only the specified range. Cells outside that range are untouched.sheets write (single batchUpdate) for bulk changes.For agent use: /google/llms.txt