Skip to main content

State System & Multi-Session Workflows

Learn how AILANG's state system enables persistent, multi-session development workflows with Claude Code skills.

Overview

AILANG provides a sophisticated state management system that enables multi-day sprints, agent handoffs, and session continuity. Unlike traditional AI assistants that lose context when you close them, AILANG's state system persists progress across sessions.

Key Innovation

The state system gives Claude Code a "hard drive" - work persists across sessions, days, or weeks!

Three Integrated Systems

1. AILANG Messaging System

Built into AILANG itself (Go implementation), provides persistent message passing between agents.

Storage: ~/.ailang/state/collaboration.db (SQLite)

Full CLI reference (send/list/read/ack/unack/forward/search) lives in the Agent Messaging guide.

Inbox types:

  • User inbox: Messages for the human developer
  • Agent inboxes: Messages for specific agents (sprint-planner, sprint-executor, etc.)

2. JSON State Files

Structured progress tracking for long-running tasks like sprints.

Location: .ailang/state/sprints/sprint_<id>.json

Purpose:

  • Track milestone completion (passes: true/false/null)
  • Record actual LOC vs estimates
  • Store velocity metrics
  • Enable multi-session continuity

Example:

{
"sprint_id": "M-TESTING-INLINE",
"status": "in_progress",
"milestones": [
{
"id": "M1",
"description": "Pipeline Integration",
"passes": true,
"actual_loc": 210,
"started": "2025-11-27T09:00:00Z",
"completed": "2025-11-27T15:00:00Z"
},
{
"id": "M2",
"description": "Examples & Tests",
"passes": null,
"started": "2025-11-27T15:00:00Z"
}
]
}

3. Claude Code Skills

Specialized workflows following Anthropic's October 2025 specification.

Location: .claude/skills/<skill-name>/

Key skills:

  • sprint-planner - Creates plans, sends handoffs
  • sprint-executor - Executes plans, reads state
  • agent-inbox - Checks messages from agents

How They Work Together

Complete Workflow Example

Session 1: Planning (15 minutes)

# Start Claude Code
You: "Plan sprint for inline testing"

# sprint-planner skill activates automatically
✓ Analyzes design docs
✓ Checks recent velocity (31 LOC/day)
✓ Discovers feature is 90% complete!
✓ Creates sprint plan:
design_docs/planned/v0_4_2/M-TESTING-INLINE-COMPLETION-SPRINT.md

✓ Creates JSON state:
.ailang/state/sprints/sprint_M-TESTING-INLINE.json

✓ Sends handoff message:
ailang messages send sprint-executor '{"type":"plan_ready","sprint_id":"M-TESTING-INLINE"}' \
--title "Sprint: M-TESTING-INLINE" --from "sprint-planner"

# Message persists in:
~/.ailang/state/collaboration.db

# You close Claude Code
# Days pass... no memory retained in Claude

Session 2: Start Implementation (next day)

# You open Claude Code (fresh session, no memory)
You: "Start the sprint"

# sprint-executor skill activates
✓ Checks inbox:
ailang messages list --unread --inbox sprint-executor

✓ Finds message from sprint-planner:
"plan_ready" for M-TESTING-INLINE

✓ Loads JSON state:
.ailang/state/sprints/sprint_M-TESTING-INLINE.json

✓ Shows summary:
╔═══════════════════════════════════════════╗
║ Sprint M-TESTING-INLINE ║
╚═══════════════════════════════════════════╝

Status: not_started
Progress: 0/2 milestones

Next: M1 - Pipeline Integration (8 hours)
- Create executor.go
- Update runner.go
- Write unit tests

✓ Begins work with TDD:
1. Write test first
2. Implement code
3. Run make test && make lint
4. Update JSON: {"id": "M1", "passes": true}
5. Commit code

# You work for 6 hours, complete M1
# Need to stop for the day

You: "Pause sprint"

✓ Updates JSON:
{
"status": "paused",
"last_checkpoint": "M1 complete, M2 ready to start",
"milestones": [
{"id": "M1", "passes": true, "actual_loc": 210}
]
}

# You close Claude Code
# A week passes...

Session 3: Resume Work (a week later)

# You open Claude Code (fresh session, no memory of last week)
You: "Continue the sprint"

# sprint-executor skill activates
✓ Loads JSON state (no inbox check needed - state is current)

✓ Shows "Here's where we left off":
╔═══════════════════════════════════════════╗
║ Sprint M-TESTING-INLINE ║
╚═══════════════════════════════════════════╝

Status: paused
Progress: 1/2 milestones complete

Completed:
✓ M1: Pipeline Integration (210 LOC, 6 hours)

Next:
→ M2: Examples & Tests (4-6 hours)
- Fix examples/testing_basic.ail
- Update examples/factorial.ail
- Write integration tests

Last checkpoint: "M1 complete, M2 ready to start"
Velocity: 35 LOC/hour (on track!)

✓ Continues implementation from exactly where it left off
✓ NO manual recap needed
✓ NO context lost

Directory Structure

your-project/
├── .claude/ # Claude Code skills (IDE-local)
│ └── skills/
│ ├── sprint-planner/ # Creates plans & handoffs
│ └── sprint-executor/ # Executes plans, tracks progress

├── .ailang/ # AILANG state (persistent)
│ └── state/
│ ├── sprints/ # Sprint progress tracking
│ │ ├── sprint_M-TESTING-INLINE.json
│ │ ├── sprint_M-DX11.json
│ │ └── sprint_M-POLY-B.json
│ │
│ └── collaboration.db # Agent messaging (SQLite)

└── design_docs/
└── planned/v0_4_2/
└── M-TESTING-INLINE-COMPLETION-SPRINT.md

Inspecting State from the Command Line

The state is plain JSON + SQLite, so everything is inspectable without Claude:

# Sprint progress at a glance
jq '.milestones[] | {id, passes, actual_loc}' \
.ailang/state/sprints/sprint_M-TESTING-INLINE.json

# Multiple sprints run in parallel — one JSON file each
ls .ailang/state/sprints/

# Messages waiting for an agent
ailang messages list --inbox sprint-executor --unread

Because state survives crashes and session loss, recovery is just "Resume sprint M-TESTING-INLINE" in a fresh session — the skill reloads the JSON and continues from the last checkpoint.

Technical Details

Message Format

Messages use JSON with standard fields:

{
"type": "plan_ready",
"correlation_id": "sprint_M-TESTING-INLINE_2025-11-27",
"sprint_id": "M-TESTING-INLINE",
"plan_path": "design_docs/planned/v0_4_2/M-TESTING-INLINE-COMPLETION-SPRINT.md",
"progress_path": ".ailang/state/sprints/sprint_M-TESTING-INLINE.json",
"estimated_duration": "1-2 days (10-14 hours)",
"milestones": [
{
"id": "M1",
"name": "Pipeline Integration",
"estimated_hours": 8
}
],
"discovery": "Feature is 90-95% complete!",
"total_loc_estimate": 400,
"risk_level": "low"
}

State File Schema

Sprint JSON files follow a consistent schema:

{
"sprint_id": "M-TESTING-INLINE",
"created": "2025-11-27T09:00:00Z",
"status": "in_progress",
"plan_path": "design_docs/...",
"milestones": [
{
"id": "M1",
"description": "Pipeline Integration",
"estimated_loc": 200,
"actual_loc": 210,
"passes": true,
"started": "2025-11-27T09:00:00Z",
"completed": "2025-11-27T15:00:00Z",
"notes": "Completed ahead of schedule"
}
],
"velocity": {
"target_loc_per_day": 150,
"actual_loc_per_day": 35,
"estimated_total_loc": 400,
"actual_total_loc": 210
},
"last_session": "2025-11-27T15:00:00Z",
"last_checkpoint": "M1 complete, M2 ready"
}

Best Practices

1. Commit State Files

# Track sprint progress in git
git add .ailang/state/sprints/sprint_*.json
git commit -m "Update sprint progress: M1 complete"

2. Regular Checkpoints

# After completing each milestone:
You: "Update sprint checkpoint"
# Claude updates JSON with latest progress

3. Clear Messages

# When sending custom messages, include context:
ailang messages send sprint-executor "Pause: need to context-switch to urgent bug. M2 50% complete. Resume 2025-11-28." \
--title "Pause request" --from "user"

4. Clean Up Old Sprints

# Archive completed sprints
mkdir -p .ailang/state/sprints/archive
mv .ailang/state/sprints/sprint_M-OLD.json \
.ailang/state/sprints/archive/

Troubleshooting

State not loading → validate the JSON: jq -e . .ailang/state/sprints/<file>.json. Messages not appearing → see the Agent Messaging guide. Two sessions edited the same sprint → the state is git-tracked JSON; diff, merge by hand, commit.

Further Reading