# NousResearch/hermes-agent · Kanban board env variable not inherited by subprocesses

## Open now

- 0 issues, 1 PR open on GitHub.
- PR #142272: fix(skills): kanban env gate misreads chat-boot BOARD pin as worker identity

A bug where HERMES_KANBAN_BOARD is not correctly pinned or propagated to subprocess environments, causing board mis-routing during agent/chat sessions. Multiple fix attempts address environment variable inheritance at CLI and terminal levels.

## TL;DR

- 5 member(s): 0 open issue(s), 1 closed issue(s), 1 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #20186. Verify it addresses your case.
- **Recommended:** read PR #20186 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-20186`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.40`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #20074: \[Bug\]: harness kanban CLI invoked from agent session ignores active-board pin, races current file with concurrent boards switch

## Prior & competing PRs

- **#20186: fix(cli): pin HERMES_KANBAN_BOARD at chat boot to stop subprocess board drift (salvages #20094)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `hermes_cli/main.py`, `tests/hermes_cli/test_pin_kanban_board_env.py`
  - fix hunks:
  - `hermes_cli/main.py`

    ```diff
    @@ -1216,6 +1216,26 @@ def _launch_tui(
         sys.exit(code)
     
     
    +def _pin_kanban_board_env() -> None:
    +    """Pin the active kanban board into ``HERMES_KANBAN_BOARD`` for the chat session.
    +
    +    Without this, in-process tools (``kanban_*``) and shelled-out CLI calls
    +    (``hermes kanban …``) resolve the board on different paths: the env-pin if
    +    set, otherwise the global ``<root>/kanban/current`` file. A concurrent
    +    ``hermes kanban boards switch`` from another session can flip the file
    +    mid-turn, so the same chat sees its tool calls hit board A while its shell
    +    calls hit board B (#20074). Pinning at chat boot mirrors what the
    +    dispatcher already does for spawned workers.
    +    """
    +    if os.environ.get("HERMES_KANBAN_BOARD"):
    +        return
    +    try:
    +        from hermes_cli.kanban_db import get_current_board
    +        os.environ["HERMES_KANBAN_BOARD"] = get_current_board()
    +    except Exception:
    +        pass
    +
    +
     def cmd_chat(args):
         """Run interactive chat CLI."""
         use_tui = getattr(args, "tui", False) or os.environ.get("HERMES_TUI") == "1"
    ```

    ```diff
    @@ -1324,6 +1344,8 @@ def cmd_chat(args):
         if getattr(args, "source", None):
             os.environ["HERMES_SESSION_SOURCE"] = args.source
     
    +    _pin_kanban_board_env()
    +
         if use_tui:
             _launch_tui(
                 getattr(args, "resume", None),
    ```
  - `tests/hermes_cli/test_pin_kanban_board_env.py`

    ```diff
    @@ -0,0 +1,75 @@
    +"""Tests for `_pin_kanban_board_env` helper invoked by `cmd_chat`.
    +
    +Regression coverage for #20074: a chat session must export the active kanban
    +board into `HERMES_KANBAN_BOARD` at boot so subprocess shell-outs (e.g.
    +`hermes kanban …`) inherit the same board the in-process kanban tools resolve.
    +Without this, a concurrent `hermes kanban boards switch` from another session
    +can flip the global current-board file mid-turn and silently divert the
    +shell calls to a different DB.
    +"""
    +import importlib
    +import os
    +
    +import pytest
    +
    +
    [redacted:email](autouse=True)
    +def _isolate_kanban_board_env():
    +    """Snapshot `HERMES_KANBAN_BOARD` and restore it after the test.
    +
    +    `_pin_kanban_board_env()` writes to ``os.environ`` directly, bypassing
    +    any ``monkeypatch.setenv`` tracking. Without this fixture the mutation
    +    leaks into subsequent tests and breaks anything that resolves a kanban
    +    path from the env (e.g. ``TestSharedBoardPaths`` in test_kanban_db.py).
    +    """
    +    prev = os.environ.get("HERMES_KANBAN_BOARD")
    +    os.environ.pop("HERMES_KANBAN_BOARD", None)
    +    try:
    +        yield
    +    finally:
    +        if prev is None:
    +            os.environ.pop("HERMES_KANBAN_BOARD", None)
    +        else:
    +            os.environ["HERMES_KANBAN_BOARD"] = prev
    +
    +
    +def test_pin_writes_resolved_board_when_env_unset(monkeypatch):
    +    main_mod = importlib.import_module("hermes_cli.main")
    +
    +    import hermes_cli.kanban_db as kdb
    +    monkeypatch.setattr(kdb, "get_current_board", lambda: "space")
    +
    +    main_mod._pin_kanban_board_env()
    +
    +    assert main_mod.os.environ.get("HERMES_KANBAN_BOARD") == "space"
    +
    +
    +def test_pin_does_not_overwrite_existing_env(monkeypatch):
    +    monkeypatch.setenv("HERMES_KANBAN_BOARD", "preset")
    +    main_mod = importlib.import_module("hermes_cli.main")
    +
    +    import hermes_cli.kanban_db as kdb
    +
    +    def _explode():
    +        raise AssertionError("get_current_board must not be called when env is set")
    +
    +    monkeypatch.setattr(kdb, "get_current_board", _explode)
    +
    +    main_mod._pin_kanban_board_env()
    +
    +    assert main_mod.os.environ.get("HERMES_KANBAN_BOARD") == "preset"
    +
    +
    +def test_pin_swallows_resolution_failures(monkeypatch):
    +    main_mod = importlib.import_module("hermes_cli.main")
    +
    +    import hermes_cli.kanban_db as kdb
    +
    +    def _boom():
    +        raise RuntimeError("disk gone")
    +
    +    monkeypatch.setattr(kdb, "get_current_board", _boom)
    +
    +    main_mod._pin_kanban_board_env()
    +
    +    assert "HERMES_KANBAN_BOARD" not in main_mod.os.environ
    ```
- **#20094: fix(cli): pin HERMES_KANBAN_BOARD at chat boot to stop subprocess board drift**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#20186`
- **#36742: fix(terminal): propagate HERMES_KANBAN_BOARD to subprocess env to prevent board mis-routing**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `b22b3f506a34cf848d68bb2ab17b68b0bc8ec152`
- **#142272: fix(skills): kanban env gate misreads chat-boot BOARD pin as worker identity**. open
  - maintainer direction: category `silent_close`; implication `active`
  - files: `agent/skill_utils.py`, `tests/agent/test_skill_env_kanban_gate.py`

## Fix status

- Merged to main in PR #20186 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-05-05`.
- Subsystem: `environments`
