Systems Lab

Agent skill

debugger

Activate when any GTM-OS CLI command fails with an error.

activeNeeds a keyActs undeclared1,844 words

From Othmane-Khadri/YALC-the-GTM-operating-system · 61 skills · 290 · pushed 2026-08-20

What it does when it runs

Activate when any GTM-OS CLI command fails with an error. Also triggers on: 'debug', 'fix', 'not working', 'broken', 'troubleshoot', 'help me fix', 'what went wrong', 'why is this failing', or any variant indicating something is broken.

Read from the skill and the 2 files bundled beside it. A skill’s own description is written to be selected by an agent, so it describes the job and not the dependencies.

Keys and connectors you must supply
  • ANTHROPIC_API_KEY
  • CRUSTDATA_API_KEY
  • ENCRYPTION_KEY
  • FIRECRAWL_API_KEY
  • FULLENRICH_API_KEY
  • INSTANTLY_API_KEY
  • NOTION_API_KEY
  • TURSO_AUTH_TOKEN
  • UNIPILE_API_KEY
Hosts it reaches
  • api.anthropic.com
  • api.crustdata.com
  • api.firecrawl.dev
  • api.notion.com
  • app.fullenrich.com
  • app.instantly.ai
  • console.anthropic.com
  • crustdata.com
  • firecrawl.dev
  • www.notion.so
Tool permissions it declares
No allowed-tools in the frontmatter. It does act, so it runs under whatever permissions your session already grants.
Actions present in the files
shell

Ask about debugger

Opens your assistant with this page's verified links already in the prompt.

Is this safe to install?ClaudeChatGPT
Adapt it to my stackClaudeChatGPT
What else do I need for it to workClaudeChatGPT
Rather ask a human? Talk to Cheetah
git clone --depth 1 --filter=blob:none --sparse https://github.com/Othmane-Khadri/YALC-the-GTM-operating-system.git /tmp/YALC-the-GTM-operating-system
git -C /tmp/YALC-the-GTM-operating-system sparse-checkout set ".claude/skills/debugger"
mkdir -p ~/.claude/skills/debugger
cp -R "/tmp/YALC-the-GTM-operating-system/.claude/skills/debugger/." ~/.claude/skills/debugger/

Picked up without a restart. A project skill of the same name is shadowed by your personal one. For one repository only, swap ~/.claude/skills for .claude/skills. Claude Code docs ↗

The folder is the same in every client that implements the format — 46 of them — so if yours is not above, only the destination changes.

Before you install: this skill will not complete its job on a bare agent. It needs ANTHROPIC_API_KEY, CRUSTDATA_API_KEY, ENCRYPTION_KEY, FIRECRAWL_API_KEY, FULLENRICH_API_KEY, INSTANTLY_API_KEY, NOTION_API_KEY, TURSO_AUTH_TOKEN, which you have to obtain separately.

Reproduced in full from Othmane-Khadri/YALC-the-GTM-operating-system/blob/5686d1f2f526346133f78eef3349fc5a655757b4/.claude/skills/debugger/SKILL.md, which is licensed MIT (repository). 1,844 words, 39 headings.

GTM-OS Debugger

Systematic diagnostic skill that activates when any GTM-OS command fails. Runs a 5-layer funnel from cheapest checks (file reads) to most expensive (live API calls), identifies the root cause, and offers auto-fixes with user approval.

When This Skill Applies

  • Any pnpm cli -- command outputs an error or stack trace
  • User says "debug" / "fix" / "not working" / "broken" / "troubleshoot"
  • User says "help me fix [error]" / "what went wrong" / "why is this failing"
  • User pastes an error message or stack trace from GTM-OS

What This Skill Does NOT Do

  • Fix bugs in user's custom code outside GTM-OS
  • Debug network/firewall issues beyond basic connectivity checks
  • Modify GTM-OS source code (only configuration, env vars, and database state)

CRITICAL RULES

  1. Never skip layers. Always start at Layer 1 even if you think you know the issue. Cheap checks catch 80% of problems.
  2. Never auto-fix without approval. Always show the proposed change and ask before applying.
  3. Never expose secrets. When reading .env.local or api_connections, mask all API keys (e.g., sk-...redacted).
  4. Short-circuit on first finding. When a layer finds the root cause, stop and offer the fix. Don't keep checking.
  5. Re-run the original command after fixing. The debug session isn't done until the command succeeds.

