microsoft/shadow-frog-update
>- Update the shadow knowledge base after code changes and from conversational insights. Detects what changed via git diff, refreshes per-file shadows, captures knowledge shared by the user during the session, and updates cross-cutting discoveries. Invoke manually with /shadow-frog-update; the preToolUse hook will remind the agent when the shadow is behind HEAD.
npx skills add https://github.com/microsoft/ShadowFrog --skill shadow-frog-update
Updates .shadow/ from two sources: code changes (git diff) and conversational
knowledge (what the user said during the session). Prerequisite: .shadow/ exists.
preToolUse injects a staleness warning when.shadow/_meta/state.json#last_commit differs from HEAD. The hook
only reminds — it does NOT auto-run update.
/shadow-frog-update# Read last_commit defensively: it may be missing, or the literal "none"
# when init ran without git (e.g. inside a container). `git diff none HEAD`
# would abort with "fatal: bad revision 'none'", and a missing key would
# make $LAST_COMMIT empty so `git diff HEAD` silently reports the wrong set.
LAST_COMMIT=$(python3 -c "import json,sys; print(json.load(sys.stdin).get('last_commit','none'))" < .shadow/_meta/state.json 2>/dev/null || echo "none")
if git rev-parse --verify "$LAST_COMMIT" >/dev/null 2>&1; then
git diff --name-only "$LAST_COMMIT" HEAD # committed changes since last update
else
echo "WARNING: state.json has no usable last_commit — falling back to a full re-scan."
fi
git diff --name-only HEAD # uncommitted changes
git diff --name-only --cached # staged changes
Categorize: modified, added, deleted, renamed.
For each changed file, update its shadow at the symbol level:
## sectionREMOVED, keep discoveries for historyLightweight update (auto/hook): re-extract symbols, update headings, flag stale.
Deep update (manual/dream): read diffs, generate new discoveries, verify existing ones.
When the user shares knowledge during the session, write it immediately.
Do not batch for later.
Signals to capture:
| Signal | Example | Category |
|--------|---------|----------|
| Warning | "Don't change the retry logic, it's subtle" | warning |
| Design intent | "We use this pattern because the API is unreliable" | intent |
| History | "We tried caching here but it caused stale reads" | history |
| Gotcha | "This looks wrong but matches the tax authority spec" | warning |
| Deprecation | "This module is being replaced by v2/" | intent |
| Contract | "The 30s timeout matches our SLA" | contract |
| Convention | "Always use the helper in utils.py, not raw SQL" | convention |
Write as:
- <user's words, as close to verbatim as possible>
_(verified, source: user)_
For knowledge emerging from collaborative work (debugging, refactoring, test failures):
- <what was discovered and how>
_(verified, source: interaction)_
Anchor to the specific file::symbol. source: user and source: interaction
are always verified.
Users will not specify where to store their knowledge. You must find the
correct location. Procedure:
class names, module names, variable names, error messages, CLI flags.
references (e.g., "always use snake_case", "no backward compatibility",
"prefer small PRs") → write to _prefs.md.
file::symbol paths in_index.md and the corresponding shadow files.
grep -rl "<keyword>" .shadow/ --include="*.md"knowledge applies to. Prefer a single file::symbol over file-level.
_cross/<slug>.mdentry and add back-pointers to each involved file's ## Cross-References.
For 2-file discoveries, use per-file entries with Also involves: instead.
the shadow) → place at the file-level ## File-Level section of the most
relevant file, or create a new _cross/ entry for repo-wide knowledge.
Never ask the user "where should I put this?" — always resolve placement yourself.
At session end or manual trigger, review the session for:
_cross/<slug>.md if 3+ files involved)Added files:
.shadow/.shadowignore — skip if the file matches an ignore pattern.shadow/<path>/<file>.md with symbol-organized template## Cross-References section_index.mdDeleted files:
ORPHANED marker to shadow header[REMOVED] on any _cross/ refs pointing to this file_index.mdRenamed files:
.shadow/<old>.md to .shadow/<new>.md_cross/ Refs: entries (old path → new path)Also involves: in other per-file shadows_index.mdFollow the dedup and writing rules in /shadow-frog — read before
write, merge or update existing entries, fix bad format in place.
Verify exploration discoveries using the observe-based or do-based
methods in /shadow-frog § Verification. source: user and
source: interaction → always verified; only re-verify if the
underlying code changes.
Check the five core invariants (full 7-invariant set in /shadow-frog):
_cross/<slug>.md ref has a back-pointer in per-file ## Cross-References## Cross-References entry has a corresponding _cross/<slug>.mdAlso involves: use file::symbol notationRepair any violations before proceeding.
Preserve dream_cycles_completed from the existing state — only dream-reconcile.py increments it.
{
"version": 1,
"initialized_at": "<preserved>",
"last_update_at": "<now ISO>",
"last_commit": "<full 40-char HEAD SHA>",
"last_update_type": "init|auto|manual|dream|meditate",
"total_files": N,
"total_symbols": N,
"total_discoveries": N,
"dream_cycles_completed": <preserved>
}
Refresh _index.md with current counts.
See /shadow-frog § Discovery Format for the verbatim per-file,
cross-cutting, and preference formats. Rules to keep in mind during
update sessions:
source: user and source: interaction → always verified, use user's own wordssource: exploration → mark uncertain unless verified by code reading or tests_cross/<slug>.md instead, add back-pointers_prefs.mdtoken-expiry-config-split.md)REMOVED, keep discoveriessource: user discoveries → only mark stale if symbol completely removedTake microsoft/shadow-frog-update from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.