Skip to content

[CLI] auto mode picks agent for Warp users: progress bars and colors silently disabled (TERM_PROGRAM=WarpTerminal) #4860

Description

@xbsheng

Summary

Running any hf command from a Warp terminal silently switches the CLI to agent output mode: no progress bars, no colors.

auto mode is documented as "picks human for an interactive terminal and agent when the CLI is invoked by an AI agent" (docs/source/en/guides/cli.md), but the implementation only looks at is_agent() — it never checks whether the process is attached to an interactive terminal. Since TERM_PROGRAM=WarpTerminal is set in every Warp shell (not only when Warp's Agent Mode drives a command), every human using the CLI in Warp loses progress bars.

Root cause

utils/_detect_agent.py matches the Hub registry entry:

"warp": { "envVars": { "TERM_PROGRAM": "WarpTerminal" } }

(warp is the only harness keyed on TERM_PROGRAM; same registry lives in huggingface.js/packages/tasks/src/agent-harnesses.ts:199-205, added in huggingface/huggingface.js#2222 — where the analogous Zed entry uses ZED_TERM, which only the integrated terminal sets.)

cli/_output.py:63-69 then does:

def set_mode(self, mode: OutputFormat = OutputFormat.auto) -> None:
    if mode == OutputFormat.auto:
        mode = OutputFormat.agent if is_agent() else OutputFormat.human
    self.mode = mode
    if mode != OutputFormat.human:
        disable_progress_bars()

utils/_terminal.py:102 does the same for ANSI colors (if os.environ.get("NO_COLOR") or is_agent(): return s).

Repro

hf 1.30.0 / huggingface_hub 1.30.0, macOS 15.7.5, Warp 0.2026.09.02, Python 3.10, in a real pty:

$ hf download sentence-transformers/all-MiniLM-L6-v2 model.safetensors --local-dir /tmp/x
path=/tmp/x/model.safetensors                      # 42 bytes of output, no bar, no color

$ env -u TERM_PROGRAM hf download sentence-transformers/all-MiniLM-L6-v2 model.safetensors --local-dir /tmp/x
model.safetensors:  12% 10.5M/90.9M [00:04<00:32, 2.45MB/s]
...
✓ Downloaded
  path: /tmp/x/model.safetensors

Same command, output size captured via pty.fork() (90.9 MB file):

TERM_PROGRAM interactive pty non-tty + TQDM_POSITION=-1
WarpTerminal 42 B (path=...) 0 B
Apple_Terminal 949 B (bars) bars
unset 892 B (bars) bars
xterm-256color — bars

(PI_CODING_AGENT=true / AI_AGENT=pi also trigger agent mode, which is intended. The problem is variables a terminal emulator sets for all sessions.)

Two related gaps

  1. --format human does not restore the bars. set_mode(human) changes rendering (back to ✓ Downloaded / path: ...) but never calls enable_progress_bars(), and the global disable already happened in Output.__init__. In a pty: hf download ... --format human → 61 B, still no bar.
  2. The registry is documented as attribution-only, but is now also used to decide output. Per hub-docs/docs/hub/agents-overview.md ("Register your agent harness"), registering a harness attributes Hub traffic via the user agent (utils/_headers.py:187 appends agent/warp). So human Warp users' requests are currently counted as Warp agent usage in the agent-usage dataset — same false positive, with a data-quality consequence.

Suggested fixes

  • huggingface_hub: in set_mode(auto), only pick agent when not attached to an interactive terminal (e.g. not sys.stderr.isatty()), and/or skip disable_progress_bars() when stderr is a tty. Making set_mode(human) call enable_progress_bars() also fixes the --format human case.
  • huggingface.js: key the warp entry on a variable that is only present in Agent Mode, or distinguish "attribution-only" entries from "agent-driven output" entries in the registry.

Workaround

env -u TERM_PROGRAM hf download ... (or TERM_PROGRAM= hf download ...), plus TQDM_POSITION=-1 when stderr is not a tty.

Activity

  1. SuhrudhC commented on Sep 10, 2026

    @SuhrudhC

    Hi — I'd like to work on this if it is still open.

    I checked the description against the current detection path: Warp is matched via TERM_PROGRAM=WarpTerminal in the agent harness registry, and OutputFormat.auto treats any is_agent() hit as agent mode (disabling progress bars/colors). Unlike other harnesses, that env var is set for every Warp shell, not only when Warp Agent Mode is driving the CLI — so interactive humans lose bars/colors.

    Plan (hub-side, minimal):

    1. Stop classifying Warp solely from TERM_PROGRAM=WarpTerminal for auto mode (or gate it on a Warp-Agent-only signal / interactive TTY check — happy to follow maintainer preference).
    2. Keep an explicit --output agent / env override path working.
    3. Add a unit test that TERM_PROGRAM=WarpTerminal alone does not force agent mode when stdin/stdout look interactive.
    4. Note the twin registry entry in huggingface.js if a follow-up there is needed for consistency.

    Could a maintainer assign this to me (or confirm the preferred detection rule) before I open a PR?

  2. Wauplin commented on Sep 11, 2026

    @Wauplin
    Collaborator

    Hi @xbsheng @SuhrudhC thanks for the report. If I understand correctly, the good way of fixing this would be to update the Warp Agent detection system. Currently we use

    "warp": { "envVars": { "TERM_PROGRAM": "WarpTerminal" } }
    

    to check if it runs on Warp. Is there any environment variable we could check instead that would trigger only on Warp Agent and not on all Warp sessions? If yes, then I'd be happy to review a PR in huggingface.js. If not, we might consider removing the Warp auto detection altogether 😕 (or maybe Warp itself can be updated to add a new agent-only env variable?)

    In any case, what I don't want to do is to rely on an extra flag for users to pass in their CLI, or to rely on auto-detection of TTY status. We've done that in the past, and there has never been a consistent way of being sure we can distinguish between TTY and non-TTY (there are soooo many corner cases around this...)

  3. xbsheng commented on Sep 11, 2026

    @xbsheng
    Author

    Thanks @Wauplin — and @SuhrudhC for picking this up. I dug into the Warp side before proposing anything, so here's a direct answer to your question.

    No, Warp does not set any Agent-Mode-only environment variable. An env dump from a plain, human-driven Warp terminal (local shell, no agent running) contains:

    TERM_PROGRAM=WarpTerminal
    TERM_PROGRAM_VERSION=v0.2026.09.02.08.27.stable_01
    WARP_CLIENT_VERSION=v0.2026.09.02.08.27.stable_01
    WARP_CLI_AGENT_PROTOCOL_VERSION=1    # sounds agent-related, but set in EVERY Warp shell
    WARP_IS_LOCAL_SHELL_SESSION=1
    WARP_HONOR_PS1=1
    WARP_TERMINAL_SESSION_UUID=...
    WARP_FOCUS_URL=warp://session/...
    

    TERM_PROGRAM=WarpTerminal only means "this is a Warp terminal", not "an agent is driving this command". WARP_CLI_AGENT_PROTOCOL_VERSION is the closest-sounding candidate, but it's a protocol-capability flag present in every Warp shell (feature-flag gated), never an agent marker. The only agent-ish vars I found in the Warp binary (WARP_SKILL_DIRS, WARP_SANDBOX_DEADLINE, WARP_API_KEY) belong to the separate oz / cloud-agent CLI, not to terminal Agent Mode.

    The structural reason: Warp Agent Mode doesn't spawn a new process or a new session. It writes commands into the same already-running shell session (same PTY) as the human, so the command inherits exactly the human shell's environment. There is nothing env-based to key on — a marker would have to be added by Warp itself.

    Given that, I went with removing the entry:

    • huggingface.js PR: Remove warp agent harness from registry huggingface.js#2476 — drops warp: { envVars: { TERM_PROGRAM: "WarpTerminal" } } from AGENT_HARNESSES. If Warp later ships an agent-only marker (e.g. AI_AGENT=warp / AGENT=warp or a dedicated WARP_AGENT_* var), the standard-var path picks it up with no further change. This also stops _headers.py from tagging every human Warp request as agent/warp, which was polluting the agent-usage attribution data.

    huggingface_hub PR (small, orthogonal — happy to close it if you prefer to keep the hub side untouched): #4879 — set_mode(human) now calls enable_progress_bars(), fixing the case where the CLI starts in agent mode and a later explicit --format human keeps progress bars disabled. No TTY sniffing involved.

  4. Wauplin commented on Sep 11, 2026

    @Wauplin
    Collaborator

    thanks for looking into it @xbsheng . For #4879 I closed it in favor of #4878. For the huggingface.js PR I think that's the easiest way to go. Before merging it, I'd like to know if warp maintainers are open to an env variable rather than just dropping them from the registry.

  5. SuhrudhC commented on Sep 14, 2026

    @SuhrudhC

    Thanks @Wauplin and @xbsheng — that investigation is very clear.

    I'll step back here. Removing Warp from the huggingface.js harness registry (huggingface/huggingface.js#2476) plus the Hub --format human override path looks like the right approach, especially given there's no agent-only env var today. Happy to help elsewhere if useful.

  6. added a commit that references this issue on Sep 23, 2026
    013bb34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions