Task-list tools (TaskCreate/TaskUpdate/TaskList/TaskGet) no longer exposed to the model after recent update (tasks still visible in UI)

Status Open
Reported on v2.1.217
Maintainer reply None cached
Activity 17 comments · opened Jul 22, 2026

Summary

As of the most recent Claude Code update, task-list tools are no longer exposed to the model in any session. Tools such as TaskCreate / TaskUpdate / TaskList / TaskGet are simply not present in the tool set, so the model can no longer create, read, or modify tasks. This affects every session, across all worktrees of the project.

Crucially, the tasks are still fully visible in the user-facing UI — so the task list and its data are intact. The regression is specifically that the model-facing tools to interact with that list have disappeared. This narrows it to a tool-exposure regression, not data loss or a bad task-list configuration.

Environment

  • Claude Code 2.1.217 (regression observed after updating to this version)
  • Windows 11 Pro (win32)
  • Project configured with a persistent task list: CLAUDE_CODE_TASK_LIST_ID=kibitzr is set in the environment

Observed behavior

  • The task-list tools (TaskCreate, TaskUpdate, TaskList, TaskGet) are absent from the available/deferred tool set. A tool lookup for those names returns "No matching tools."
  • The tasks themselves remain visible and correct in the user-facing UI, confirming the underlying list is unaffected — only the model's tool access is gone.
  • Only TaskOutput and TaskStop are present, and those are the deprecated background-process controls (for background shells/agents), not task-list tools.
  • CLAUDE_CODE_TASK_LIST_ID is still correctly set (kibitzr), so the task list itself is configured — but there is no tool surface to interact with it.
  • The model therefore cannot add or update tasks; the on-disk task list can only be hand-edited, which was previously discouraged in favor of the native tools.

Expected behavior

Sessions should expose the native task-list tools (as they did prior to this update) so the model can create and modify tasks in the configured task list.

Impact

Any workflow that relies on the shared/persistent task list as the source of truth is broken — the model can no longer record new tasks, mark progress, or update task state. Multiple concurrent sessions are all affected simultaneously, which points to a global (build/config) regression rather than a per-session or per-project issue.

Notes

  • CLAUDE_CODE_TASK_LIST_ID being set but no task tools appearing suggests the tools were dropped from the exposed tool set (or gated off) in this release, rather than a bad task-list-id configuration.

View original on GitHub ↗

17 Comments

DrunkOnJava · 2 months ago

Confirming this on macOS arm64 (native install, Ghostty, Max plan) — with evidence that it is not a 2.1.217 client regression. It's a remote flag flip, and the title's "after recent update" framing will mislead the bisect.

Not version-specific

  • Fresh interactive sessions on 2.1.217 AND 2.1.216 (pinned binary, launched directly from ~/.local/share/claude/versions/2.1.216) both come up without TaskCreate/TaskUpdate/TaskList/TaskGet and without the TodoWrite fallback. ToolSearch select:TaskCreate,... returns no match in either.
  • Sessions started before Jul 21 ~15:20 PT keep their tools, including across a 2.1.215 → 2.1.217 resume (one of mine logged 46 TaskUpdate calls on 2.1.217 turns hours after fresh 2.1.217 sessions had lost the tools).
  • Affected on claude-fable-5 AND claude-opus-4-8, in multiple projects, with a clean env (no CLAUDE_CODE_ENABLE_TASKS, no deny rules, no --agent/--bare/--tools, no proxy).
  • Headless (claude -p) is unaffected on both versions — consistent with #78769's finding that print mode skips the live flag fetch.

Cache evidence

~/.claude.json on my machine, fetched Jul 21:

cachedGrowthBookFeatures.tengu_vellum_ash = ["claude-opus-4-8","claude-sonnet-5","claude-fable-5"]

This matches the gating #78769 extracted from the binary: the TaskCreate family registers with isEnabled = VR() && !XJ() and TodoWrite with !VR() && !XJ(), where XJ() matches the current model against the tengu_vellum_ash list — so when the flag fires, both task-tracking families disappear with no fallback, and CLAUDE_CODE_ENABLE_TASKS=1 cannot override it.

Workaround verified (including hot-reload)

Per #78769:

  1. ~/.claude/settings.json env: "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
  2. Clear cachedGrowthBookFeatures.tengu_vellum_ash to [] in ~/.claude.json

The tools came back in an already-running session via config hot-reload — ToolSearch resolved all four schemas and TaskCreate worked immediately, no restart. Downside of the workaround: it also disables update checks, /bug, and error reporting, which is a heavy price for a documented core feature.

