Skip to content

Display-only hook for assistant messages (show real values to the user while the model sees redacted tokens) #5099

Description

@Zidane786

Describe the feature or problem you'd like to solve

A hook that changes what the user sees for an assistant message without changing what the model sees. Today a postToolUse hook can redact sensitive values in a tool result (modifiedResult.textResultForLlm) so the model only sees tokens like <EMAIL_1>. But nothing can turn those tokens back into the real values on screen, so the user is stuck reading <EMAIL_1> too.

Proposed solution

Add a display-only hook event for assistant output, for example messageDisplay / MessageDisplay:

  • Input: the assistant text as it streams (or the whole message when it's done), plus sessionId and a message id.
  • Output: displayContent, the text to render in place of the original. Leaving it out shows the original.
  • Display only: the session history, the model's context and --output-format json keep the original text, so the model never sees the replacement.
  • Fail-open: on error or timeout, show the original text.

This is the reverse of userPromptTransformed, which today changes what the model gets while "the prompt displayed in the timeline is unaffected".

Claude Code ships this as the MessageDisplay hook (hookSpecificOutput.displayContent). It would also help plugins that target both CLIs, since Copilot CLI already accepts Claude-style PascalCase hooks.

Example prompts or workflows

  1. Keep PII away from the model. An MCP server returns customer records. A postToolUse hook replaces emails and phone numbers with <EMAIL_1>, <PHONE_1> and keeps the mapping locally. The model answers "Contact <EMAIL_1> about the refund", and the display hook shows the real email to the user.
  2. Internal identifiers. Swap internal hostnames or account IDs for tokens before the model sees them, and show the real values on screen.
  3. Shown differently, not hidden. Turn ticket IDs into clickable links, or mark up text on screen, without changing what the model sees or what's stored in the history.

Additional context

  • Tested on Copilot CLI 1.0.94: redacting with postToolUse → modifiedResult works (the model only sees the token), but the user also sees only the token.
  • --secret-env-vars and streamer mode only hide values. They can't put the real value back for the user.
  • Claude Code reference: https://code.claude.com/docs/en/hooks (MessageDisplay).
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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions