Move per-session runtime state out of workspace `.claude/` into `~/.claude/projects/<encoded>/`

Resolved 💬 3 comments Opened Apr 28, 2026 by the-gigi Closed May 2, 2026

Summary

Claude Code drops per-session runtime state files into the workspace's .claude/ directory (e.g. .claude/scheduled_tasks.lock). Because .claude/ is also where users keep shared, committed project config (settings.json, agents/, commands/, skills/, hooks/), every Claude Code user ends up needing fine-grained gitignore entries to avoid accidentally committing machine/session-specific lockfiles.

This feels inconsistent with Claude Code's own conventions: project-scoped state like the auto-memory store already lives under ~/.claude/projects/<encoded-workspace-path>/.... Moving the scheduler lock (and any future ephemeral state) next to it would solve the problem without users needing to know about it.

Concrete example

After running /rev5 (a personal skill that uses ScheduleWakeup), the workspace gains:

.claude/scheduled_tasks.lock

Contents are intrinsically per-machine:

{"sessionId":"...","pid":92776,"procStart":"Tue Apr 28 18:34:21 2026","acquiredAt":1777409137527}

Two failure modes:

  1. Accidental commitgit add . from a developer who's not paying attention bakes a stale sessionId/PID into the repo. Anyone who later checks out the repo could have a Claude Code session think the lock is held by a process that doesn't exist.
  2. Gitignore tax — every project that uses Claude Code has to figure out the right surgical gitignore (a blanket /.claude/ over-ignores the shared config; you have to enumerate each runtime path). This is a paper cut that scales linearly with the number of repos a user works in.

Proposed fix

Store ephemeral, per-session state under ~/.claude/projects/<encoded-workspace-path>/ alongside the existing memory directory. The encoded-path scheme already in use (e.g. ~/.claude/projects/-Users-gigi-git-prplx-space/memory/) gives you the per-workspace key without polluting the workspace itself.

Files I'd expect to move:

  • scheduled_tasks.lock (and any pending-task state for ScheduleWakeup / CronCreate)
  • Anything else currently written into workspace .claude/ that isn't user-authored config

Files that should stay in workspace .claude/:

  • settings.json (shared project settings)
  • settings.local.json (per-developer overrides — already gitignored by convention)
  • agents/, commands/, skills/, hooks/ — explicitly-authored project assets

Why this matters

The user-facing fix is one-line gitignore entries per repo, but the upstream fix is a one-time path change in Claude Code that benefits every user forever. Strongly preferred to externalize this paper cut once rather than have N teams each rediscover and document it.

Environment

  • Claude Code: latest (Opus 4.7 1M)
  • macOS Darwin 24.5.0

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