Skip to content
Back to skills

Global State

ASecurity

Global state management for cross-session persistence. Reference this skill to read/write global config, history, learnings, and statistics.

  • 666 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 8, 2026
developmentjavascripttypescriptjavanodeexpresstestingapidatabasefrontendperformance

Works with

  • claude code
  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill global-state --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Global State?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Global State
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-global-state/badge)](https://www.skillsdirectory.com/skills/majiayu000-global-state)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: global-state
description: Global state management for cross-session persistence. Reference this skill to read/write global config, history, learnings, and statistics.
---

// Project Autopilot - Cross-Session State Management
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>

# Global State Skill

Manage persistent state across Claude Code sessions. Works on macOS, Linux, and Windows.

---

## Directory Location

### Platform-Specific Paths

| Platform | Path |
|----------|------|
| macOS/Linux | `~/.claude/autopilot/` |
| Windows | `%USERPROFILE%\.claude\autopilot\` |

### Resolving the Path

```
FUNCTION getGlobalStateDir():
    IF platform == "windows":
        RETURN env.USERPROFILE + "\\.claude\\autopilot\\"
    ELSE:
        RETURN expandPath("~/.claude/autopilot/")
```

Or use Node.js style:
```javascript
const os = require('os');
const path = require('path');
const globalDir = path.join(os.homedir(), '.claude', 'autopilot');
```

---

## Directory Structure

```
{globalDir}/
├── config.json        # User preferences and defaults
├── history.json       # All projects built with outcomes
├── learnings.json     # Cross-project patterns and knowledge
└── statistics.json    # Aggregate stats and estimation accuracy
```

---

## File Schemas

### config.json

User preferences that persist across sessions.

```json
{
  "version": "1.0",
  "defaults": {
    "maxCost": 50,
    "warnCost": 10,
    "alertCost": 25,
    "maxTokens": 2000000,
    "warnTokens": 500000,
    "alertTokens": 1000000,
    "preferredModel": "sonnet",
    "autoApprove": false,
    "verboseOutput": false
  },
  "ui": {
    "compactStatus": false,
    "showEstimates": true,
    "showVariance": true
  },
  "created": "2026-01-28T00:00:00Z",
  "updated": "2026-01-28T00:00:00Z"
}
```

### history.json

Project history for estimation and resume.

```json
{
  "version": "1.0",
  "projects": [
    {
      "id": "uuid-v4",
      "name": "my-project",
      "path": "/Users/user/projects/my-project",
      "description": "User authentication system",
      "techStack": ["node", "typescript", "postgres"],
      "started": "2026-01-25T10:00:00Z",
      "completed": "2026-01-25T14:30:00Z",
      "status": "completed",
      "phases": {
        "total": 10,
        "completed": 10
      },
      "costs": {
        "estimated": 6.52,
        "actual": 5.89,
        "variance": -9.7
      },
      "tokens": {
        "input": 1250000,
        "output": 480000
      },
      "checkpointPath": ".autopilot/checkpoint.md",
      "outcome": "success",
      "notes": "Completed under budget"
    }
  ],
  "totalProjects": 1,
  "updated": "2026-01-28T00:00:00Z"
}
```

### learnings.json

Cross-project knowledge and patterns.

```json
{
  "version": "1.0",
  "techStacks": {
    "node-typescript-postgres": {
      "seenCount": 5,
      "avgPhaseCost": {
        "setup": 0.12,
        "database": 0.35,
        "auth": 0.38,
        "api": 0.85,
        "testing": 0.45
      },
      "commonDependencies": ["express", "prisma", "jest"],
      "typicalPhaseCount": 8,
      "notes": ["Always add input validation early", "Tests save time later"]
    }
  },
  "estimationAccuracy": {
    "byPhaseType": {
      "setup": { "avgVariance": -15, "samples": 12 },
      "database": { "avgVariance": 8, "samples": 10 },
      "auth": { "avgVariance": 12, "samples": 8 },
      "api": { "avgVariance": 5, "samples": 15 },
      "testing": { "avgVariance": -5, "samples": 11 }
    },
    "overall": {
      "avgVariance": 3,
      "samples": 56
    }
  },
  "commonPatterns": [
    {
      "pattern": "API with auth",
      "requiredPhases": ["setup", "database", "auth", "api", "testing"],
      "avgTotalCost": 3.50,
      "avgDuration": "4h"
    }
  ],
  "errorPatterns": [
    {
      "error": "Missing environment variables",
      "frequency": 15,
      "solution": "Add .env.example and validation on startup",
      "preventionPhase": "setup"
    }
  ],
  "updated": "2026-01-28T00:00:00Z"
}
```

### statistics.json

Aggregate metrics across all projects.

```json
{
  "version": "1.0",
  "totals": {
    "projects": 25,
    "successfulProjects": 23,
    "failedProjects": 2,
    "totalCost": 89.45,
    "totalTokens": {
      "input": 28500000,
      "output": 11200000
    },
    "totalPhases": 187,
    "totalTasks": 1245
  },
  "averages": {
    "costPerProject": 3.58,
    "tokensPerProject": 1588000,
    "phasesPerProject": 7.5,
    "tasksPerProject": 49.8,
    "durationPerProject": "3.5h"
  },
  "accuracy": {
    "overallEstimateAccuracy": 94.5,
    "bestPhaseType": "setup",
    "worstPhaseType": "frontend",
    "improvementTrend": "+2.3%"
  },
  "timeline": {
    "firstProject": "2026-01-01T00:00:00Z",
    "lastProject": "2026-01-28T00:00:00Z"
  },
  "updated": "2026-01-28T00:00:00Z"
}
```

---

## Operations

### Initialize Global State

First time setup - create directory and default files.

```
FUNCTION initializeGlobalState():

    dir = expandPath("~/.claude/autopilot/")

    IF NOT exists(dir):
        mkdir(dir)

    # Create default config if missing
    IF NOT exists(dir + "config.json"):
        WRITE defaultConfig to dir + "config.json"

    # Create empty history if missing
    IF NOT exists(dir + "history.json"):
        WRITE emptyHistory to dir + "history.json"

    # Create empty learnings if missing
    IF NOT exists(dir + "learnings.json"):
        WRITE emptyLearnings to dir + "learnings.json"

    # Create empty statistics if missing
    IF NOT exists(dir + "statistics.json"):
        WRITE emptyStatistics to dir + "statistics.json"

    RETURN success
```

### Read Global Config

Load user preferences with defaults fallback.

```
FUNCTION getGlobalConfig():

    path = expandPath("~/.claude/autopilot/config.json")

    IF NOT exists(path):
        initializeGlobalState()

    config = parseJSON(readFile(path))

    # Merge with defaults for any missing keys
    RETURN mergeWithDefaults(config, DEFAULT_CONFIG)
```

### Update Global Config

Save configuration changes.

```
FUNCTION updateGlobalConfig(updates):

    config = getGlobalConfig()

    # Deep merge updates
    FOR key, value IN updates:
        config[key] = deepMerge(config[key], value)

    config.updated = now()

    WRITE config to "~/.claude/autopilot/config.json"

    RETURN config
```

### Add Project to History

Record a completed project.

```
FUNCTION addProjectToHistory(project):

    path = expandPath("~/.claude/autopilot/history.json")
    history = parseJSON(readFile(path))

    projectEntry = {
        id: generateUUID(),
        name: project.name,
        path: project.path,
        description: project.description,
        techStack: project.techStack,
        started: project.started,
        completed: now(),
        status: project.status,
        phases: {
            total: project.totalPhases,
            completed: project.completedPhases
        },
        costs: {
            estimated: project.estimatedCost,
            actual: project.actualCost,
            variance: calculateVariance(project.estimatedCost, project.actualCost)
        },
        tokens: project.tokens,
        checkpointPath: project.checkpointPath,
        outcome: project.outcome,
        notes: project.notes
    }

    history.autopilots.push(projectEntry)
    history.totalProjects = history.autopilots.length
    history.updated = now()

    WRITE history to path

    # Also update statistics
    updateStatistics(projectEntry)

    # And learnings
    updateLearnings(projectEntry)

    RETURN projectEntry.id
```

### Find Similar Projects

Get historical projects for estimation.

```
FUNCTION findSimilarProjects(techStack, description):

    history = getHistory()
    matches = []

    FOR project IN history.autopilots:
        score = 0

        # Tech stack similarity
        commonTech = intersection(techStack, project.techStack)
        score += commonTech.length * 20

        # Description similarity (simple keyword match)
        IF hasCommonKeywords(description, project.description):
            score += 30

        IF score >= 40:
            matches.push({
                project: project,
                similarity: score
            })

    # Sort by similarity descending
    RETURN matches.sortBy(m => m.similarity).reverse()
```

### Get Estimation Adjustment

Calculate adjustment factor from historical accuracy.

```
FUNCTION getEstimationAdjustment(phaseType, techStack):

    learnings = getLearnings()

    # Check phase-specific accuracy
    IF learnings.estimationAccuracy.byPhaseType[phaseType]:
        phaseVariance = learnings.estimationAccuracy.byPhaseType[phaseType].avgVariance
    ELSE:
        phaseVariance = 0

    # Check tech stack accuracy
    stackKey = techStack.sort().join("-")
    IF learnings.techStacks[stackKey]:
        stackData = learnings.techStacks[stackKey]
        IF stackData.avgPhaseCost[phaseType]:
            # Use historical average if we have enough data
            RETURN {
                type: "historical",
                adjustment: 1 + (phaseVariance / 100),
                confidence: "high",
                historicalCost: stackData.avgPhaseCost[phaseType]
            }

    # Fall back to general phase variance
    RETURN {
        type: "estimated",
        adjustment: 1 + (phaseVariance / 100),
        confidence: phaseVariance != 0 ? "medium" : "low",
        historicalCost: null
    }
```

### Update Learnings

Extract and store knowledge from completed project.

```
FUNCTION updateLearnings(project):

    path = expandPath("~/.claude/autopilot/learnings.json")
    learnings = parseJSON(readFile(path))

    # Update tech stack knowledge
    stackKey = project.techStack.sort().join("-")
    IF NOT learnings.techStacks[stackKey]:
        learnings.techStacks[stackKey] = {
            seenCount: 0,
            avgPhaseCost: {},
            commonDependencies: [],
            typicalPhaseCount: 0,
            notes: []
        }

    stack = learnings.techStacks[stackKey]
    stack.seenCount++
    stack.typicalPhaseCount = runningAverage(
        stack.typicalPhaseCount,
        project.phases.total,
        stack.seenCount
    )

    # Update estimation accuracy
    variance = project.costs.variance
    overall = learnings.estimationAccuracy.overall
    overall.avgVariance = runningAverage(
        overall.avgVariance,
        variance,
        overall.samples + 1
    )
    overall.samples++

    learnings.updated = now()

    WRITE learnings to path
```

### Update Statistics

Aggregate project stats.

```
FUNCTION updateStatistics(project):

    path = expandPath("~/.claude/autopilot/statistics.json")
    stats = parseJSON(readFile(path))

    # Update totals
    stats.totals.autopilots++
    IF project.outcome == "success":
        stats.totals.successfulProjects++
    ELSE:
        stats.totals.failedProjects++

    stats.totals.totalCost += project.costs.actual
    stats.totals.totalTokens.input += project.tokens.input
    stats.totals.totalTokens.output += project.tokens.output
    stats.totals.totalPhases += project.phases.total

    # Update averages
    n = stats.totals.autopilots
    stats.averages.costPerProject = stats.totals.totalCost / n
    stats.averages.tokensPerProject = (
        stats.totals.totalTokens.input +
        stats.totals.totalTokens.output
    ) / n
    stats.averages.phasesPerProject = stats.totals.totalPhases / n

    # Update accuracy
    IF project.costs.variance != null:
        accuracy = 100 - Math.abs(project.costs.variance)
        oldAcc = stats.accuracy.overallEstimateAccuracy
        stats.accuracy.overallEstimateAccuracy = runningAverage(oldAcc, accuracy, n)

    # Update timeline
    stats.timeline.lastProject = now()
    stats.updated = now()

    WRITE stats to path
```

### Get Resumable Projects

Find projects that can be resumed.

```
FUNCTION getResumableProjects():

    history = getHistory()
    resumable = []

    FOR project IN history.autopilots:
        IF project.status == "in_progress" OR project.status == "paused":
            # Check if checkpoint exists
            checkpointPath = project.path + "/" + project.checkpointPath
            IF exists(checkpointPath):
                resumable.push({
                    id: project.id,
                    name: project.name,
                    path: project.path,
                    lastActivity: project.updated OR project.started,
                    progress: (project.phases.completed / project.phases.total) * 100,
                    remainingCost: project.costs.estimated - project.costs.actual
                })

    # Sort by last activity (most recent first)
    RETURN resumable.sortBy(p => p.lastActivity).reverse()
```

---

## Default Values

### DEFAULT_CONFIG

```json
{
  "version": "1.0",
  "defaults": {
    "maxCost": 50,
    "warnCost": 10,
    "alertCost": 25,
    "maxTokens": 2000000,
    "warnTokens": 500000,
    "alertTokens": 1000000,
    "preferredModel": "sonnet",
    "autoApprove": false,
    "verboseOutput": false
  },
  "ui": {
    "compactStatus": false,
    "showEstimates": true,
    "showVariance": true
  }
}
```

### EMPTY_HISTORY

```json
{
  "version": "1.0",
  "projects": [],
  "totalProjects": 0,
  "updated": null
}
```

### EMPTY_LEARNINGS

```json
{
  "version": "1.0",
  "techStacks": {},
  "estimationAccuracy": {
    "byPhaseType": {},
    "overall": {
      "avgVariance": 0,
      "samples": 0
    }
  },
  "commonPatterns": [],
  "errorPatterns": [],
  "updated": null
}
```

### EMPTY_STATISTICS

```json
{
  "version": "1.0",
  "totals": {
    "projects": 0,
    "successfulProjects": 0,
    "failedProjects": 0,
    "totalCost": 0,
    "totalTokens": {
      "input": 0,
      "output": 0
    },
    "totalPhases": 0,
    "totalTasks": 0
  },
  "averages": {
    "costPerProject": 0,
    "tokensPerProject": 0,
    "phasesPerProject": 0,
    "tasksPerProject": 0,
    "durationPerProject": "0h"
  },
  "accuracy": {
    "overallEstimateAccuracy": 0,
    "bestPhaseType": null,
    "worstPhaseType": null,
    "improvementTrend": null
  },
  "timeline": {
    "firstProject": null,
    "lastProject": null
  },
  "updated": null
}
```

---

## Integration Points

### Commands Using Global State

| Command | Reads | Writes |
|---------|-------|--------|
| `/autopilot:takeoff` | config, history, learnings | history, learnings, statistics |
| `/autopilot:radar` | config, history, learnings | - |
| `/autopilot:cockpit` | config, history | history |
| `/autopilot:altitude --global` | config, history, statistics | - |
| `/autopilot:config` | all | config |
| `/autopilot:portfolio` | history, statistics, learnings | history (archive) |
| `/autopilot:compare` | history, learnings, statistics | - |
| `/autopilot:estimate` | history, learnings | - |

---

## Portfolio Queries

### Get All Projects

```
FUNCTION getAllProjects(filters):

    history = readJSON("~/.claude/autopilot/history.json")

    projects = history.autopilots

    # Apply filters
    IF filters.status:
        projects = projects.filter(p => p.status == filters.status)

    IF filters.stack:
        projects = projects.filter(p =>
            p.techStack.some(t => filters.stack.includes(t))
        )

    IF filters.archived !== undefined:
        projects = projects.filter(p => p.archived == filters.archived)

    # Sort by last activity
    projects.sort((a, b) =>
        new Date(b.updated || b.completed) - new Date(a.updated || a.completed)
    )

    RETURN projects
```

### Get Portfolio Summary

```
FUNCTION getPortfolioSummary():

    history = readJSON("~/.claude/autopilot/history.json")
    statistics = readJSON("~/.claude/autopilot/statistics.json")

    RETURN {
        totalProjects: history.totalProjects,
        byStatus: {
            active: countByStatus(history, "in_progress"),
            paused: countByStatus(history, "paused"),
            completed: countByStatus(history, "completed"),
            failed: countByStatus(history, "failed")
        },
        costs: {
            total: statistics.totals.totalCost,
            average: statistics.averages.costPerProject
        },
        accuracy: statistics.accuracy.overallEstimateAccuracy,
        tokens: statistics.totals.totalTokens
    }
```

### Get Project By Name

```
FUNCTION getProjectByName(name):

    history = readJSON("~/.claude/autopilot/history.json")

    # Exact match
    project = history.autopilots.find(p =>
        p.name.toLowerCase() == name.toLowerCase()
    )

    IF NOT project:
        # Partial match
        project = history.autopilots.find(p =>
            p.name.toLowerCase().includes(name.toLowerCase())
        )

    RETURN project
```

### Archive Project

```
FUNCTION archiveProject(projectId):

    history = readJSON("~/.claude/autopilot/history.json")

    project = history.autopilots.find(p => p.id == projectId)

    IF NOT project:
        ERROR "Project not found"
        RETURN false

    project.archived = true
    project.archivedAt = now()

    writeJSON("~/.claude/autopilot/history.json", history)

    LOG "Project archived: {project.name}"
    RETURN true
```

### Get Cost Analysis

```
FUNCTION getCostAnalysis():

    history = readJSON("~/.claude/autopilot/history.json")
    statistics = readJSON("~/.claude/autopilot/statistics.json")

    analysis = {
        total: statistics.totals.totalCost,
        byProject: [],
        byStatus: {},
        byStack: {},
        trend: []
    }

    # By project
    FOR each project IN history.autopilots:
        analysis.byProject.push({
            name: project.name,
            cost: project.costs.actual,
            variance: project.costs.variance
        })

    # By status
    statuses = groupBy(history.autopilots, "status")
    FOR each status, projects IN statuses:
        analysis.byStatus[status] = {
            count: projects.length,
            total: sum(projects.map(p => p.costs.actual)),
            average: avg(projects.map(p => p.costs.actual))
        }

    # By tech stack
    stacks = {}
    FOR each project IN history.autopilots:
        stackKey = project.techStack.sort().join("-")
        IF NOT stacks[stackKey]:
            stacks[stackKey] = []
        stacks[stackKey].push(project)

    FOR each stack, projects IN stacks:
        analysis.byStack[stack] = {
            count: projects.length,
            total: sum(projects.map(p => p.costs.actual)),
            average: avg(projects.map(p => p.costs.actual))
        }

    RETURN analysis
```

### When to Read Global State

1. **Session Start** - Load config defaults
2. **Cost Estimation** - Get historical accuracy adjustments
3. **Project Scan** - Find similar projects for comparison
4. **Resume** - Find resumable projects

### When to Write Global State

1. **Project Completion** - Add to history, update learnings and stats
2. **Config Changes** - User updates preferences
3. **Phase Completion** - Update estimation accuracy
4. **Checkpoint Save** - Mark project status in history

---

## Error Handling

### File Access Errors

```
TRY:
    data = readGlobalFile(filename)
CATCH FileNotFound:
    initializeGlobalState()
    data = readGlobalFile(filename)
CATCH ParseError:
    # Backup corrupted file
    mv(filename, filename + ".backup." + timestamp)
    # Create fresh default
    data = getDefaultFor(filename)
    writeFile(filename, data)
    LOG warning: "Corrupted {filename} backed up and reset"
CATCH PermissionError:
    LOG error: "Cannot access ~/.claude/autopilot/ - check permissions"
    RETURN null
```

### Data Migration

When schema version changes:

```
FUNCTION migrateIfNeeded(data, filename):

    currentVersion = SCHEMA_VERSIONS[filename]
    dataVersion = data.version OR "0.0"

    IF dataVersion < currentVersion:
        data = applyMigrations(data, dataVersion, currentVersion)
        data.version = currentVersion
        writeFile(filename, data)
        LOG "Migrated {filename} from v{dataVersion} to v{currentVersion}"

    RETURN data
```

---

## Performance Notes

- Global state files are small (<1MB typically)
- Read at session start, cache in memory
- Write atomically (temp file + rename)
- Don't re-read during execution unless explicitly needed

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.