Base Context: GTM-OS Architecture

GTM-OS is a CLI-first TypeScript system for AI-native go-to-market automation.

Entry point: src/cli/index.ts via npx tsx Env loading: .env.local via loadEnv() at CLI startup Config files: ~/.gtm-os/config.yaml (user prefs) + gtm-os.yaml (GTM framework) Database: SQLite via @libsql/client + Drizzle ORM. Default path: file:./gtm-os.db

Three-Layer Architecture

LayerLocationPurpose
Servicesrc/lib/services/Singleton SDK wrappers (Unipile, Firecrawl, Notion). Lazy-init from env vars.
Providersrc/lib/providers/builtin/StepExecutor implementations. Registry dispatches by capability.
Skillsrc/lib/skills/User-facing composable operations.

Provider Dependency Matrix

ProviderRequired Env VarsHealth CheckCommon Failure
QualifyANTHROPIC_API_KEYKey format checkMissing or invalid key
FirecrawlFIRECRAWL_API_KEY5s timeout scrape testExpired key, timeout
UnipileUNIPILE_API_KEY + UNIPILE_DSNgetAccounts()Missing DSN, no LinkedIn account
NotionNOTION_API_KEYLight search()Insufficient scopes
CrustdataCRUSTDATA_API_KEYKey format checkCredits exhausted
FullEnrichFULLENRICH_API_KEYKey format checkInvalid key format
InstantlyINSTANTLY_API_KEYInvalid account

Critical Files Map

Issue DomainFiles to Check
Environment.env.local, .env.example
Databasesrc/lib/db/schema.ts, src/lib/db/index.ts, drizzle.config.ts
Providerssrc/lib/services/{name}.ts, src/lib/providers/builtin/{name}-provider.ts
Frameworkgtm-os.yaml, src/lib/framework/context.ts
Config~/.gtm-os/config.yaml, src/lib/config/loader.ts
Encryptionsrc/lib/crypto.ts
Rate limitssrc/lib/rate-limiter/index.ts
CLI entrysrc/cli/index.ts

Diagnostic Workflow

Step 0: Capture Error Context

Before starting the funnel, capture:

  1. The exact error message and stack trace
  2. Which CLI command was run (e.g., campaign:track, leads:qualify)
  3. Which provider is involved (extract from error message or command)

Store this context — you'll reference it throughout the funnel.

Step 1: Layer 1 — Environment Validation (FREE)

Check .env.local existence and content. No API calls needed.

# Check .env.local exists
test -f .env.local && echo "OK: .env.local exists" || echo "FAIL: .env.local missing"
# Check required vars are set (mask values)
for var in ANTHROPIC_API_KEY DATABASE_URL ENCRYPTION_KEY; do
  if grep -q "^${var}=" .env.local 2>/dev/null; then
    echo "OK: $var is set"
  else
    echo "FAIL: $var is missing"
  fi
done
# Check provider-specific vars for the failing provider
# (run only the relevant check based on Step 0 context)

# Unipile check:
grep -q "^UNIPILE_API_KEY=" .env.local && echo "OK: UNIPILE_API_KEY set" || echo "FAIL: UNIPILE_API_KEY missing"
grep -q "^UNIPILE_DSN=" .env.local && echo "OK: UNIPILE_DSN set" || echo "FAIL: UNIPILE_DSN missing"

# Validate UNIPILE_DSN format (must be https://api{N}.unipile.com:{PORT})
grep "^UNIPILE_DSN=" .env.local | grep -qE "^UNIPILE_DSN=https://api[0-9]+\.unipile\.com:[0-9]+" && echo "OK: DSN format valid" || echo "FAIL: DSN format invalid"
# Check for common env var mistakes
# Trailing whitespace:
grep -n ' $' .env.local && echo "WARNING: Trailing whitespace found" || echo "OK: No trailing whitespace"
# Quoted values (should NOT be quoted):
grep -nE '^[A-Z_]+=".+"' .env.local && echo "WARNING: Quoted values found — remove quotes" || echo "OK: No quoted values"

If any FAIL found: Stop here. Explain the issue and offer to fix it.