Likely duplicates of the same flip

#79949 (calls it a remote config flip, same cached value, "not a version thing"), #79900 (2.1.216), #79695 (2.1.216, GrowthBook), #79836 (intermittent "exists but is not enabled"), #79791 (remote-control sessions, Jul 21), #80034 (mid-session loss after /login re-fetch), and #78769 (mechanism; filed Jul 18 when the flag apparently covered fewer models).

Ask

If tengu_vellum_ash is an intentional A/B for the task system, the current state still looks like a misfire: it hides both the Task family and the TodoWrite fallback simultaneously, leaving no task tracking at all, and no env override wins. Either keep the fallback alive under the experiment, let CLAUDE_CODE_ENABLE_TASKS=1 override the gate, or revert the Jul 21 flip.

NubeBuster · 2 months ago
[!IMPORTANT] Updated 2026-07-28 — the one-shot script in this comment has changed. Do not use a copy you saved earlier. It now also sets CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF=1, applying @hw5511's two-variable recipe from #79949. The original set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC alone, which fixes the Task tools but collapses every GrowthBook flag to its hardcoded default — silently taking unrelated features down with it. It cost me plugin channels six days later; write-up in Collateral damage at the bottom. If you already ran the old version, adding that one env var is the entire delta — or just re-run the current script, it is idempotent. The superseded original is preserved further down, collapsed.

---

Linux x86_64, native install, claude-opus-4-8. Adding a pre-flip counter-example, a version data point, a repo-side check — and, as of 2026-07-28, what the workaround itself breaks.

---

I had some claude code sessions with model Fable open since 2.1.214 was latest.
Resuming them by sending a new message today made me switch to opus-4.8 because fable is no longer provided in my subscription plan.

Correction: Fable 5 is still included with your Max plan. If you see a prompt to set up usage credits for it, restart Claude Code.

Applying the workarounds mentioned in this issue discussion fixed the issue in the live sessions without requiring claude code to restart.

One-shot for anyone else hitting this. Paste into a terminal — it is idempotent, backs up every file it touches to *.bak, preserves all other keys, honours CLAUDE_CONFIG_DIR, refuses to touch unparseable JSON, and warns if a higher-precedence scope would override the fix. Takes effect in already-running sessions via hot-reload; no restart needed.

Two caveats on that "no restart", both learned since: it holds because the script writes the env block in settings.json, which Claude Code re-reads — if you instead export these at the OS level, an already-running editor keeps its stale environment block and you get the pre-fix behaviour, as @hw5511 describes above. And it applies to flag evaluation only: channel registration happens once at session start, so anything channel-related needs a fresh session regardless of hot-reload.

Edited 2026-07-28 — second env var added, applying @hw5511's two-variable recipe from #79949; see the banner at the top of this comment. The superseded original is collapsed below.

<details>
<summary><b>Current script</b> — updated 2026-07-28 (click to expand, run at own risk)</summary>

python3 - <<'PY'
import json, os, shutil, sys

FLAG = "tengu_vellum_ash"
VARS = {
    # stops the startup fetch that would re-populate the flag
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
    # ...and makes the remaining ~429 flags read your disk cache instead of
    # collapsing to hardcoded defaults. First-party auth only (see note below).
    "CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF": "1",
}
home = os.path.expanduser("~")
cfg = os.environ.get("CLAUDE_CONFIG_DIR") or os.path.join(home, ".claude")


def load(path):
    """Return (data, ok). ok=False means present-but-unparseable: never overwrite those."""
    if not os.path.exists(path):
        return {}, True
    try:
        with open(path) as fh:
            return json.load(fh), True
    except Exception as e:
        print(f"  ! {path} is not valid JSON ({e}) — skipped, fix it by hand")
        return None, False


def save(path, data):
    if os.path.exists(path):
        shutil.copy2(path, path + ".bak")
    os.makedirs(os.path.dirname(path) or ".", exist_ok=True)
    tmp = path + ".tmp"
    with open(tmp, "w") as fh:
        json.dump(data, fh, indent=2)
    os.replace(tmp, path)


changed = []

# 1. Clear the cached flag. .claude.json may sit next to the config dir or in $HOME.
for path in {os.path.join(home, ".claude.json"), os.path.join(os.path.dirname(cfg) or home, ".claude.json")}:
    if not os.path.exists(path):
        continue
    d, ok = load(path)
    if not ok:
        continue
    feats = d.get("cachedGrowthBookFeatures") or {}
    if feats.get(FLAG):
        print(f"  flag was: {json.dumps(feats.get(FLAG))}")
        feats[FLAG] = []
        d["cachedGrowthBookFeatures"] = feats
        save(path, d)
        changed.append(path)
    else:
        print(f"  flag already empty or absent in {path}")

# 2. Set the env vars in user settings (env blocks merge across scopes, so this suffices).
settings = os.path.join(cfg, "settings.json")
d, ok = load(settings)
if ok:
    env = d.setdefault("env", {})
    missing = {k: v for k, v in VARS.items() if env.get(k) != v}
    if not missing:
        print(f"  env vars already set in {settings}")
    else:
        env.update(missing)
        save(settings, d)
        changed.append(settings)
        for k in missing:
            print(f"  set {k}={missing[k]} in {settings}")

# 3. Warn if a higher-precedence scope explicitly disables it (would beat the write above).
higher = [
    "/etc/claude-code/managed-settings.json",
    "/Library/Application Support/ClaudeCode/managed-settings.json",
    "C:\\ProgramData\\ClaudeCode\\managed-settings.json",
    os.path.join(os.getcwd(), ".claude", "settings.json"),
    os.path.join(os.getcwd(), ".claude", "settings.local.json"),
]
for path in higher:
    if not os.path.exists(path) or os.path.abspath(path) == os.path.abspath(settings):
        continue
    d, ok = load(path)
    if not ok:
        continue
    for k, v in VARS.items():
        cur = d.get("env", {}).get(k)
        if cur not in (None, v):
            print(f"  !! {path} sets {k}={cur} and outranks user settings — change it there too")

# 4. DISABLE_GROWTHBOOK outranks the disk-cache path entirely — it must be UNSET.
KILL = "DISABLE_GROWTHBOOK"
hits = []
if os.environ.get(KILL):
    hits.append("the process environment")
for path in [settings, *higher]:
    if not os.path.exists(path):
        continue
    dd, dok = load(path)
    if dok and dd.get("env", {}).get(KILL):
        hits.append(path)
if hits:
    print(f"  !! {KILL} is set in: " + ", ".join(hits))
    print("     While it is set, CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF cannot engage,")
    print("     so every flag still collapses to its hardcoded default. Unset it.")

# 5. The disk-cache path is first-party only; on Bedrock/Vertex it never engages.
if os.environ.get("CLAUDE_CODE_USE_BEDROCK") or os.environ.get("CLAUDE_CODE_USE_VERTEX"):
    print("  !! Bedrock/Vertex detected — CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF")
    print("     has no effect there, so your other flags will still fall back to defaults.")

print()
if changed:
    print("patched (backups alongside as *.bak):")
    for p in changed:
        print("  -", p)
    print("\nTakes effect in already-running sessions via hot-reload; no restart needed.")
else:
    print("nothing to change — already applied, or the flag was never set for you.")
    sys.exit(0)
PY

</details>

All three pieces matter, and they do different jobs:

  • Clearing the cached flag alone is undone by the next startup fetch.
  • CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 suppresses that fetch — but on its own it also stops flag evaluation, so every other flag falls back to its hardcoded default.
  • CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF=1 puts evaluation back on the disk cache, so only tengu_vellum_ash — the value you just edited — differs from what the server last sent you.

Two conditions on that last one, both from @hw5511's gate dump above and both now checked by the script: it requires first-party auth (no effect on Bedrock/Vertex), and it requires DISABLE_GROWTHBOOK to be unset — that variable short-circuits the disk-cache path as well as the fetch, so setting it alongside gets you the hardcoded defaults anyway.

env blocks merge across settings scopes, so writing user settings.json works even if you also have /etc/claude-code/managed-settings.json — verified here by observing managed-only and user-only vars simultaneously present in the session environment.

Revert by restoring the *.bak files once this is fixed upstream — the traffic var also disables update checks, /bug, and error reporting, and while it is set your flag cache is frozen at its last live fetch, so genuinely new server-side features will not reach you.

<br>

<details>
<summary>~~Original script~~ — superseded 2026-07-28, kept for reference (do not run)</summary>

⚠️ Do not run this one. It is the version the confirmations above refer to, kept so those comments still point at something real. It sets CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC only, which fixes the Task tools while silently disabling every other default-off flag-gated feature. Use the current script above.
python3 - <<'PY'
# !! SUPERSEDED 2026-07-28 — this version sets CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
# !! only, which disables other flag-gated features (channels, Monitor, ...).
# !! Use the current script in the comment above instead.
import json, os, shutil, sys

FLAG = "tengu_vellum_ash"
VAR = "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"
home = os.path.expanduser("~")
cfg = os.environ.get("CLAUDE_CONFIG_DIR") or os.path.join(home, ".claude")


def load(path):
    """Return (data, ok). ok=False means present-but-unparseable: never overwrite those."""
    if not os.path.exists(path):
        return {}, True
    try:
        with open(path) as fh:
            return json.load(fh), True
    except Exception as e:
        print(f"  ! {path} is not valid JSON ({e}) — skipped, fix it by hand")
        return None, False


def save(path, data):
    if os.path.exists(path):
        shutil.copy2(path, path + ".bak")
    os.makedirs(os.path.dirname(path) or ".", exist_ok=True)
    tmp = path + ".tmp"
    with open(tmp, "w") as fh:
        json.dump(data, fh, indent=2)
    os.replace(tmp, path)


changed = []

# 1. Clear the cached flag. .claude.json may sit next to the config dir or in $HOME.
for path in {os.path.join(home, ".claude.json"), os.path.join(os.path.dirname(cfg) or home, ".claude.json")}:
    if not os.path.exists(path):
        continue
    d, ok = load(path)
    if not ok:
        continue
    feats = d.get("cachedGrowthBookFeatures") or {}
    if feats.get(FLAG):
        print(f"  flag was: {json.dumps(feats.get(FLAG))}")
        feats[FLAG] = []
        d["cachedGrowthBookFeatures"] = feats
        save(path, d)
        changed.append(path)
    else:
        print(f"  flag already empty or absent in {path}")

# 2. Set the env var in user settings (env blocks merge across scopes, so this suffices).
settings = os.path.join(cfg, "settings.json")
d, ok = load(settings)
if ok:
    if d.get("env", {}).get(VAR) == "1":
        print(f"  {VAR} already set in {settings}")
    else:
        d.setdefault("env", {})[VAR] = "1"
        save(settings, d)
        changed.append(settings)

# 3. Warn if a higher-precedence scope explicitly disables it (would beat the write above).
higher = [
    "/etc/claude-code/managed-settings.json",
    "/Library/Application Support/ClaudeCode/managed-settings.json",
    "C:\\ProgramData\\ClaudeCode\\managed-settings.json",
    os.path.join(os.getcwd(), ".claude", "settings.json"),
    os.path.join(os.getcwd(), ".claude", "settings.local.json"),
]
for path in higher:
    if not os.path.exists(path) or os.path.abspath(path) == os.path.abspath(settings):
        continue
    d, ok = load(path)
    if ok and d.get("env", {}).get(VAR) not in (None, "1"):
        print(f"  !! {path} sets {VAR}={d['env'][VAR]} and outranks user settings — change it there too")

print()
if changed:
    print("patched (backups alongside as *.bak):")
    for p in changed:
        print("  -", p)
    print("\nTakes effect in already-running sessions via hot-reload; no restart needed.")
else:
    print("nothing to change — already applied, or the flag was never set for you.")
    sys.exit(0)
PY

</details>

~~Both steps matter: clearing the cached flag alone is undone by the next startup fetch, which is what the env var suppresses. env blocks merge across settings scopes, so writing user settings.json works even if you also have /etc/claude-code/managed-settings.json — verified here by observing managed-only and user-only vars simultaneously present in the session environment.~~ ~~Revert by restoring the *.bak files once this is fixed upstream — the env var also disables update checks, /bug, and error reporting.~~

---

2.1.214 is affected, and pre-flip sessions do _not_ keep their tools

A session whose transcript starts 2026-07-18 04:08 UTC — three days before the flip — is stamped version: 2.1.214 on every entry including today's. The installed version here is 2.1.217, so a fresh launch or --continue would be stamped 2.1.217: this is the original long-lived 2.1.214 process, not a resume onto a new binary.

| When (UTC) | What |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Jul 18 04:09 – 08:45 | 76 successful TaskCreate/TaskUpdate calls |
| Jul 18 08:45 → Jul 22 05:04 | idle (~4 days) |
| Jul 22 05:04:17 | resumed with a new user message |
| Jul 22 05:06:57 | TaskUpdate, TaskList → No such tool available: TaskUpdate. TaskUpdate exists but is not enabled in this context. |

So the gate is re-evaluated mid-process, not pinned at process start, and 2.1.214 is below the range tested so far. "Started before Jul 21 ~15:20 PT" is not the discriminator — being idle across the flip and used again is enough.

