diff --git a/docs/CNAME b/docs/CNAME index e79fe93..6523b45 100644 --- a/docs/CNAME +++ b/docs/CNAME @@ -1 +1 @@ -gogcli.sh \ No newline at end of file +gogcli.sh diff --git a/docs/assets/site.css b/docs/assets/site.css new file mode 100644 index 0000000..83da001 --- /dev/null +++ b/docs/assets/site.css @@ -0,0 +1,489 @@ +:root { + --bg0: #07070b; + --bg1: #0b0b11; + --bg2: #11111a; + --card: rgba(17, 17, 26, 0.72); + --card2: rgba(12, 12, 18, 0.64); + --stroke: rgba(255, 255, 255, 0.08); + --stroke2: rgba(255, 255, 255, 0.05); + --text: #f3f4f6; + --muted: rgba(243, 244, 246, 0.7); + --dim: rgba(243, 244, 246, 0.46); + + --b: #4285f4; + --r: #ea4335; + --y: #fbbc05; + --g: #34a853; + + --shadow: 0 24px 60px rgba(0, 0, 0, 0.55); + --shadow2: 0 16px 40px rgba(0, 0, 0, 0.45); + + --radius: 16px; + --radius2: 22px; + + --serif: "Fraunces", ui-serif, Georgia, serif; + --sans: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; +} + +* { + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + margin: 0; + background: radial-gradient(1200px 800px at 50% -20%, rgba(66, 133, 244, 0.18), transparent 60%), + radial-gradient(900px 700px at 80% 18%, rgba(234, 67, 53, 0.14), transparent 55%), + radial-gradient(1000px 900px at 18% 62%, rgba(52, 168, 83, 0.14), transparent 55%), + radial-gradient(900px 900px at 65% 88%, rgba(251, 188, 5, 0.12), transparent 55%), + linear-gradient(180deg, var(--bg0), var(--bg1) 40%, var(--bg0)); + color: var(--text); + font-family: var(--sans); + -webkit-font-smoothing: antialiased; + line-height: 1.55; + overflow-x: hidden; +} + +a { + color: inherit; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +code { + font-family: var(--mono); + font-size: 0.95em; +} + +.skip { + position: absolute; + left: -999px; + top: 10px; + background: var(--bg2); + border: 1px solid var(--stroke); + color: var(--text); + padding: 10px 12px; + border-radius: 10px; + z-index: 20; +} +.skip:focus { + left: 12px; +} + +.bg { + position: fixed; + inset: 0; + pointer-events: none; + z-index: 0; +} + +.bg__mesh { + position: absolute; + inset: 0; + background: radial-gradient(1200px 800px at 20% 20%, rgba(66, 133, 244, 0.18), transparent 60%), + radial-gradient(1000px 800px at 82% 30%, rgba(234, 67, 53, 0.12), transparent 55%), + radial-gradient(1000px 900px at 40% 85%, rgba(52, 168, 83, 0.12), transparent 55%); + filter: blur(4px) saturate(1.12); + opacity: 0.95; +} + +.bg__grid { + position: absolute; + inset: -2px; + background-image: linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px); + background-size: 72px 72px; + opacity: 0.055; + transform: perspective(900px) rotateX(58deg) translateY(-18%); + transform-origin: top; + mask-image: radial-gradient(60% 60% at 50% 30%, rgba(0, 0, 0, 1), transparent 72%); +} + +.bg__grain { + position: absolute; + inset: 0; + opacity: 0.2; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)' opacity='.45'/%3E%3C/svg%3E"); + mix-blend-mode: overlay; +} + +.wrap { + width: min(1100px, calc(100% - 48px)); + margin: 0 auto; + position: relative; + z-index: 1; +} + +.top { + position: sticky; + top: 0; + z-index: 10; + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + background: rgba(7, 7, 11, 0.58); + border-bottom: 1px solid rgba(255, 255, 255, 0.06); +} + +.top__row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 14px 0; +} + +.brand { + display: flex; + align-items: center; + gap: 10px; + text-decoration: none !important; +} + +.brand__mark { + width: 26px; + height: 26px; + border-radius: 10px; + background: conic-gradient(from 200deg, var(--b), var(--g), var(--y), var(--r), var(--b)); + box-shadow: 0 10px 24px rgba(66, 133, 244, 0.15), 0 10px 24px rgba(52, 168, 83, 0.12); +} + +.brand__mark--small { + width: 18px; + height: 18px; + border-radius: 7px; +} + +.brand__name { + font-family: var(--mono); + font-weight: 500; + letter-spacing: -0.02em; +} + +.brand__tag { + font-size: 12px; + color: var(--dim); + border: 1px solid var(--stroke2); + background: rgba(17, 17, 26, 0.55); + padding: 3px 8px; + border-radius: 999px; +} + +.nav { + display: flex; + align-items: center; + gap: 18px; + font-size: 14px; + color: var(--muted); +} + +.nav a { + text-decoration: none; +} + +.nav a:hover { + color: var(--text); + text-decoration: none; +} + +.nav__cta { + color: var(--text) !important; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.08); + padding: 8px 12px; + border-radius: 999px; +} + +.main { + padding-bottom: 70px; +} + +.hero { + padding: 56px 0 26px; +} + +.hero__grid { + display: grid; + grid-template-columns: 1.05fr 0.95fr; + gap: 28px; + align-items: start; +} + +.kicker { + display: inline-flex; + gap: 10px; + align-items: center; + font-size: 12px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: rgba(243, 244, 246, 0.58); + margin: 0 0 14px; +} + +.kicker::before { + content: ""; + width: 10px; + height: 10px; + border-radius: 3px; + background: linear-gradient(135deg, rgba(66, 133, 244, 0.9), rgba(52, 168, 83, 0.85)); + box-shadow: 0 0 0 4px rgba(66, 133, 244, 0.08); +} + +h1 { + font-family: var(--serif); + font-weight: 700; + letter-spacing: -0.03em; + line-height: 0.95; + margin: 0 0 14px; + font-size: clamp(44px, 5.5vw, 68px); +} + +.hero__word { + display: block; + opacity: 0; + transform: translateY(10px); + animation: rise 700ms cubic-bezier(0.2, 1, 0.2, 1) forwards; +} + +.hero__word:nth-child(1) { + animation-delay: 80ms; +} +.hero__word:nth-child(2) { + animation-delay: 160ms; +} +.hero__word:nth-child(3) { + animation-delay: 260ms; +} + +.hero__word--mono { + font-family: var(--mono); + font-weight: 500; + letter-spacing: -0.04em; + color: rgba(243, 244, 246, 0.92); +} + +@keyframes rise { + to { + opacity: 1; + transform: translateY(0); + } +} + +.lede { + margin: 0 0 18px; + font-size: 16.5px; + color: var(--muted); + max-width: 52ch; + opacity: 0; + transform: translateY(10px); + animation: rise 700ms cubic-bezier(0.2, 1, 0.2, 1) 320ms forwards; +} + +.lede strong { + color: var(--text); + font-weight: 600; +} + +.pills { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin: 0 0 20px; + opacity: 0; + transform: translateY(10px); + animation: rise 700ms cubic-bezier(0.2, 1, 0.2, 1) 380ms forwards; +} + +.pill { + font-size: 12px; + border-radius: 999px; + padding: 6px 10px; + border: 1px solid var(--stroke2); + background: rgba(17, 17, 26, 0.55); + color: rgba(243, 244, 246, 0.76); +} + +.pill--b { + box-shadow: inset 0 0 0 1px rgba(66, 133, 244, 0.25); +} +.pill--r { + box-shadow: inset 0 0 0 1px rgba(234, 67, 53, 0.22); +} +.pill--y { + box-shadow: inset 0 0 0 1px rgba(251, 188, 5, 0.22); +} +.pill--g { + box-shadow: inset 0 0 0 1px rgba(52, 168, 83, 0.22); +} + +.hero__actions { + display: flex; + gap: 12px; + margin: 0 0 12px; + opacity: 0; + transform: translateY(10px); + animation: rise 700ms cubic-bezier(0.2, 1, 0.2, 1) 440ms forwards; +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 10px; + padding: 10px 14px; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.08); + text-decoration: none !important; + font-weight: 600; + font-size: 14px; + box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22); +} + +.btn--primary { + background: linear-gradient(135deg, rgba(66, 133, 244, 0.92), rgba(52, 168, 83, 0.86)); + color: #091018; + border-color: rgba(255, 255, 255, 0.12); + box-shadow: 0 18px 44px rgba(66, 133, 244, 0.18), 0 18px 44px rgba(52, 168, 83, 0.14); +} + +.btn--ghost { + background: rgba(255, 255, 255, 0.06); + color: var(--text); +} + +.btn:hover { + transform: translateY(-1px); +} + +.note { + margin: 0; + color: rgba(243, 244, 246, 0.56); + font-size: 13px; + opacity: 0; + transform: translateY(10px); + animation: rise 700ms cubic-bezier(0.2, 1, 0.2, 1) 520ms forwards; +} + +.note code { + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.07); + padding: 2px 6px; + border-radius: 8px; + color: rgba(243, 244, 246, 0.84); +} + +.hero__panel { + display: grid; + gap: 14px; + opacity: 0; + transform: translateY(10px); + animation: rise 700ms cubic-bezier(0.2, 1, 0.2, 1) 260ms forwards; +} + +.card { + border: 1px solid var(--stroke); + background: var(--card); + border-radius: var(--radius2); + box-shadow: var(--shadow); + overflow: hidden; +} + +.term__bar { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 14px; + background: rgba(12, 12, 18, 0.58); + border-bottom: 1px solid rgba(255, 255, 255, 0.06); +} + +.dots { + display: inline-flex; + gap: 6px; +} + +.dot { + width: 11px; + height: 11px; + border-radius: 999px; +} + +.dot--r { + background: #ff5f57; +} +.dot--y { + background: #febc2e; +} +.dot--g { + background: #28c840; +} + +.term__title { + margin-left: auto; + margin-right: auto; + font-family: var(--mono); + font-size: 12px; + color: rgba(243, 244, 246, 0.55); +} + +.term__body { + padding: 14px 14px 16px; + background: rgba(11, 11, 17, 0.6); +} + +.term__pre { + margin: 0; + font-family: var(--mono); + font-size: 12.5px; + color: rgba(243, 244, 246, 0.86); + line-height: 1.6; + white-space: pre-wrap; +} + +.term__pre code { + display: block; +} + +.meta { + padding: 14px 14px; + background: var(--card2); + border: 1px solid rgba(255, 255, 255, 0.06); + box-shadow: var(--shadow2); +} + +.meta__item { + display: grid; + grid-template-columns: 90px 1fr; + gap: 12px; + padding: 10px 0; +} + +.meta__item + .meta__item { + border-top: 1px solid rgba(255, 255, 255, 0.06); +} + +.meta__k { + color: rgba(243, 244, 246, 0.55); + font-size: 12px; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.meta__v { + color: rgba(243, 244, 246, 0.86); + font-size: 13px; +} + +.meta__v code { + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.07); + padding: 2px 6px; + border-radius: 8px; + color: rgba(243, 244, 246, 0.9); +} diff --git a/docs/assets/site.js b/docs/assets/site.js new file mode 100644 index 0000000..85f3a12 --- /dev/null +++ b/docs/assets/site.js @@ -0,0 +1,34 @@ +(() => { + const el = document.getElementById("demo"); + if (!el) return; + + const original = el.textContent || ""; + const prefersReduced = window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches; + if (prefersReduced) return; + + el.textContent = ""; + + const lines = original.split("\n"); + const chunkDelay = 16; + const lineDelay = 140; + let i = 0; + let j = 0; + + const tick = () => { + if (i >= lines.length) return; + const line = lines[i]; + if (j <= line.length) { + el.textContent += line.slice(j, j + 1); + j += 1; + window.setTimeout(tick, chunkDelay); + return; + } + el.textContent += "\n"; + i += 1; + j = 0; + window.setTimeout(tick, lineDelay); + }; + + window.setTimeout(tick, 260); +})(); + diff --git a/docs/assets/site.more.css b/docs/assets/site.more.css new file mode 100644 index 0000000..c3d0042 --- /dev/null +++ b/docs/assets/site.more.css @@ -0,0 +1,239 @@ +.section { + padding: 52px 0; +} + +.section__grid { + display: grid; + grid-template-columns: 0.36fr 0.64fr; + gap: 28px; + align-items: start; +} + +h2 { + font-family: var(--serif); + font-weight: 700; + letter-spacing: -0.02em; + margin: 0 0 6px; + font-size: 28px; +} + +h3 { + margin: 0 0 8px; + font-size: 16px; + font-weight: 700; +} + +.muted { + margin: 0; + color: var(--muted); +} + +.cols { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 14px; +} + +.block { + padding: 16px 16px; +} + +.code { + margin: 0; + padding: 12px 12px; + border-radius: 14px; + background: rgba(0, 0, 0, 0.22); + border: 1px solid rgba(255, 255, 255, 0.08); + overflow: auto; +} + +.code code { + font-family: var(--mono); + font-size: 12.5px; + color: rgba(243, 244, 246, 0.88); +} + +.steps { + display: grid; + gap: 14px; +} + +.step { + display: grid; + grid-template-columns: 46px 1fr; + gap: 14px; + padding: 16px; + border-radius: var(--radius2); + border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(12, 12, 18, 0.46); + box-shadow: var(--shadow2); +} + +.step__n { + width: 40px; + height: 40px; + border-radius: 14px; + display: grid; + place-items: center; + font-family: var(--mono); + font-weight: 500; + color: rgba(243, 244, 246, 0.92); + background: linear-gradient(135deg, rgba(66, 133, 244, 0.22), rgba(52, 168, 83, 0.18)); + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.step p { + margin: 0 0 10px; + color: var(--muted); +} + +.callout { + margin-top: 14px; + display: grid; + grid-template-columns: 44px 1fr; + gap: 14px; + padding: 16px; + border-radius: var(--radius2); + border: 1px solid rgba(255, 255, 255, 0.08); + background: linear-gradient(135deg, rgba(66, 133, 244, 0.14), rgba(234, 67, 53, 0.08)); + box-shadow: var(--shadow2); +} + +.callout__icon { + width: 44px; + height: 44px; + border-radius: 16px; + background: rgba(0, 0, 0, 0.18); + border: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: inset 0 0 0 1px rgba(66, 133, 244, 0.18); +} + +.callout__body p { + margin: 0 0 10px; + color: var(--muted); +} + +.callout__body code { + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.07); + padding: 2px 6px; + border-radius: 8px; + color: rgba(243, 244, 246, 0.92); +} + +.grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; +} + +.feat { + padding: 16px; + background: rgba(12, 12, 18, 0.46); + box-shadow: var(--shadow2); +} + +.feat p { + margin: 0; + color: var(--muted); +} + +.footerline { + display: flex; + gap: 12px; + margin-top: 18px; +} + +.sitefoot { + padding: 36px 0 26px; + border-top: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(7, 7, 11, 0.35); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} + +.sitefoot__row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; +} + +.sitefoot__brand { + display: inline-flex; + align-items: center; + gap: 10px; + font-family: var(--mono); +} + +.sitefoot__small { + margin-top: 8px; + color: rgba(243, 244, 246, 0.6); + font-size: 13px; +} + +.sitefoot__small a { + color: rgba(243, 244, 246, 0.75); +} + +.sep { + margin: 0 8px; + color: rgba(243, 244, 246, 0.28); +} + +.sitefoot__right { + display: flex; + gap: 14px; + color: rgba(243, 244, 246, 0.7); + font-size: 14px; +} + +.sitefoot__fineprint { + margin-top: 18px; + color: rgba(243, 244, 246, 0.46); + font-size: 12px; +} + +@media (max-width: 980px) { + .hero__grid { + grid-template-columns: 1fr; + } + .section__grid { + grid-template-columns: 1fr; + } + .grid { + grid-template-columns: 1fr 1fr; + } +} + +@media (max-width: 640px) { + .wrap { + width: min(1100px, calc(100% - 28px)); + } + .nav { + display: none; + } + .cols { + grid-template-columns: 1fr; + } + .grid { + grid-template-columns: 1fr; + } + .footerline { + flex-direction: column; + align-items: flex-start; + } + .sitefoot__row { + flex-direction: column; + align-items: flex-start; + } +} + +@media (prefers-reduced-motion: reduce) { + * { + animation: none !important; + transition: none !important; + scroll-behavior: auto !important; + } +} + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..58a069f --- /dev/null +++ b/docs/index.html @@ -0,0 +1,301 @@ + + + + + + gog — Google in your terminal + + + + + + + + + + + + + + + + + + + +
+
+ + + gog + gogcli + + +
+
+ +
+
+
+
+

Google Workspace. One binary.

+

+ Google + in your + terminal +

+

+ gog unifies Gmail, Calendar, Drive, Contacts, Tasks, Sheets, Docs, Slides, and People + under one CLI — with JSON output and sane defaults. +

+ +
+ Gmail + Calendar + Drive + Contacts + Tasks + Sheets + Docs + Slides + People +
+ +
+ Install + Readme +
+ +

+ Tip: add export GOG_ACCOUNT=you@gmail.com once, stop repeating --account. +

+
+ +
+
+ +
+

+$ brew install steipete/tap/gogcli
+$ gog auth credentials ~/Downloads/client_secret.json
+$ gog auth add you@gmail.com
+
+$ export GOG_ACCOUNT=you@gmail.com
+$ gog gmail labels list
+$ gog calendar calendars --max 5 --json | jq '.calendars[].summary'
+$ gog drive ls --query "mimeType='application/pdf'" --max 3
+
+
+
+ +
+
+
Output
+
tables / --plain / --json
+
+
+
Accounts
+
multi-account + gog auth manage
+
+
+
Secrets
+
OS keyring (Keychain / Secret Service / CredMan)
+
+
+
+
+
+ +
+
+
+

Install

+

Homebrew tap, or build from source.

+
+ +
+
+

Homebrew

+
brew install steipete/tap/gogcli
+
+
+

From source

+
git clone https://github.com/steipete/gogcli.git
+cd gogcli
+make
+./bin/gog --help
+
+
+
+
+ +
+
+
+

Quickstart

+

+ You’ll need a Google Cloud “Desktop app” OAuth client JSON once. Then you can keep adding accounts. +

+
+ +
+
+
1
+
+

Store credentials

+

Save your downloaded client JSON into gog’s config.

+
gog auth credentials ~/Downloads/client_secret_....json
+
+
+
+
2
+
+

Authorize an account

+

Browser flow by default. Use --manual for headless.

+
gog auth add you@gmail.com
+
+
+
+
3
+
+

Run commands

+

Use --json for scripting.

+
export GOG_ACCOUNT=you@gmail.com
+gog gmail search 'newer_than:7d' --max 10 --json | jq
+
+
+
+ +
+ +
+

Re-auth a service (e.g. Sheets)

+

+ If you add scopes later and Google doesn’t return a refresh token, re-run with + --force-consent. +

+
gog auth add you@gmail.com --services sheets --force-consent
+
+
+
+
+ +
+
+
+

Features

+

High leverage commands, consistent UX, and clean output.

+
+
+
+

Gmail

+

Search threads, send mail, manage labels, drafts, filters, settings, and watch (Pub/Sub push).

+
+
+

Calendar

+

List/create/update events, respond to invites, detect conflicts, and check free/busy.

+
+
+

Drive

+

List/search/upload/download, export Docs formats, permissions, folders, URLs.

+
+
+

Sheets / Docs / Slides

+

Read/write Sheets; export Docs/Slides/Sheets to PDF/DOCX/PPTX/XLSX/CSV via Drive.

+
+
+

Contacts / People

+

Personal contacts, “other contacts”, Workspace directory, and your profile.

+
+
+

Tasks

+

Tasklists + tasks: add/update/done/undo/delete/clear with paging and JSON output.

+
+
+
+
+ +
+
+
+

Examples

+

A few commands you’ll actually use.

+
+
+
+

Find unread mail

+
gog gmail search 'is:unread newer_than:7d' --max 20
+

Pipe JSON to jq for scripts.

+
gog gmail search 'newer_than:7d' --max 50 --json | jq '.threads[] | .subject'
+
+
+

Export a Sheet as PDF

+
gog sheets export <spreadsheetId> --format pdf --out ./sheet.pdf
+

Docs and Slides are similar.

+
gog docs export <docId> --format docx --out ./doc.docx
+gog slides export <presentationId> --format pptx --out ./deck.pptx
+
+
+ + +
+
+
+ + + + + +