Workspace Analysis Skill
SkillAI & modelsThis skill gives Claude Code an awareness of all the repositories you work in, whether they are separate repos or one large monorepo. Once added, your AI can understand how your projects fit together and carry that understanding across everything it does for you.
Available today. Use it from your connected AI after setup.
No other account needed.
After adding it, open your projects in Claude Code and ask it to map out your workspace. From there, you can ask questions about how your repositories connect or work on changes that touch several at once.
Then ask your AI: use the Workspace Analysis Skill skill
What your AI can do with it
- See how your repositories relate and depend on each other
- Analyze the overall structure and layout of your workspace
- Track API contracts between your projects and services
- Keep working context when a task spans more than one repository
- Handle both multi-repo setups and single monorepos
What this skill tells your AI
The instructions your AI receives, as published by alinaqi/maggy in skills/workspace/SKILL.md and read by ahel’s review.
Dynamic multi-repo and monorepo awareness for Claude Code. Analyze workspace topology, track API contracts, and maintain cross-repo context.
The Problem
When you have separate frontend/backend repos (or monorepo with multiple apps), Claude Code operates in isolation. It doesn't know:
- API contracts between modules/repos
- Shared types and interfaces
- Full system architecture
- Cross-repo dependencies
- What changed in other parts of the system
This leads to:
- Duplicate type definitions
- API contract mismatches
- Breaking changes not caught until runtime
- Claude reimplementing things that exist elsewhere
Solution: Dynamic Workspace Analysis
Instead of static manifests that get stale, Claude dynamically analyzes the workspace and generates context artifacts that stay fresh through hooks.
┌─────────────────────────────────────────────────────────────────┐
│ WORKSPACE ANALYSIS SYSTEM │
├─────────────────────────────────────────────────────────────────┤
│ │
│ /analyze-workspace (Full Analysis - ~2 min) │
│ ├── Topology discovery (monorepo vs multi-repo) │
│ ├── Dependency graph (who calls whom) │
│ ├── Contract extraction (OpenAPI, GraphQL, types) │
│ └── Key file identification (what to load when) │
│ │
│ /sync-contracts (Incremental - ~15 sec) │
│ ├── Check contract source files for changes │
│ ├── Update CONTRACTS.md with diffs │
│ └── Validate consistency │
│ │
│ Hooks (Automatic) │
│ ├── Session start: Staleness advisory (~5 sec) │
│ ├── Post-commit: Auto-sync if contracts changed (~15 sec) │
│ └── Pre-push: Validation gate (~10 sec) │
│ │
└─────────────────────────────────────────────────────────────────┘
Workspace Classification
Detection Patterns
| Type | Indicators | File Access |
|---|---|---|
| Monorepo | pnpm-workspace.yaml, nx.json, turbo.json, lerna.json | Direct (same tree) |
| Multi-repo | Sibling directories with separate .git | Via symlinks or paths |
| Hybrid | Monorepo + external repo dependencies | Mixed |
| Single | One app, no workspace config | N/A (use existing-repo) |
Monorepo Detection
# Check for monorepo indicators
ls package.json pnpm-workspace.yaml lerna.json nx.json turbo.json 2>/dev/null
ls apps/ packages/ services/ libs/ modules/ 2>/dev/null
Multi-Repo Detection
# Check sibling directories for related repos
ls -la ../*.git 2>/dev/null
cat ../*/.git/config 2>/dev/null | grep "url"
# Look for naming patterns
ls .. | grep -E "(frontend|backend|api|web|shared|common)"
Polyglot Detection
# Find all package manifests
find . -maxdepth 4 -name "package.json" -o -name "pyproject.toml" \
-o -name "go.mod" -o -name "Cargo.toml" -o -name "pom.xml" \
-o -name "build.gradle" -o -name "Gemfile"
Analysis Protocol
Phase 1: Topology Discovery (~30 seconds)
Determine workspace structure:
## Discovery Checklist
1. [ ] Identify workspace root
2. [ ] Classify workspace type (monorepo/multi-repo/hybrid/single)
3. [ ] List all modules/apps/packages
4. [ ] Detect tech stack per module
5. [ ] Identify entry points per module
Module Detection Pattern:
workspace-root/
├── apps/ → Application modules
│ ├── web/ → Frontend app
│ └── api/ → Backend app
├── packages/ → Shared packages
│ ├── ui/ → Component library
│ ├── types/ → Shared types
│ └── db/ → Database layer
├── services/ → Microservices
└── libs/ → Internal libraries
Phase 2: Dependency Graph (~60 seconds)
For each module, map:
1. Internal Dependencies
# TypeScript/JavaScript
grep -r "from ['\"]@" --include="*.ts" --include="*.tsx" | head -50
grep -r "workspace:" package.json
# Python
grep -r "from \." --include="*.py" | head -50
2. API Relationships
# Find API calls
grep -rE "fetch|axios|httpx|requests\." --include="*.ts" --include="*.py" | \
grep -E "/api|localhost|127\.0\.0\.1" | head -30
3. Database Connections
# Find DB access patterns
grep -rE "prisma|drizzle|sqlalchemy|sequelize|typeorm" --include="*.ts" --include="*.py"
Phase 3: Contract Extraction (~45 seconds)
Identify and parse API contracts:
| Contract Type | Detection | Extraction |
|---|---|---|
| OpenAPI | openapi.json, swagger.yaml, /docs endpoint | Parse paths, schemas |
| GraphQL | schema.graphql, *.gql, /graphql endpoint | Parse types, queries, mutations |
| tRPC | trpc router files, @trpc/* imports | Parse router definitions |
| Protobuf | *.proto files | Parse services, messages |
| TypeScript | Shared .d.ts, exported interfaces | Parse exported types |
| Pydantic | schemas/, models/ with BaseModel | Parse model definitions |
| Zod | schemas/ with z.object | Parse schema definitions |
Contract Source Priority:
- Generated specs (openapi.json) - most accurate
- Schema definitions (Pydantic, Zod) - source of truth
- Type exports (TypeScript .d.ts) - consumer contracts
- Inferred from code - last resort
Phase 4: Key File Identification (~30 seconds)
Identify files Claude MUST know about for each context:
| Category | Detection Pattern | Token Priority |
|---|---|---|
| Route definitions | **/routes/**, **/api/**, @app.get, @router | HIGH |
| Type definitions | **/types/**, *.d.ts, schemas/, models/ | HIGH |
| Config | .env.example, config/, settings.py | MEDIUM |
| Entry points | main.ts, index.ts, app.py, server.py | MEDIUM |
| API clients | **/api/client*, **/lib/api* | HIGH |
| Database schema | schema/, migrations/, prisma/schema.prisma | MEDIUM |
| Tests | __tests__/, *_test.py, *.spec.ts | LOW (on-demand) |
Generated Artifacts
All artifacts go in _project_specs/workspace/:
_project_specs/workspace/
├── TOPOLOGY.md # What modules exist, their roles
├── CONTRACTS.md # API specs, shared types (summarized)
├── DEPENDENCY_GRAPH.md # Who calls whom (visual + list)
├── KEY_FILES.md # What to load for each context
├── CROSS_REPO_INDEX.md # Capabilities across all modules
└── .contract-sources # Files to monitor for changes
TOPOLOGY.md Format
# Workspace Topology
Generated: 2026-01-20T14:32:00Z
Analyzer: maggy/workspace-analysis
Workspace Type: Monorepo (Turborepo)
## Overview
┌─────────────────────────────────────────────────┐ │ apps/web (Next.js) ←→ apps/api (FastAPI) │ │ ↓ ↓ │ │ packages/shared-types ← packages/db │ └─────────────────────────────────────────────────┘
## Modules
### apps/web
- **Path**: /apps/web
- **Tech**: Next.js 14, TypeScript, TailwindCSS
- **Role**: Customer-facing dashboard
- **Consumes**: apps/api (REST), packages/shared-types
- **Entry**: src/app/layout.tsx
- **Key files**:
- `src/lib/api/client.ts` - API client (187 lines)
- `src/types/` - Frontend-specific types (12 files)
- **Token estimate**: ~15K (full), ~4K (summarized)
### apps/api
- **Path**: /apps/api
- **Tech**: FastAPI, Python 3.12, SQLAlchemy
- **Role**: REST API, business logic
- **Exposes**: OpenAPI at /docs (47 endpoints)
- **Consumes**: packages/db
- **Entry**: app/main.py
- **Key files**:
- `app/routes/` - All endpoints (8 routers)
- `app/schemas/` - Pydantic models (23 files)
- `openapi.json` - Generated spec
- **Token estimate**: ~22K (full), ~6K (summarized)
### packages/shared-types
- **Path**: /packages/shared-types
- **Tech**: TypeScript
- **Role**: Shared type definitions
- **Consumed by**: apps/web, apps/api (codegen)
- **Key files**:
- `src/index.ts` - All exports (340 lines)
- **Token estimate**: ~3K
### packages/db
- **Path**: /packages/db
- **Tech**: Drizzle ORM, TypeScript
- **Role**: Database schema, migrations
- **Consumed by**: apps/api
- **Key files**:
- `schema/` - Table definitions (8 files)
- `migrations/` - Migration history (23 files)
- **Token estimate**: ~8K (full), ~2K (schema only)
CONTRACTS.md Format
# API Contracts
Generated: 2026-01-20T14:32:00Z
Last sync: 2026-01-20T16:45:00Z
Sources: 3 files monitored
## REST API: apps/api → apps/web
### Endpoints Summary (47 total)
| Domain | Count | Key Endpoints |
|--------|-------|---------------|
| /api/auth | 5 | POST /login, POST /register, POST /refresh |
| /api/users | 6 | GET /me, PATCH /me, GET /:id |
| /api/campaigns | 8 | CRUD + POST /bulk, GET /analytics |
| /api/analytics | 12 | GET /dashboard, GET /timeseries, GET /funnel |
| /api/settings | 4 | GET /, PATCH /, GET /integrations |
### Key Types
```typescript
// Campaign domain (from apps/api/app/schemas/campaign.py)
interface Campaign {
id: string;
name: string;
status: 'draft' | 'active' | 'paused' | 'completed';
budget: number;
target_audience: TargetAudience;
created_at: string;
updated_at: string;
}
interface CampaignCreate {
name: string;
budget: number;
target_audience?: TargetAudience;
}
// Auth domain (from apps/api/app/schemas/auth.py)
interface User {
id: string;
email: string;
name: string;
role: 'user' | 'admin';
}
interface TokenPair {
access_token: string;
refresh_token: string;
expires_in: number;
}
Contract Validation Status
| Check | Status | Details |
|---|---|---|
| OpenAPI matches routes | ✅ | 47/47 endpoints documented |
| Types match schemas | ✅ | All Pydantic models exported |
| Frontend types current | ⚠️ | 2 types need regeneration |
Shared Types: packages/shared-types
Exported Types (34 total)
| Category | Types | Used By |
|---|---|---|
| Domain models | Campaign, User, Analytics | web, api |
| API responses | ApiResponse, PaginatedResponse | web |
| Utilities | DateRange, FilterParams | web, api |
Database Schema: packages/db
Tables (12 total)
| Table | Key Columns | Relations |
|---|---|---|
| users | id, email, name, role | campaigns, sessions |
| campaigns | id, user_id, name, status | analytics, targets |
| analytics | id, campaign_id, date, metrics | campaigns |
### DEPENDENCY_GRAPH.md Format
```markdown
# Dependency Graph
Generated: 2026-01-20T14:32:00Z
## Visual Overview
┌─────────────────┐
│ packages/db │
│ (Drizzle ORM) │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐ │ apps/web │◄──│ apps/api │ │ (Next.js) │ │ (FastAPI) │ └────────┬────────┘ └────────┬────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────┐ │ packages/shared-types │ │ (TypeScript) │ └─────────────────────────────────────────┘
## Dependency Matrix
| Module | Depends On | Depended By |
|--------|------------|-------------|
| apps/web | shared-types, apps/api (runtime) | - |
| apps/api | shared-types (codegen), db | apps/web |
| packages/shared-types | - | apps/web, apps/api |
| packages/db | - | apps/api |
## Import Analysis
### apps/web imports:
@repo/shared-types: 23 files apps/api (via fetch): 15 files
### apps/api imports:
packages/db: 12 files packages/shared-types (codegen): 8 files
## API Call Graph
apps/web apps/api ───────── ──────── src/lib/api/client.ts ──────────► app/routes/auth.py └── login() POST /api/auth/login └── register() POST /api/auth/register
src/app/campaigns/page.tsx ─────► app/routes/campaigns.py └── getCampaigns() GET /api/campaigns └── createCampaign() POST /api/campaigns
KEY_FILES.md Format
# Key Files by Context
## Context: Frontend API Integration
**When**: Modifying API calls, response handling, or API types in frontend
Load these files (~8K tokens):
apps/web/src/lib/api/client.ts # API client implementation apps/web/src/types/api.d.ts # Frontend API types apps/api/openapi.json # Full API spec (or summary) packages/shared-types/src/index.ts # Shared type definitions
## Context: Backend Endpoint Development
**When**: Adding/modifying API endpoints
Load these files (~12K tokens):
apps/api/app/routes/ # Existing route patterns apps/api/app/schemas/ # Pydantic models (relevant domain) apps/api/app/dependencies/ # Auth, DB dependencies packages/db/schema/ # Relevant table definitions
## Context: Database Changes
**When**: Schema modifications, migrations, queries
Load these files (~6K tokens):
packages/db/schema/ # All table definitions packages/db/migrations/ # Last 5 migrations apps/api/app/models/ # ORM model usage
## Context: Shared Types
**When**: Modifying interfaces used across modules
Load these files (~4K tokens):
packages/shared-types/src/ # Type source files apps/web/src/types/api.d.ts # Consumer (frontend) apps/api/app/schemas/ # Source (backend)
## Context: Authentication
**When**: Auth flow, sessions, tokens
Load these files (~5K tokens):
apps/api/app/routes/auth.py # Auth endpoints apps/api/app/dependencies/auth.py # Auth middleware apps/web/src/lib/auth/ # Frontend auth handling packages/shared-types/src/auth.ts # Auth types
## Load-on-Demand Triggers
| Claude detects... | Load additionally |
|-------------------|-------------------|
| "check the API contract" | Full OpenAPI spec |
| Import from another module | That module's exports |
| Database query pattern | Full schema definitions |
| Test failure in other module | That module's test files |
| "breaking change" | Both sides of the contract |
CROSS_REPO_INDEX.md Format
# Cross-Repository Capability Index
Generated: 2026-01-20T14:32:00Z
## Capabilities by Domain
### Authentication
| Capability | Location | Module | Type |
|------------|----------|--------|------|
| Login user | POST /api/auth/login | apps/api | endpoint |
| Register user | POST /api/auth/register | apps/api | endpoint |
| Refresh token | POST /api/auth/refresh | apps/api | endpoint |
| Auth context | src/contexts/AuthContext.tsx | apps/web | component |
| Auth hook | src/hooks/useAuth.ts | apps/web | hook |
| User type | src/auth.ts | shared-types | type |
| Session type | src/auth.ts | shared-types | type |
### Campaigns
| Capability | Location | Module | Type |
|------------|----------|--------|------|
| List campaigns | GET /api/campaigns | apps/api | endpoint |
| Create campaign | POST /api/campaigns | apps/api | endpoint |
| Campaign CRUD | app/routes/campaigns.py | apps/api | router |
| Campaign form | src/components/CampaignForm.tsx | apps/web | component |
| Campaign type | src/campaign.ts | shared-types | type |
| campaigns table | schema/campaigns.ts | packages/db | table |
### Analytics
| Capability | Location | Module | Type |
|------------|----------|--------|------|
| Dashboard data | GET /api/analytics/dashboard | apps/api | endpoint |
| Timeseries | GET /api/analytics/timeseries | apps/api | endpoint |
| Analytics hook | src/hooks/useAnalytics.ts | apps/web | hook |
| Chart components | src/components/charts/ | apps/web | components |
## Search Index
Before implementing new functionality, search this index:
Q: "How do I get the current user?" A: Use useAuth() hook from apps/web/src/hooks/useAuth.ts Or GET /api/users/me endpoint from apps/api
Q: "Where are campaign types defined?" A: Source of truth: packages/shared-types/src/campaign.ts Backend schema: apps/api/app/schemas/campaign.py Frontend types: apps/web/src/types/api.d.ts (generated)
Q: "How do I add a new API endpoint?" A: Pattern in apps/api/app/routes/campaigns.py Register in apps/api/app/routes/init.py Add types to packages/shared-types Regenerate frontend types
Token Budget Management
Context Limits
┌─────────────────────────────────────────────────────────────────┐
│ TOKEN BUDGET ALLOCATION │
├─────────────────────────────────────────────────────────────────┤
│ Total context: ~200K tokens │
│ Reserve for output: ~50K tokens │
│ Working budget: ~150K tokens │
├─────────────────────────────────────────────────────────────────┤
│ P0 (Must have): 50K │ Current module (full) │
│ P1 (Should have): 40K │ Directly related modules (summary) │
│ P2 (Nice to have): 30K │ Contracts + shared types │
│ P3 (If room): 20K │ Decisions, todos, history │
│ Buffer: 10K │ Dynamic loading during session │
└─────────────────────────────────────────────────────────────────┘
Automatic Summarization
When loading cross-module context, summarize:
| Content Type | Full Load Threshold | Summarization Strategy |
|---|---|---|
| OpenAPI spec | < 50 endpoints | Endpoints + key types only |
| Type files | < 30 types | Exported types only |
| Route files | < 200 lines | Signatures + docstrings |
| Config files | < 50 lines | Keys only (no values/secrets) |
| Test files | Never full | Only on explicit request |
Context Loading Strategy
┌─────────────────────────────────────────────────────────────────┐
│ CONTEXT LOADING HIERARCHY │
├─────────────────────────────────────────────────────────────────┤
│ Level 1: Always loaded (~5K tokens) │
│ ├── TOPOLOGY.md (workspace structure) │
│ ├── CONTRACTS.md (API summary) │
│ └── CROSS_REPO_INDEX.md (capability search) │
│ │
│ Level 2: Loaded based on current file (~15K tokens) │
│ ├── KEY_FILES.md recommendations for current context │
│ ├── Related module summaries │
│ └── Relevant type definitions │
│ │
│ Level 3: On-demand expansion (variable) │
│ ├── Full OpenAPI spec (when "check API contract") │
│ ├── Full type files (when modifying interfaces) │
│ └── Other module's full files (when cross-repo change) │
└─────────────────────────────────────────────────────────────────┘
Multi-Repo File Access
For multi-repo workspaces (separate .git directories):
Option 1: Sibling Directory Convention (Recommended)
~/code/
├── myapp-frontend/ # git repo
├── myapp-backend/ # git repo
├── myapp-shared/ # git repo
└── .workspace/ # workspace config (optional)
└── myapp.yaml
Claude accesses via relative paths: ../myapp-backend/
Option 2: Workspace Symlinks
# In frontend repo
mkdir -p .workspace/repos
ln -s ../../myapp-backend .workspace/repos/backend
ln -s ../../myapp-shared .workspace/repos/shared
Option 3: Git Submodules
# Add related repos as submodules (read-only)
git submodule add --depth 1 ../myapp-shared .workspace/shared
File Access Rules
## Multi-Repo Access Protocol
WHEN accessing files from another repo:
1. Use relative paths from workspace root
2. Read-only access (never modify other repos)
3. Cache contract files locally in _project_specs/workspace/cache/
4. Log cross-repo reads in decisions.md
BEFORE making cross-repo changes:
1. Document the change in BOTH repos' decisions.md
2. Create linked todos in BOTH repos
3. Implement in dependency order (shared → backend → frontend)
Cross-Repo Change Detection
When Claude detects changes that affect other modules:
┌─────────────────────────────────────────────────────────────────┐
│ ⚠️ CROSS-REPO CHANGE DETECTED │
├─────────────────────────────────────────────────────────────────┤
│ This change affects: apps/api │
│ Specifically: Endpoint POST /api/campaigns expects new field │
│ │
│ Impact Analysis: │
│ ├── apps/web/src/lib/api/client.ts - needs update │
│ ├── packages/shared-types/src/campaign.ts - needs new field │
│ └── apps/api/app/schemas/campaign.py - source of change │
│ │
│ Recommended Order: │
│ 1. Update packages/shared-types first (source of truth) │
│ 2. Update apps/api schema │
│ 3. Regenerate frontend types │
│ 4. Update apps/web API client │
│ 5. Run /sync-contracts │
│ │
│ [Proceed with guidance] [Load full context] [Cancel] │
└─────────────────────────────────────────────────────────────────┘
Change Impact Patterns
| Change Type | Impacts | Action |
|---|---|---|
| New API endpoint | Frontend client, types | Add to both, sync contracts |
| Modified response | Frontend types, tests | Regenerate types, update tests |
| New required field | All consumers | Breaking change protocol |
| Renamed field | All consumers | Migration + deprecation |
| New shared type | Consumers on next use | Export from shared-types |
| Schema migration | API models, queries | Run migration, verify queries |
Contract Freshness System
Staleness Detection
# .contract-sources file (auto-generated)
# Files that define contracts - monitored for changes
# OpenAPI specs
apps/api/openapi.json
apps/api/docs/openapi.yaml
# Type definitions
packages/shared-types/src/index.ts
packages/shared-types/src/api.ts
# Pydantic schemas
apps/api/app/schemas/*.py
# Database schema
packages/db/schema/*.ts
Freshness Tiers
| Tier | Trigger | Action | Time | Blocking |
|---|---|---|---|---|
| 1 | Session start | Staleness check | ~5s | No |
| 2 | Post-commit | Auto-sync if contracts changed | ~15s | No |
| 3 | Pre-push | Validation gate | ~10s | Yes (bypassable) |
| 4 | PR opened | CI validation | ~30s | Yes |
| 5 | Weekly cron | Full re-analysis | ~2min | No |
Freshness Indicators
## Contract Status (shown in CONTRACTS.md header)
Last full analysis: 2026-01-18T10:00:00Z
Last sync: 2026-01-20T14:32:00Z
Staleness: 🟢 Fresh (synced 2 hours ago)
## Confidence Levels
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 707
- Forks
- 56
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
workspace- Source
- github.com/alinaqi/maggy