mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-02 11:45:20 +02:00
feat: add /setup-team-sync skill, auto-push transcript hooks in skills
- setup-team-sync/SKILL.md.tmpl: idempotent guided setup (create config, OAuth, verify connectivity, configure settings, summary) - ship/retro/qa SKILL.md.tmpl: add push-transcript hook after existing push-ship/push-retro/push-qa hooks (silent, non-fatal) - scripts/gen-skill-docs.ts: add setup-team-sync to template list - Regenerated all SKILL.md files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -271,6 +271,7 @@ $B snapshot -i -a -o "$REPORT_DIR/screenshots/issue-002.png"
|
||||
}
|
||||
QAEOF
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-qa .gstack/qa-reports/qa-sync.json 2>/dev/null && echo "Synced to team ✓" || true
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-transcript 2>/dev/null || true
|
||||
```
|
||||
Substitute actual values. Uses snake_case keys matching the Supabase schema.
|
||||
|
||||
|
||||
@@ -245,6 +245,7 @@ $B snapshot -i -a -o "$REPORT_DIR/screenshots/issue-002.png"
|
||||
}
|
||||
QAEOF
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-qa .gstack/qa-reports/qa-sync.json 2>/dev/null && echo "Synced to team ✓" || true
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-transcript 2>/dev/null || true
|
||||
```
|
||||
Substitute actual values. Uses snake_case keys matching the Supabase schema.
|
||||
|
||||
|
||||
@@ -358,6 +358,7 @@ Include backlog data in the JSON when TODOS.md exists:
|
||||
After writing the JSON snapshot, sync to the team store (non-fatal, silent if not configured):
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-retro ".context/retros/${today}-${next}.json" 2>/dev/null && echo "Synced to team ✓" || true
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-transcript 2>/dev/null || true
|
||||
```
|
||||
|
||||
### Step 14: Write the Narrative
|
||||
|
||||
@@ -349,6 +349,7 @@ Include backlog data in the JSON when TODOS.md exists:
|
||||
After writing the JSON snapshot, sync to the team store (non-fatal, silent if not configured):
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-retro ".context/retros/${today}-${next}.json" 2>/dev/null && echo "Synced to team ✓" || true
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-transcript 2>/dev/null || true
|
||||
```
|
||||
|
||||
### Step 14: Write the Narrative
|
||||
|
||||
@@ -183,6 +183,7 @@ function findTemplates(): string[] {
|
||||
path.join(ROOT, 'plan-eng-review', 'SKILL.md.tmpl'),
|
||||
path.join(ROOT, 'retro', 'SKILL.md.tmpl'),
|
||||
path.join(ROOT, 'gstack-upgrade', 'SKILL.md.tmpl'),
|
||||
path.join(ROOT, 'setup-team-sync', 'SKILL.md.tmpl'),
|
||||
];
|
||||
for (const p of candidates) {
|
||||
if (fs.existsSync(p)) templates.push(p);
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
---
|
||||
name: setup-team-sync
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Set up team sync with Supabase. Creates .gstack-sync.json if missing,
|
||||
authenticates via OAuth, verifies connectivity, and configures sync settings.
|
||||
Idempotent — safe to run multiple times. Use before first /ship, /retro, or /qa
|
||||
to enable team data sharing.
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
- Write
|
||||
- AskUserQuestion
|
||||
---
|
||||
<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
|
||||
<!-- Regenerate: bun run gen:skill-docs -->
|
||||
|
||||
## Update Check (run first)
|
||||
|
||||
```bash
|
||||
_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)
|
||||
[ -n "$_UPD" ] && echo "$_UPD" || true
|
||||
```
|
||||
|
||||
If output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user "Running gstack v{to} (just updated!)" and continue.
|
||||
|
||||
# Setup Team Sync
|
||||
|
||||
Set up gstack team sync with Supabase. This skill is idempotent — safe to run anytime.
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1: Check project config
|
||||
|
||||
```bash
|
||||
cat .gstack-sync.json 2>/dev/null || echo "NOT_FOUND"
|
||||
```
|
||||
|
||||
- If the file exists and has `supabase_url`, `supabase_anon_key`, and `team_slug`: print "Team config found: {team_slug} at {supabase_url}" and skip to Step 3.
|
||||
- If NOT_FOUND: proceed to Step 2.
|
||||
|
||||
### Step 2: Create .gstack-sync.json
|
||||
|
||||
Ask the user for three values using AskUserQuestion:
|
||||
|
||||
1. **Supabase URL** — e.g., `https://xyzcompany.supabase.co`
|
||||
- Found in Supabase Dashboard → Project Settings → API → Project URL
|
||||
2. **Anon Key** — the public `anon` key (NOT the `service_role` key)
|
||||
- Found in Supabase Dashboard → Project Settings → API → Project API keys → `anon` `public`
|
||||
- This key is safe to commit — it's public by design (like a Firebase API key). RLS enforces real access control.
|
||||
3. **Team slug** — a short identifier like `my-team` or `yc-internal`
|
||||
|
||||
Then write `.gstack-sync.json`:
|
||||
|
||||
```bash
|
||||
cat > .gstack-sync.json << 'ENDCONFIG'
|
||||
{
|
||||
"supabase_url": "USER_PROVIDED_URL",
|
||||
"supabase_anon_key": "USER_PROVIDED_KEY",
|
||||
"team_slug": "USER_PROVIDED_SLUG"
|
||||
}
|
||||
ENDCONFIG
|
||||
echo "Created .gstack-sync.json"
|
||||
```
|
||||
|
||||
Tell the user: "Commit this file to your repo so team members get it automatically. The anon key is public by Supabase design — RLS enforces real access control."
|
||||
|
||||
### Step 3: Check authentication
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync status 2>&1
|
||||
```
|
||||
|
||||
Look at the output:
|
||||
- If `Authenticated: yes` → skip to Step 5
|
||||
- If `Authenticated: no` → proceed to Step 4
|
||||
|
||||
### Step 4: Authenticate
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync setup 2>&1
|
||||
```
|
||||
|
||||
This opens a browser for OAuth. Tell the user to complete authentication in their browser. Wait for the output to show "Authenticated as ..." or an error.
|
||||
|
||||
If it fails with "Port 54321 is in use", ask the user to close the other process and retry.
|
||||
|
||||
### Step 5: Test connectivity
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync test 2>&1
|
||||
```
|
||||
|
||||
This runs a full push + pull test. All 4 steps should show `ok`:
|
||||
1. Config: ok
|
||||
2. Auth: ok
|
||||
3. Push: ok (with latency)
|
||||
4. Pull: ok (with row count)
|
||||
|
||||
If Step 3 (Push) fails, tell the user: "The Supabase migrations may not be applied yet. Copy the SQL files from `supabase/migrations/` and run them in your Supabase SQL editor, in order (001 through 006)."
|
||||
|
||||
### Step 6: Configure sync settings
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config get sync_enabled 2>/dev/null
|
||||
~/.claude/skills/gstack/bin/gstack-config get sync_transcripts 2>/dev/null
|
||||
```
|
||||
|
||||
Ask the user if they want to enable transcript sync (opt-in, shares Claude session data with the team):
|
||||
|
||||
- If they say yes:
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set sync_enabled true
|
||||
~/.claude/skills/gstack/bin/gstack-config set sync_transcripts true
|
||||
```
|
||||
|
||||
- If they say no (or just want basic sync without transcripts):
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set sync_enabled true
|
||||
```
|
||||
|
||||
### Step 7: Summary
|
||||
|
||||
Print a summary:
|
||||
|
||||
```
|
||||
Team sync setup complete!
|
||||
|
||||
Project config: .gstack-sync.json ✓ (commit to repo)
|
||||
Authentication: {email} ✓
|
||||
Connectivity: {supabase_url} ✓
|
||||
Sync enabled: yes
|
||||
Transcripts: {yes/no}
|
||||
|
||||
Next steps:
|
||||
• Run /ship, /retro, or /qa — data syncs automatically
|
||||
• View team data: gstack-sync show
|
||||
• Check status anytime: gstack-sync status
|
||||
```
|
||||
@@ -0,0 +1,130 @@
|
||||
---
|
||||
name: setup-team-sync
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Set up team sync with Supabase. Creates .gstack-sync.json if missing,
|
||||
authenticates via OAuth, verifies connectivity, and configures sync settings.
|
||||
Idempotent — safe to run multiple times. Use before first /ship, /retro, or /qa
|
||||
to enable team data sharing.
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
- Write
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
{{UPDATE_CHECK}}
|
||||
|
||||
# Setup Team Sync
|
||||
|
||||
Set up gstack team sync with Supabase. This skill is idempotent — safe to run anytime.
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1: Check project config
|
||||
|
||||
```bash
|
||||
cat .gstack-sync.json 2>/dev/null || echo "NOT_FOUND"
|
||||
```
|
||||
|
||||
- If the file exists and has `supabase_url`, `supabase_anon_key`, and `team_slug`: print "Team config found: {team_slug} at {supabase_url}" and skip to Step 3.
|
||||
- If NOT_FOUND: proceed to Step 2.
|
||||
|
||||
### Step 2: Create .gstack-sync.json
|
||||
|
||||
Ask the user for three values using AskUserQuestion:
|
||||
|
||||
1. **Supabase URL** — e.g., `https://xyzcompany.supabase.co`
|
||||
- Found in Supabase Dashboard → Project Settings → API → Project URL
|
||||
2. **Anon Key** — the public `anon` key (NOT the `service_role` key)
|
||||
- Found in Supabase Dashboard → Project Settings → API → Project API keys → `anon` `public`
|
||||
- This key is safe to commit — it's public by design (like a Firebase API key). RLS enforces real access control.
|
||||
3. **Team slug** — a short identifier like `my-team` or `yc-internal`
|
||||
|
||||
Then write `.gstack-sync.json`:
|
||||
|
||||
```bash
|
||||
cat > .gstack-sync.json << 'ENDCONFIG'
|
||||
{
|
||||
"supabase_url": "USER_PROVIDED_URL",
|
||||
"supabase_anon_key": "USER_PROVIDED_KEY",
|
||||
"team_slug": "USER_PROVIDED_SLUG"
|
||||
}
|
||||
ENDCONFIG
|
||||
echo "Created .gstack-sync.json"
|
||||
```
|
||||
|
||||
Tell the user: "Commit this file to your repo so team members get it automatically. The anon key is public by Supabase design — RLS enforces real access control."
|
||||
|
||||
### Step 3: Check authentication
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync status 2>&1
|
||||
```
|
||||
|
||||
Look at the output:
|
||||
- If `Authenticated: yes` → skip to Step 5
|
||||
- If `Authenticated: no` → proceed to Step 4
|
||||
|
||||
### Step 4: Authenticate
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync setup 2>&1
|
||||
```
|
||||
|
||||
This opens a browser for OAuth. Tell the user to complete authentication in their browser. Wait for the output to show "Authenticated as ..." or an error.
|
||||
|
||||
If it fails with "Port 54321 is in use", ask the user to close the other process and retry.
|
||||
|
||||
### Step 5: Test connectivity
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync test 2>&1
|
||||
```
|
||||
|
||||
This runs a full push + pull test. All 4 steps should show `ok`:
|
||||
1. Config: ok
|
||||
2. Auth: ok
|
||||
3. Push: ok (with latency)
|
||||
4. Pull: ok (with row count)
|
||||
|
||||
If Step 3 (Push) fails, tell the user: "The Supabase migrations may not be applied yet. Copy the SQL files from `supabase/migrations/` and run them in your Supabase SQL editor, in order (001 through 006)."
|
||||
|
||||
### Step 6: Configure sync settings
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config get sync_enabled 2>/dev/null
|
||||
~/.claude/skills/gstack/bin/gstack-config get sync_transcripts 2>/dev/null
|
||||
```
|
||||
|
||||
Ask the user if they want to enable transcript sync (opt-in, shares Claude session data with the team):
|
||||
|
||||
- If they say yes:
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set sync_enabled true
|
||||
~/.claude/skills/gstack/bin/gstack-config set sync_transcripts true
|
||||
```
|
||||
|
||||
- If they say no (or just want basic sync without transcripts):
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set sync_enabled true
|
||||
```
|
||||
|
||||
### Step 7: Summary
|
||||
|
||||
Print a summary:
|
||||
|
||||
```
|
||||
Team sync setup complete!
|
||||
|
||||
Project config: .gstack-sync.json ✓ (commit to repo)
|
||||
Authentication: {email} ✓
|
||||
Connectivity: {supabase_url} ✓
|
||||
Sync enabled: yes
|
||||
Transcripts: {yes/no}
|
||||
|
||||
Next steps:
|
||||
• Run /ship, /retro, or /qa — data syncs automatically
|
||||
• View team data: gstack-sync show
|
||||
• Check status anytime: gstack-sync status
|
||||
```
|
||||
@@ -431,6 +431,7 @@ Substitute actual values from the preceding steps. Use `0` for Greptile fields i
|
||||
2. Push (non-fatal):
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-ship /tmp/gstack-ship-log.json 2>/dev/null && echo "Synced to team ✓" || true
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-transcript 2>/dev/null || true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -422,6 +422,7 @@ Substitute actual values from the preceding steps. Use `0` for Greptile fields i
|
||||
2. Push (non-fatal):
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-ship /tmp/gstack-ship-log.json 2>/dev/null && echo "Synced to team ✓" || true
|
||||
~/.claude/skills/gstack/bin/gstack-sync push-transcript 2>/dev/null || true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user