Three follow-ons:

  • #79836 is not a separate intermittent bug — its "exists but is not enabled" wording is exactly this.
  • /login is not required for mid-session loss (cf. #80034); grep for /login in that transcript returns 0.
  • The TUI still rendered the existing task list while the model could not read or modify it, matching the title.

---

No client release could have caused this

The published v2.1.214...v2.1.217 diff touches only CHANGELOG.md, feed.xml, and a new examples/gateway/aws/ tree:

curl -sL https://github.com/anthropics/claude-code/compare/v2.1.214...v2.1.217.diff \
  | grep -cE 'TaskCreate|TaskUpdate|TaskList|TaskGet|TodoWrite'   # -> 0

The title's "after recent update" framing should probably be dropped.

---

Still being served as of 2026-07-22 05:09 UTC

A fresh startup fetch wrote tengu_vellum_ash = ["claude-opus-4-8","claude-sonnet-5","claude-fable-5"] — identical to the Jul 21 macOS value, so it had not been reverted ~14h later and the same list goes out across platforms. Note the 05:06:57 failure above _precedes_ that 05:09:47 cache write, so the cache timestamp is not the moment the gate takes effect.

---

Notes

  • The workaround also works from /etc/claude-code/managed-settings.json, not just user settings.json, and restored all four tools via hot-reload in an already-running session — useful if you're deploying it fleet-wide.
  • CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 does not exempt you. With teams enabled the task list is the coordination surface between teammates, so the flag takes that out too.
  • TaskOutput/TaskStop survive — background-process tools, unrelated to the gated family. Reports saying "the task tools are gone" are ambiguous without that split.
  • claude-fable-5 stopped being offered on resume, forcing sessions onto claude-opus-4-8 — also on the list, so switching models doesn't dodge the gate.

---

Collateral damage: the traffic var alone silently kills plugin channels (added 2026-07-28)

Six days after applying my own workaround I lost inbound MCP channel notifications and spent a while looking for the wrong culprit, because the only trace is one --debug line that names no cause:

[DEBUG] MCP server "<plugin>": Channel notifications skipped: channels feature is not currently available

Channel registration is gated on tengu_harbor, whose hardcoded default is false — so with CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 and nothing else, it evaluates false no matter what the server sent you. My cache held tengu_harbor: true the entire time; it was simply never consulted. Everything else on the registration path was fine — the plugin declares the capability, channelsEnabled: true is set, the plugin is on the allowlist and passed via --channels — the flag was the only blocker. Adding CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF=1 restored it on the next launch (Linux x86_64, native, 2.1.220, first-party, Max).

To be clear about what this does and doesn't fix: it restores channels that worked before you set the traffic var. If channels never worked for you, this changes nothing — that's #74303 / #36460 territory.

Same collapse @hw5511 documented, reached by a different route: theirs came from DISABLE_GROWTHBOOK=1, mine from CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 on its own. Two triggers, one outcome — and the traffic var is the one this thread hands out, so it is the path most people here are on.

Counting the reports scattered across these threads, that collapse now has five known casualties, every one found by accident days later:

| What dies | Gate | Reported in |
| --- | --- | --- |
| Monitor, RemoteTrigger, PushNotification, EndConversation | tengu_amber_sentinel | #79949 — @hw5511 |
| Remote Control (/rc absent) | — | #78769 — @aschoettler |
| Hosted Artifacts (Artifact tool + artifact-design / artifact-capabilities skills) | — | #78769 — @gulp |
| Opus 4.6 1M context on eligible plans | — | #34178 |
| Plugin channels (inbound MCP notifications) | tengu_harbor | this comment |

The oldest is #34178, filed at 2.1.75 asking that feature entitlements not depend on telemetry configuration. Auto-closed as inactive, argued against in comments, closed again, locked. #45918 later filed the channels case by name ("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC blocks channels feature flag (tengu_harbor)") and was auto-closed as a duplicate — of that locked issue. Neither mentions the disk-cache var, so anyone routed there today is still told the choice is telemetry-or-no-channels.

Which is the wider point for this issue: telling users to disable nonessential traffic to dodge an A/B flip hands them an unbounded, unannounced feature regression. The blast radius is every default-off flag in the build, nothing in the UI says so, and no user can enumerate what they lost.

Fuller write-up, including why Tasks and Artifacts//rc are not actually mutually exclusive (cf. @gulp above): my follow-up comment.

mokelly · 2 months ago

I confirm that the Clear cachedGrowthBookFeatures.tengu_vellum_ash to [] in ~/.claude.json proposal fixed the problem for me, and agree that the root problem was not a version bump -- just coincident. Thanks to all for the help!

cmaga · 2 months ago

Posted consolidated evidence in #75577 (https://github.com/anthropics/claude-code/issues/75577#issuecomment-5058318002): the tengu_vellum_ash gate oscillates server-side (empty on 2026-07-15 and briefly on 2026-07-22, repopulated since), and the tool roster locks at session startup — so concurrent same-model sessions on one machine can disagree about whether the task tools exist. Includes verified dead ends for local workarounds.

fqx · 2 months ago

I can see todo list now, is it solved?

NubeBuster · 2 months ago

I've edited my one-shot script above to apply @hw5511's two-variable recipe from #79949 — CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 plus CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF=1. My original set the traffic var alone, which fixes the Task tools but collapses every flag to its hardcoded default.

Two things worth having in this thread: a casualty of that collapse nobody had named yet, and the fact that the decoupling several people here have asked for already exists.

The unnamed casualty: plugin channels

One --debug line, no warning, no UI change:

[DEBUG] MCP server "<plugin>": Channel notifications skipped: channels feature is not currently available

Channel registration is gated on tengu_harbor, hardcoded default false. My disk cache held tengu_harbor: true the whole time — it was simply never consulted. Nothing else was wrong: capability declared, channelsEnabled: true, plugin allowlisted and passed via --channels. The flag was the only blocker. The two-var recipe restored it on the next launch (Linux x86_64, native, 2.1.220, first-party, Max).

Scope: this restores channels that worked before you set the traffic var. If channels never worked for you it changes nothing — that's #74303 / #36460.

Tasks vs. Artifacts / /rc is not mutually exclusive

@gulp reported (#78769) that the workaround forces a choice — Task tools or hosted Artifacts and Remote Control — and asked for "a per-flag local override (bootstrapping tengu_vellum_ash: [] without blocking all nonessential traffic)".

That override exists today. CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF=1 is exactly it: evaluation reads your on-disk cachedGrowthBookFeatures instead of collapsing to defaults, so the one array you edited is the only value that differs from what the server last sent. Tasks and Artifacts and /rc at once. It is undocumented, which is why this thread converged on the blunt lever instead.

Two conditions, both from @hw5511's Eug() dump (above) and both now enforced by my script:

  • first-party auth only — no effect on Bedrock/Vertex;
  • DISABLE_GROWTHBOOK must be unset — Eug() contains !Z.DISABLE_GROWTHBOOK, so it kills the disk-cache path too. Set both and you are back on defaults with nothing indicating the rescue var did nothing.

One channels-specific caveat: flag changes hot-reload, but channel registration happens once at session start, so channels need a fresh session either way.

Five casualties, five people who found them by accident

| What silently dies | Gate | Reported in |
| --- | --- | --- |
| Monitor, RemoteTrigger, PushNotification, EndConversation | tengu_amber_sentinel | #79949 — @hw5511 |
| Remote Control (/rc) | — | #78769 — @aschoettler |
| Hosted Artifacts (Artifact tool + artifact-design / artifact-capabilities skills) | — | #78769 — @gulp |
| Opus 4.6 1M context on eligible plans | — | #34178 |
| Plugin channels (inbound MCP notifications) | tengu_harbor | this comment |

Not one was found by looking — each surfaced days later when something unrelated stopped working.

The oldest is #34178, filed at 2.1.75 asking that feature entitlements not depend on telemetry configuration. Auto-closed as inactive, argued against in comments, closed again, locked. #45918 later filed the channels case by name and was auto-closed as a duplicate — of that locked issue. Neither mentions the disk-cache var, so anyone routed there today is still told the choice is telemetry-or-no-channels.

So: the recipe in this thread works and I've updated mine to match. The remaining ask is documentation and decoupling. CLAUDE_CODE_GB_DISK_CACHE_WHEN_TELEMETRY_OFF is currently discoverable only by decompiling the binary, and the lever people find first has an unbounded blast radius with no in-product signal about what it took away.

noenteas · 1 month ago

Same regression on Linux, with a reproduction and two data points that may help narrow it down.

Environment

  • Claude Code 2.1.233, native install
  • Ubuntu 24.04.4 LTS, kernel 7.0.0-28-generic
  • Ghostty, TERM=xterm-ghostty, started as plain claude from the terminal — no wrapper script

Symptom — identical to #86929: TaskCreate, TaskUpdate, TaskGet, TaskList and TodoWrite are all absent from the model's tool set. Only Task, TaskOutput and TaskStop remain.

Reproduction — the system init event lists the session's tools, so this needs no interactive guesswork:

claude -p "ok" --output-format=stream-json --verbose --max-turns 1 \
  | head -1 \
  | jq -c '{total: (.tools|length), task: [.tools[] | select(startswith("Task") or contains("odo"))]}'

Output here:

{"total":98,"task":["Task","TaskOutput","TaskStop"]}

Does not fix it

  • "todoFeatureEnabled": true set explicitly in ~/.claude/settings.json
  • CLAUDE_CODE_ENABLE_TASKS=1 — identical tool list with and without it, 98 tools either way
  • No permissions.deny, no --disallowedTools, no project-level settings files

Two data points

  1. The isTTY theory from #80160 does not hold here. This session's stdin and stdout are both /dev/pts/0 — a real interactive TTY, launched directly from the terminal with no .bat or wrapper indirection, no git-bash in the path. The tools are missing anyway. The headless -p run above reproduces it too, so the behaviour is the same with and without a TTY.
  1. The tools appear to be present in the build and simply not exposed to the main loop. In two sessions on this same version where the claude-security plugin's orchestrator agent was driving, TaskCreate/TaskUpdate calls do appear in the transcripts (~90 across the two), and that agent declares those tools in its own definition. I have not verified this from the source, but it is consistent with the main-loop tool set omitting them rather than the tools being disabled build-wide.

#87057 looks like the same issue reported without repro steps.

noenteas · 1 month ago

Correcting my earlier comment: there is a working workaround, and the gate turns out to be model-dependent rather than a plain regression.

Workaround — in ~/.claude/settings.json:

"env": { "CLAUDE_CODE_ENABLE_TODO_TOOLS": "1" }

TaskCreate, TaskGet, TaskList and TaskUpdate come back immediately. On 2.1.233 it applied to my already-running session without a restart. Verified with the same probe as before:

without the env var: ["Task","TaskOutput","TaskStop"]
with    the env var: ["Task","TaskCreate","TaskGet","TaskList","TaskOutput","TaskStop","TaskUpdate"]

Why it happens. The gate in the 2.1.233 bundle reduces to:

if (currentModelIsOutsideList) return true;                          // tools enabled
if (env.CLAUDE_CODE_ENABLE_TODO_TOOLS === true) return true;         // tools enabled
return featureFlag("tengu_rosy_wren", false) === true;               // otherwise, server flag decides

with the list being [["opus",[4,8]], ["sonnet",[5]], ["fable",[5]], ["mythos",[5]]].

So the tools are withheld only for models in that list, and for those they depend on either the env var or the tengu_rosy_wren feature flag. That flag is absent from my cached feature set, which is why the tools never appeared. This would explain why the issue looks intermittent across users and why switching models mid-session did not help the reporter of #80160 — Opus and Sonnet are both on the list.

One more correction to my previous comment: CLAUDE_CODE_ENABLE_TASKS cannot enable anything. Its implementation is if (env.CLAUDE_CODE_ENABLE_TASKS === false) return false; return true — it is an off switch only. Setting it to 1, as suggested in #80160, is a no-op.

If the model list is intentional, the tools being silently absent with no diagnostic is the real bug — nothing in /doctor, /config or the docs points at CLAUDE_CODE_ENABLE_TODO_TOOLS.

jpjonte · 1 month ago

I'm surprised there's so little discussion about this. The task list is very useful for visualizing Claude's progress on a task.

duaneking · 1 month ago

I'm not a fan of this defect, and would like to respectfully request that this be fixed as soon as possible.

The model is looking like it's just not giving access to that toolset and if I activate them I'm getting messages like:

● The task tools just surfaced. Loading them and putting the list in properly.

It doesn't make any sense to remove these tools when they are core to the functionality of the system for so many loops.

justinhall02 · 1 month ago

Still present on v2.1.246 (latest as of 2026-08-26), model claude-opus-4-8. Adding data that narrows the regression window and flags a previously-working workaround that has since stopped working.

Symptom: Fresh interactive sessions have no TaskCreate / TaskList / TaskUpdate / TaskGet in the toolset (a ToolSearch select:TaskCreate,TaskList returns no matches), so the task panel stays blank and cannot be populated. Long-running sessions that were started on an older build keep their working task tools; only freshly launched sessions are affected — which is why, on the same machine, some panes have tasks and others come up empty.

Version bisect (same machine, same account, same model, fresh interactive sessions):

  • 2.1.231 — TaskList is present and callable (verified an actual TaskList tool call succeeding).
  • 2.1.246 — TaskCreate/TaskList absent.
  • So the regression landed between 2.1.231 and 2.1.246.

The DISABLE_GROWTHBOOK=1 workaround from #80566 no longer works on 2.1.246. Launching with DISABLE_GROWTHBOOK=1 CLAUDE_CODE_ENABLE_TASKS=1 still yields no task-list tools in a fresh interactive session. In the 2.1.246 binary the string tengu_vellum_ash is no longer present (DISABLE_GROWTHBOOK and CLAUDE_CODE_ENABLE_TASKS still are), so whatever gates the tools now, disabling GrowthBook does not re-enable them.

How tested: launched an interactive session on each version, had it attempt a TaskList call and report whether the tool exists. -p/headless mode never exposes the task-list tools regardless, so the check has to be interactive.

Net: the only thing that restores the task panel today is running a pre-regression build (e.g. 2.1.231). It would help a lot to get the tools re-enabled for these models, or the gate exposed as a documented, stable setting.

duaneking · 1 month ago

This is still not fixed, and the workarounds given are not always working. It just completely randomly loses its full task list, in the worst case hours of work from a days session suddenly gone, and then I have to ask it to use its session to try to recover that work which is not always something that we can do (it doesn't seem to be able to fully understand what it lost from the journal history in every case) , Task create and task list are critical for getting work done, it's insane that these randomly drop, here now suddenly gone until I set a env value (again, because its losing it, somehow), and I'm finding that I'm using the competition more because of that because I can't wait for this to get fixed , This is actively making developers I know give up on Anthropic models and Claude because it's so unstable that we can't get work done, fix this, PLEASE. We MUST have working Task* tools.

NubeBuster · 1 month ago

@duaneking

Please note, the following text is generated through speech to text by Whisper X. It's custom Whisper X implementation. There might be transcription mistakes.

However, even if it looks AI-generated, it is my speech transcribed without any changes.

---

Are you referring to having difficulty recovering tasks from the list once it loses its tools? Either I can share or perhaps or maybe just suggest I made Claude generate a system service for Linux that would it sets up a I notify watcher for the team directories in .Claude. And on any file change, it will commit this file change to a single Git repository locally. So this will be a point in time recovery system for teams, inboxes and tasks so that you can literally do a point in time recovery to any of these files. I can either recommend you to make your own version, or I could share this at your request. It's not very thoroughly tested, but this is my method for making at least recovery less painful. I've personally also made a system separately that will automatically recover tasks for a session that was stopped or forked or some other reason to very easily just recover the tasks from a different session or the same session which could also be useful let me know if you're interested and i can spend a little bit of time to make a gist or get repository even for it for this system

carlosdealmeida · 1 month ago

Disclosure: I maintain Claude Todos, an open-source VS Code/JetBrains panel that reads the task list from the transcripts Claude Code writes, so this change hit us directly. A few data points that may help others landing here:

  • Verified on 2.1.261 (the binary bundled with the VS Code extension): with no flag, a fresh session on Opus 5 / Fable 5 has only TaskOutput and TaskStop. Adding "env": { "CLAUDE_CODE_ENABLE_TODO_TOOLS": "1" } to ~/.claude/settings.json brings the tools back on any model, including sessions started by the VS Code extension — a session that was already running picked them up without a restart.
  • They come back as deferred tools (the model loads them through ToolSearch), and which schema you get depends on the environment: with CLAUDE_CODE_ENABLE_TASKS=0 (what the VS Code extension sets) it is TodoWrite; otherwise TaskCreate/TaskUpdate.
  • +1 on documenting the env var outside the changelog and on having the model say the task list is off for this model rather than that the tool is missing. Until then, our panel detects the state (harness ≥ 2.1.233, newer model, flag absent from user/project settings and env) and offers a one-click switch that writes that key after a confirmation, in case it is useful to anyone — see the README section "Turn the task tools back on" (v0.19.0).
rusterholz · 1 month ago

Has there been any response from an official Anthropic engineer on this?

jcogilvie · 1 month ago

https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md

Todo/task-tracking tools (TaskCreate/Get/Update/List, TodoWrite) are no longer available on Opus 4.8, Sonnet 5, Fable 5, Mythos 5, and newer models; set CLAUDE_CODE_ENABLE_TODO_TOOLS=1 to bring them back

I understand that this removal is intentional, but TODOs are not just for agents; they are a great way for me as a human to track what work remains to be done.

NubeBuster · 1 month ago
I understand that this removal is intentional, but TODOs are not just for agents; they are a great way for me as a human to track what work remains to be done.

Precisely. The agents are slow enough that I generally have 5 sessions running agents or solo. If they don't have tasks I cannot even understand what they're saying. I wouldn't be able to use Claude Code if I didn't have a PTY wrapper.
One of the things it does is prevent jokes like the task tools disappearing etc.