feat(claude-code): add {user_id} retainTags template variable#1161
Merged
nicoloboschi merged 3 commits intovectorize-io:mainfrom Apr 20, 2026
Merged
feat(claude-code): add {user_id} retainTags template variable#1161nicoloboschi merged 3 commits intovectorize-io:mainfrom
nicoloboschi merged 3 commits intovectorize-io:mainfrom
Conversation
Resolve {user_id} from HINDSIGHT_USER_ID env var in retainTags and
retainMetadata. After template resolution, tags whose namespace part is
empty (e.g. 'user:' when HINDSIGHT_USER_ID is unset) are dropped from
the outgoing retain request, so a single portable config works whether
or not the user id is set.
Existing behavior preserved: empty/None retainTags -> tags=None; tags
without ':' are never dropped; fully-resolved tags with non-empty
content pass through unchanged.
Four new cases in TestRetainHook:
- {user_id} resolves from HINDSIGHT_USER_ID env var (via _run_hook's
extra_env, since the helper strips real HINDSIGHT_* env vars by design)
- dangling 'user:' is dropped when env is unset; other tags survive
- colon-less tags are preserved regardless of env state
- all-dropped tags produce a request with no 'tags' field
Full suite: 133 passed.
- README: expand retainTags description to enumerate all four template
placeholders ({session_id}, {bank_id}, {timestamp}, {user_id}), add a
Template variables reference table, and add a per-user memory scoping
example showing HINDSIGHT_USER_ID usage and recall filter pattern.
- retainMetadata description updated to note shared template support.
- CHANGELOG: add [Unreleased] section with Added (new template var) and
Changed (dangling-tag drop semantics) entries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
{user_id}template variable toretainTags/retainMetadata, resolved fromHINDSIGHT_USER_ID."<ns>:"(empty post-colon segment). Tags without:are untouched.Fixes #1160.
What
scripts/retain.py: extendtemplate_varswith"user_id": os.environ.get("HINDSIGHT_USER_ID", ""), rewrite the tag-resolution loop to drop dangling namespaced tags (logged viadebug_log).tests/test_hooks.py: four new cases inTestRetainHook.{user_id}is injected via_run_hook'sextra_env(the helper strips realHINDSIGHT_*vars by design).README.md: expandedretainTagsdescription, template variables reference table, per-user scoping example.CHANGELOG.md:[Unreleased]Added / Changed entries.How
template_vars["user_id"]is resolved once and applies to bothretainTagsandretainMetadatabecause_resolve_templateis shared.After
_resolve_template, the loop skips any tag where":" in resolved and resolved.split(":", 1)[1] == "". Colon-less tags never match the guard, so backward compat is preserved by construction. If every tag drops,tagsis normalized toNone;HindsightClient.retain's existing field-omission path (client.py:144—if tags: item["tags"] = tags) then omits the field from the outgoing request.Test plan
pytest tests/test_hooks.py -v -k retain_tag→ 5 passed (1 existing + 4 new).pytest tests/ -v→ 133 passed, no regression.