Auto-fix actions:

  • Missing .env.local → "I'll copy .env.example to .env.local. You'll need to fill in your API keys."
  • Missing env var → "I'll add {VAR}= to your .env.local. Please paste your key value."
  • Invalid DSN format → Show the correct format: UNIPILE_DSN=https://api{N}.unipile.com:{PORT}
  • Quoted values → "I'll remove the quotes around the value."
  • Trailing whitespace → "I'll trim the whitespace."

Step 2: Layer 2 — Database Validation (FREE)

Check database file and schema state. Local queries only.

# Extract DB path from .env.local (default: ./gtm-os.db)
DB_URL=$(grep "^DATABASE_URL=" .env.local 2>/dev/null | cut -d= -f2-)
DB_PATH="${DB_URL:-file:./gtm-os.db}"
DB_PATH="${DB_PATH#file:}"
echo "Database path: $DB_PATH"
test -f "$DB_PATH" && echo "OK: Database file exists" || echo "FAIL: Database file missing"
# Check core tables exist (need at least these)
sqlite3 "$DB_PATH" "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;" 2>&1

Expected tables (minimum): conversations, messages, workflows, workflow_steps, result_sets, result_rows, knowledge_items, api_connections, frameworks, rate_limit_buckets, campaigns, campaign_leads, campaign_variants, campaign_messages

# Check FTS5 virtual table
sqlite3 "$DB_PATH" "SELECT name FROM sqlite_master WHERE type='table' AND name='knowledge_fts';" 2>&1
# Check pragmas
sqlite3 "$DB_PATH" "PRAGMA journal_mode;" 2>&1
sqlite3 "$DB_PATH" "PRAGMA foreign_keys;" 2>&1

If any FAIL found: Stop here.

Auto-fix actions:

  • Database file missing → "I'll run pnpm db:push to create the database and tables. Approve?"
  • Missing tables → "Tables are missing. I'll run pnpm db:push to apply the schema. Approve?"
  • FTS5 missing → "The full-text search index is missing. This usually self-heals on next startup. Try re-running your command."
  • WAL mode off → "I'll enable WAL mode: sqlite3 gtm-os.db 'PRAGMA journal_mode=WAL;'. Approve?"

Step 3: Layer 3 — Configuration Validation (FREE)

Check YAML config files exist and parse correctly.

# Check gtm-os.yaml
test -f gtm-os.yaml && echo "OK: gtm-os.yaml exists" || echo "FAIL: gtm-os.yaml missing"
# Validate YAML syntax
node -e "
try {
  require('js-yaml').load(require('fs').readFileSync('gtm-os.yaml','utf8'));
  console.log('OK: Valid YAML');
} catch(e) {
  console.log('FAIL: Invalid YAML -', e.message);
}
" 2>&1
# Check onboarding status
node -e "
const y = require('js-yaml').load(require('fs').readFileSync('gtm-os.yaml','utf8'));
console.log('onboarding_complete:', y.onboarding_complete || false);
" 2>&1
# Check user config
test -f ~/.gtm-os/config.yaml && echo "OK: User config exists" || echo "FAIL: User config missing at ~/.gtm-os/config.yaml"

Auto-fix actions:

  • Missing gtm-os.yaml → "Run yalc-gtm onboard to create your GTM framework. This asks 5 questions about your business."
  • Invalid YAML → Show the syntax error location and offer to fix it
  • onboarding_complete: false → "Run yalc-gtm onboard to complete setup."
  • Missing user config → "I'll create ~/.gtm-os/config.yaml with defaults. Approve?"

Step 4: Layer 4 — Provider Connectivity (1 API call)

Only test the provider involved in the error. Never test all providers.

Identify the provider from the error message or command:

  • campaign:track, leads:scrape-post, linkedin:* → Unipile
  • search_web_*, web scraping errors → Firecrawl
  • export, notion:*, Notion errors → Notion
  • qualify, Claude/AI errors → Anthropic
  • enrich, email errors → Crustdata / FullEnrich

Provider-specific health checks:

# Unipile: Check accounts exist
source .env.local 2>/dev/null
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "X-API-KEY: $UNIPILE_API_KEY" "$UNIPILE_DSN/api/v1/accounts" 2>&1 | tail -5
# Firecrawl: Lightweight check (don't scrape, just verify auth)
source .env.local 2>/dev/null
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $FIRECRAWL_API_KEY" "https://api.firecrawl.dev/v1/scrape" -X POST -H "Content-Type: application/json" -d '{"url":"https://example.com","formats":["markdown"],"timeout":5000}' 2>&1 | tail -5
# Notion: Light search
source .env.local 2>/dev/null
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $NOTION_API_KEY" -H "Notion-Version: 2022-06-28" "https://api.notion.com/v1/search" -X POST -H "Content-Type: application/json" -d '{"page_size":1}' 2>&1 | tail -5

Interpret results:

  • HTTP 200 → Provider is working. Issue is elsewhere (proceed to Layer 5).
  • HTTP 401/403 → Authentication failure. Key is invalid or expired.
  • HTTP 429 → Rate limited. Wait and retry.
  • Connection refused / timeout → Network issue or DSN wrong.
  • HTTP 404 → Endpoint changed or DSN format wrong.

Auto-fix actions:

  • Auth failure → "Your API key for {provider} is invalid or expired. Get a new one from {provider dashboard URL} and update .env.local."
  • Rate limited → "You've hit the rate limit. Wait 60 seconds and try again."
  • Unipile no accounts → "No LinkedIn account is connected in Unipile. Go to your Unipile dashboard to connect one."
  • DSN connection failure → "The Unipile DSN is unreachable. Check if it matches the format https://api{N}.unipile.com:{PORT} — the DSN can rotate."

Step 5: Layer 5 — Deep Diagnosis (varies)

If Layers 1-4 all pass, the issue is in application logic. Analyze the stack trace.

  1. Parse the stack trace — identify the failing file and function
  2. Read the failing source file — understand what it's trying to do
  3. Check for known runtime errors — reference config/error-catalog.md
  4. Check rate limit state:
DB_PATH=$(grep "^DATABASE_URL=" .env.local 2>/dev/null | cut -d= -f2- | sed 's/^file://')
DB_PATH="${DB_PATH:-./gtm-os.db}"
sqlite3 "$DB_PATH" "SELECT provider, tokens_remaining, last_refill_at FROM rate_limit_buckets;" 2>&1
  1. Check encryption state:
sqlite3 "$DB_PATH" "SELECT provider, status, substr(encrypted_key, 1, 20) || '...' as key_preview FROM api_connections;" 2>&1
  1. Check for concurrent access:
# Check if another process has the DB locked
lsof "$DB_PATH" 2>/dev/null | head -5

Auto-fix actions vary by finding. Always explain what you found and propose a specific fix.

Step 6: Unresolved — Generate Diagnostic Report

If all layers pass but the error persists:

  1. Collect a diagnostic summary:

    • OS + Node.js version
    • GTM-OS version (from package.json)
    • Env vars present (names only, never values)
    • Database table count
    • Provider availability status
    • The original error + stack trace
  2. Save to ./debug-report-{YYYYMMDD-HHmmss}.md

  3. Tell the user:

"I've exhausted the standard diagnostic checks and couldn't identify the root cause. I've saved a diagnostic report to debug-report-{timestamp}.md. You can share this when filing a GitHub issue — it contains no secrets."


After Fixing

Once a fix is applied:

  1. Re-run the exact command that originally failed
  2. If it succeeds → "Fixed! The command ran successfully."
  3. If it fails with a NEW error → restart the funnel from Layer 1 with the new error
  4. If it fails with the SAME error → escalate to the next layer

Provider Dashboard URLs (for guiding users to regenerate keys)

ProviderDashboard
Anthropichttps://console.anthropic.com/settings/keys
UnipileYour Unipile admin panel (URL varies by account)
Firecrawlhttps://firecrawl.dev/app/api-keys
Notionhttps://www.notion.so/my-integrations
Crustdatahttps://crustdata.com/app/api-keys
FullEnrichhttps://app.fullenrich.com/api-keys
Instantlyhttps://app.instantly.ai/app/settings/api

Files bundled with it

These load only when the skill asks for them, so they cost nothing until it runs.

Need help setting it up?

This page tells you what debugger does and what it needs. Cheetah builds the agent setup it runs inside: data, CRM, sequencing and the guardrails.

Book a call →

The directory stays free. There is nothing gated behind this.