Smith — Update to Latest
SkillAI & modelsUpdate Smith to the latest upstream version. Compares the installed commit SHA against https://github.com/ATTCKDigital/smith main, prompts to update if behind, and refreshes global install (~/.claude/skills, ~/.claude/hooks, ~/.smith) plus per-project artifacts (.specify/scripts, .claude/commands/smith.*, CLAUDE.md / constitution.md via migrate-templates, optional manifest sidecar bootstrap). Workflow-gate compliant.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Smith — Update to Latest skill
What this skill tells your AI
The instructions your AI receives, as published by attckdigital/smith in skills/smith-update/SKILL.md and read by ahel’s review.
End-to-end skill for keeping Smith up to date. Detects local-vs-upstream commit drift, prompts to update, and runs the existing installer plus per-project refresh steps when invoked inside a Smith-initialized project.
Arguments: $ARGUMENTS (no positional args; reserved for future flags like --check / --no-project)
When to Use
- "is smith out of date?" / "update smith" / "let's update smith"
- After learning of a new Smith feature you want to adopt
- After an old project's
.smith/index/was generated against an earlier manifest schema and needs regeneration
Vault Logging
Throughout this action, log significant events to the vault session log. Read the session log path from .smith/vault/.current-session. If the file is missing or the vault is not initialized, skip all logging silently.
Format:
### [HH:MM:SS] /smith-update <event>
**User Request:**
> <verbatim user message that triggered this action>
**Synthesized Input:** <brief summary>
**Outcome:** <what happened>
**Artifacts:** <files created/modified>
**Systems affected:** smith-update (smith-repo distribution)
Log at: invocation, after version detection (with SHAs + commits-behind), after global update, after per-project update, on completion.
Natural Language Triggers
If the user says any of these (or similar), treat as invoking this command:
- "update smith"
- "let's update smith"
- "is smith out of date"
- "smith is behind"
- "pull the latest smith"
Phase 0: Activate Workflow Tracking (Workflow-Gate Compliance)
/smith-update writes many files: install.sh's destructive cp -R of skills, the version file, settings.json merge, per-project script copies, etc. The PreToolUse workflow-gate hook (PR #20) would deny all of these without an active marker. So create the marker first.
Skip if no .smith/ directory exists in the current working directory (the gate naturally exits silent in that case per PR #20, so no marker is needed). Otherwise:
TS=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
PROJECT_DIR=$(pwd)
if [ -d "$PROJECT_DIR/.smith" ]; then
mkdir -p "$PROJECT_DIR/.smith/vault/active-workflows"
cat > "$PROJECT_DIR/.smith/vault/active-workflows/update-${TS}.yaml" << EOF
workflow: smith-update
feature: smith-version-sync
branch: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)
started: ${TS//-/:}
EOF
# remember marker path for cleanup at end
MARKER_PATH="$PROJECT_DIR/.smith/vault/active-workflows/update-${TS}.yaml"
fi
The marker is removed in Phase 6 cleanup (or on exit-with-no-changes paths). Use the shipped helper so it works under a Bash(rm:*) deny rule:
[ -n "${MARKER_PATH:-}" ] && [ -f "$MARKER_PATH" ] && \
"$PROJECT_DIR/.specify/scripts/bash/clear-active-workflow.sh" "update-${TS}" 2>/dev/null || true
Phase 1: Detect Upstream and Installed Versions
UPSTREAM_REMOTE="https://github.com/ATTCKDigital/smith.git"
SMITH_HOME="$HOME/.smith"
VERSION_FILE="$SMITH_HOME/.installed-version"
# Upstream SHA (network call — graceful on failure per Q4)
UPSTREAM_OUT=$(git ls-remote "$UPSTREAM_REMOTE" refs/heads/main 2>&1)
if [ $? -ne 0 ]; then
echo "Unable to reach upstream — $UPSTREAM_OUT" >&2
# cleanup marker, exit cleanly
exit 0
fi
UPSTREAM_SHA=$(echo "$UPSTREAM_OUT" | awk '{print $1}')
# Installed SHA (per Q2-D: handle absent file by establishing baseline)
if [ -f "$VERSION_FILE" ]; then
INSTALLED_SHA=$(cat "$VERSION_FILE" | tr -d ' \n\r')
else
# First invocation since /smith-update shipped. Establish baseline silently.
mkdir -p "$SMITH_HOME"
echo "$UPSTREAM_SHA" > "$VERSION_FILE"
echo "Smith is up to date — version baseline established at ${UPSTREAM_SHA:0:7}."
# cleanup marker, exit
exit 0
fi
Phase 2: Compute Commits-Behind
Per Q5-A: gh first, shallow-clone fallback.
COMMITS_BEHIND=""
if command -v gh >/dev/null 2>&1; then
COMMITS_BEHIND=$(gh api "repos/ATTCKDigital/smith/compare/${INSTALLED_SHA}...${UPSTREAM_SHA}" --jq '.ahead_by' 2>/dev/null)
fi
if [ -z "$COMMITS_BEHIND" ] || ! [[ "$COMMITS_BEHIND" =~ ^[0-9]+$ ]]; then
# Fallback: shallow-clone the upstream and use git rev-list --count.
TMPCLONE=$(mktemp -d -t smith-update-XXXXXX)
trap 'rm -rf "$TMPCLONE"' EXIT # extended at Phase 6 to include marker cleanup
if ! git clone --quiet "$UPSTREAM_REMOTE" "$TMPCLONE/smith" 2>/dev/null; then
echo "Unable to reach upstream — clone failed." >&2
exit 0
fi
COMMITS_BEHIND=$(git -C "$TMPCLONE/smith" rev-list --count "${INSTALLED_SHA}..${UPSTREAM_SHA}" 2>/dev/null || echo "?")
fi
# Up-to-date short-circuit
if [ "$COMMITS_BEHIND" = "0" ]; then
echo "Smith is up to date (commit ${UPSTREAM_SHA:0:7})."
exit 0
fi
# Prompt
echo "Smith is $COMMITS_BEHIND commits behind. Update? (y/n)"
read -r REPLY
case "$REPLY" in
[yY]|[yY][eE][sS]) ;;
*) echo "Update declined."; exit 0 ;;
esac
Phase 3: Snapshot (Q7-A Rollback Safety)
Before any destructive work, snapshot the global install state. On non-zero exit from install.sh, restore.
BACKUP_ROOT="$SMITH_HOME/.backups"
BACKUP_DIR="$BACKUP_ROOT/update-${TS}"
mkdir -p "$BACKUP_DIR"
# Snapshot the three writable areas
cp -R "$HOME/.claude/skills" "$BACKUP_DIR/skills" 2>/dev/null || true
cp -R "$HOME/.claude/hooks" "$BACKUP_DIR/hooks" 2>/dev/null || true
cp "$HOME/.claude/settings.json" "$BACKUP_DIR/settings.json" 2>/dev/null || true
# GC: keep last 3 (Q7-A keep-last-N policy)
ls -t "$BACKUP_ROOT" 2>/dev/null | tail -n +4 | while read -r old; do
rm -rf "$BACKUP_ROOT/$old"
done
# Restore function — invoked if install.sh fails
restore_snapshot() {
echo "Update failed — restoring from $BACKUP_DIR" >&2
rm -rf "$HOME/.claude/skills" "$HOME/.claude/hooks"
cp -R "$BACKUP_DIR/skills" "$HOME/.claude/skills" 2>/dev/null || true
cp -R "$BACKUP_DIR/hooks" "$HOME/.claude/hooks" 2>/dev/null || true
cp "$BACKUP_DIR/settings.json" "$HOME/.claude/settings.json" 2>/dev/null || true
}
Phase 4: Global Update
Clone smith-repo to a temp dir (or reuse the one from Phase 2's fallback), run installer, write version file.
if [ -z "${TMPCLONE:-}" ] || ! [ -d "$TMPCLONE/smith" ]; then
TMPCLONE=$(mktemp -d -t smith-update-XXXXXX)
trap 'rm -rf "$TMPCLONE"' EXIT
git clone --quiet "$UPSTREAM_REMOTE" "$TMPCLONE/smith"
fi
# Q1-D settings.json dedupe BEFORE running install.sh, so the installer's
# jq merge doesn't compound onto existing duplicates. Dedupe ONLY Smith-owned
# hook entries (those referencing ~/.claude/hooks/<known-name>.sh).
"$TMPCLONE/smith/scripts/dedupe-settings.sh" "$HOME/.claude/settings.json" 2>/dev/null || true
# Run the installer
if ! "$TMPCLONE/smith/scripts/install.sh" -y; then
restore_snapshot
echo "install.sh failed. Restored from snapshot at $BACKUP_DIR." >&2
exit 1
fi
# install.sh now writes $SMITH_HOME/.installed-version itself (this PR adds that),
# but write it again here defensively in case install.sh was pre-versioning.
echo "$UPSTREAM_SHA" > "$VERSION_FILE"
Phase 5: Per-Project Update (Conditional)
Only runs if $PROJECT_DIR/.smith/ exists. Refresh Smith-owned files; never touch user files; offer manifest bootstrap if .smith/index/ is absent.
5.1 Refresh .specify/scripts/bash/ and .claude/commands/smith.*
Smith-owned files. Safe to overwrite. Detect orphans first (Q6-A + Q8-B unified pass).
if [ -d "$PROJECT_DIR/.smith" ]; then
# Collect orphans before copying new files.
UPSTREAM_SCRIPTS="$TMPCLONE/smith/skills/smith/scripts"
LOCAL_SCRIPTS="$PROJECT_DIR/.specify/scripts/bash"
ORPHAN_SCRIPTS=()
if [ -d "$LOCAL_SCRIPTS" ]; then
for f in "$LOCAL_SCRIPTS"/*; do
name=$(basename "$f")
[ -f "$UPSTREAM_SCRIPTS/$name" ] || ORPHAN_SCRIPTS+=("$name")
done
fi
UPSTREAM_CMDS="$TMPCLONE/smith/skills/smith/commands"
LOCAL_CMDS="$PROJECT_DIR/.claude/commands"
ORPHAN_CMDS=()
if [ -d "$LOCAL_CMDS" ]; then
for f in "$LOCAL_CMDS"/smith.*.md; do
[ -e "$f" ] || continue
name=$(basename "$f")
[ -f "$UPSTREAM_CMDS/$name" ] || ORPHAN_CMDS+=("$name")
done
fi
UPSTREAM_HOOKS="$TMPCLONE/smith/hooks"
LOCAL_HOOKS="$HOME/.claude/hooks"
ORPHAN_HOOKS=()
if [ -d "$LOCAL_HOOKS" ]; then
for f in "$LOCAL_HOOKS"/*.sh; do
[ -e "$f" ] || continue
name=$(basename "$f")
[ -f "$UPSTREAM_HOOKS/$name" ] || ORPHAN_HOOKS+=("$name")
done
fi
# Q6/Q8 unified orphan prompt (default = n)
if [ ${#ORPHAN_SCRIPTS[@]} -gt 0 ] || [ ${#ORPHAN_CMDS[@]} -gt 0 ] || [ ${#ORPHAN_HOOKS[@]} -gt 0 ]; then
echo ""
echo "Orphaned Smith-owned files detected (no longer in upstream):"
[ ${#ORPHAN_HOOKS[@]} -gt 0 ] && printf " hooks: %s\n" "${ORPHAN_HOOKS[@]}"
[ ${#ORPHAN_SCRIPTS[@]} -gt 0 ] && printf " scripts: %s\n" "${ORPHAN_SCRIPTS[@]}"
[ ${#ORPHAN_CMDS[@]} -gt 0 ] && printf " commands: %s\n" "${ORPHAN_CMDS[@]}"
echo "Remove these? (y/N)"
read -r REPLY
case "$REPLY" in
[yY]|[yY][eE][sS])
for n in "${ORPHAN_HOOKS[@]}"; do rm -f "$LOCAL_HOOKS/$n"; done
for n in "${ORPHAN_SCRIPTS[@]}"; do rm -f "$LOCAL_SCRIPTS/$n"; done
for n in "${ORPHAN_CMDS[@]}"; do rm -f "$LOCAL_CMDS/$n"; done
;;
*) echo "Keeping orphaned files." ;;
esac
fi
# Refresh Smith-owned files (touch only smith.*.md in .claude/commands per Q8-B)
if [ -d "$UPSTREAM_SCRIPTS" ] && [ -d "$LOCAL_SCRIPTS" ]; then
cp "$UPSTREAM_SCRIPTS"/*.sh "$LOCAL_SCRIPTS/" 2>/dev/null || true
chmod +x "$LOCAL_SCRIPTS"/*.sh
fi
if [ -d "$UPSTREAM_CMDS" ] && [ -d "$LOCAL_CMDS" ]; then
cp "$UPSTREAM_CMDS"/smith.*.md "$LOCAL_CMDS/" 2>/dev/null || true
fi
fi
5.2 Run /smith-index --migrate-templates
Non-destructively merge new template sections into CLAUDE.md and constitution.md. Invoke as a sub-action of this skill.
if [ -d "$PROJECT_DIR/.smith" ]; then
# Invoke /smith-index --migrate-templates as a Claude Code skill invocation
# (the parent assistant runs this; not shellable from here directly).
# See "Invoking sub-skills" note in the Key Rules section below.
echo "Running /smith-index --migrate-templates..."
fi
Note: bash can't directly invoke another Claude skill. The PARENT ASSISTANT (the one running this skill) must invoke /smith-index --migrate-templates as a Claude tool call after the bash block above echoes its placeholder. This is the only sub-skill invocation in /smith-update.
5.3 Q9-B — Schema Version Check + Regeneration Prompt
if [ -d "$PROJECT_DIR/.smith/index" ]; then
UPSTREAM_SCHEMA_VERSION=$(cat "$TMPCLONE/smith/scripts/parsers/meta_schema_version.txt" 2>/dev/null | tr -d ' \n\r')
LOCAL_SCHEMA_VERSION=$(cat "$PROJECT_DIR/.smith/index/.schema-version" 2>/dev/null | tr -d ' \n\r')
LOCAL_SCHEMA_VERSION="${LOCAL_SCHEMA_VERSION:-1}" # absent → assume legacy v1
if [ -n "$UPSTREAM_SCHEMA_VERSION" ] && [ "$UPSTREAM_SCHEMA_VERSION" != "$LOCAL_SCHEMA_VERSION" ]; then
echo ""
echo "Smith manifest schema mismatch:"
echo " Local: v${LOCAL_SCHEMA_VERSION}"
echo " Upstream: v${UPSTREAM_SCHEMA_VERSION}"
echo "Regenerate the manifest? (y/N) — runs /smith-index to refresh all .meta files."
read -r REPLY
case "$REPLY" in
[yY]|[yY][eE][sS])
# Parent assistant runs /smith-index here
echo "Running /smith-index..."
;;
*) echo "Keeping current manifest. You can regenerate later with /smith-index." ;;
esac
fi
fi
5.4 Manifest Sidecar Bootstrap Prompt (Q3-B)
If .smith/index/ doesn't exist at all (project predates manifest system, PR #19), offer the bootstrap.
if [ -d "$PROJECT_DIR/.smith" ] && ! [ -d "$PROJECT_DIR/.smith/index" ]; then
echo ""
echo "Smith manifest sidecar is missing for this project. Bootstrap now?"
echo " (1) Structural only — fast, runs /smith-index"
echo " (2) Structural + LLM descriptions — slow, runs /smith-index --describe"
echo " (3) Defer — skip (you can run /smith-index manually later)"
echo "Default: 3 (defer)"
read -r REPLY
case "$REPLY" in
1) echo "Running /smith-index..." ;; # parent assistant invokes
2) echo "Running /smith-index --describe..." ;; # parent assistant invokes
*) echo "Deferred. Run /smith-index when ready." ;;
esac
fi
5.5 Refresh .gitignore / .gitattributes Policy (Feature 36)
Re-merge the canonical team-shareable vault & index policy into the project-root
.gitignore and .gitattributes, idempotently, using the same sentinel logic as
/smith init. This is project-config, not vault data — merging managed lines in
the project-root .gitignore/.gitattributes does NOT violate the
"NEVER touch .smith/vault/" rule (which protects vault data: bank, ledger,
sessions, queue, agents, todo). Confirmed permitted for this step.
Source templates (upstream clone first, installed copy fallback):
$TMPCLONE/smith/skills/smith-index/templates/.gitignore-smith-additions(or installed~/.claude/skills/smith-index/templates/.gitignore-smith-additions)$TMPCLONE/smith/skills/smith-index/templates/.gitattributes-smith-additions
Staleness guard + auto-repair (Feature 38). The merge logic below trusts
whatever template $SMITH_TPL_DIR resolves to. A pre-Feature-36 installed
template is the inverse policy (it IGNORES index/files/ + index/systems/)
and has NO sentinel marker. Applying it would silently write the wrong policy.
So before merging: if the resolved source is the INSTALLED copy and it lacks the
# >>> smith-gitignore-policy >>> sentinel, treat it as stale. In /smith-update
an upstream clone ($TMPCLONE) is normally present, so we AUTO-REPAIR — overwrite
the stale installed template from the clone, then merge from the refreshed copy.
(scripts/install.sh already cp -R'd the whole skill dir during Phase 4, so a
clean update keeps the installed copy current; this guard catches the case where
§5.5 runs against a stale installed copy anyway.)
if [ -d "$PROJECT_DIR/.smith" ]; then
INSTALLED_TPL_DIR="$HOME/.claude/skills/smith-index/templates"
CLONE_TPL_DIR="$TMPCLONE/smith/skills/smith-index/templates"
SENTINEL='# >>> smith-gitignore-policy >>>'
# Prefer the upstream clone (authoritative this run); else the installed copy.
if [ -f "$CLONE_TPL_DIR/.gitignore-smith-additions" ]; then
SMITH_TPL_DIR="$CLONE_TPL_DIR"
else
SMITH_TPL_DIR="$INSTALLED_TPL_DIR"
fi
# Staleness guard + auto-repair: if we're about to use the INSTALLED template
# and it predates Feature 36 (no sentinel), repair it from the clone if we can.
if [ "$SMITH_TPL_DIR" = "$INSTALLED_TPL_DIR" ] \
&& ! grep -qF "$SENTINEL" "$INSTALLED_TPL_DIR/.gitignore-smith-additions" 2>/dev/null; then
if [ -f "$CLONE_TPL_DIR/.gitignore-smith-additions" ]; then
echo "NOTE: installed gitignore template is stale (pre-Feature-36) — repairing from upstream clone."
mkdir -p "$INSTALLED_TPL_DIR"
cp -f "$CLONE_TPL_DIR/.gitignore-smith-additions" "$INSTALLED_TPL_DIR/.gitignore-smith-additions"
cp -f "$CLONE_TPL_DIR/.gitattributes-smith-additions" "$INSTALLED_TPL_DIR/.gitattributes-smith-additions" 2>/dev/null || true
SMITH_TPL_DIR="$INSTALLED_TPL_DIR" # now refreshed; safe to use
else
echo "WARNING: installed gitignore template is stale (pre-Feature-36) and no upstream"
echo " clone is available to repair it. Skipping the .gitignore/.gitattributes"
echo " policy merge to avoid writing the wrong (inverted) policy. Re-run"
echo " /smith-update with network access to refresh the installed template."
SMITH_TPL_DIR="" # sentinel for "skip merge" — handled below
fi
fi
if [ -n "$SMITH_TPL_DIR" ]; then
# Q4-A: WARN (do not remove) on known-conflicting bare ignore lines that sit
# OUTSIDE the sentinels and shadow the now-committed shared paths.
GI="$PROJECT_DIR/.gitignore"
if [ -f "$GI" ]; then
# Strip the managed sentinel region first, then scan the remainder.
OUTSIDE=$(awk '
/# >>> smith-gitignore-policy >>>/ {inblk=1}
!inblk {print}
/# <<< smith-gitignore-policy <<</ {inblk=0}
' "$GI")
for bad in '.smith/' '.smith/index/' '.smith/index/files/' '.smith/index/systems/'; do
if printf '%s\n' "$OUTSIDE" | grep -qxF "$bad"; then
LINE=$(grep -nxF "$bad" "$GI" | head -1 | cut -d: -f1)
echo ""
echo "WARNING: $GI line $LINE contains a bare '$bad' ignore OUTSIDE the Smith"
echo " sentinels. This shadows the now-committed shared paths"
echo " (manifest, .meta describe layer, ledger, bank, agents, sessions)."
echo " Smith will NOT remove it automatically. Remove it manually so the"
echo " shared Smith artifacts can be committed."
fi
done
fi
# Idempotent sentinel replace-or-append (same contract as /smith init §4.7).
python3 - "$SMITH_TPL_DIR" "$PROJECT_DIR" <<'PYEOF'
import sys, pathlib
tpl_dir = pathlib.Path(sys.argv[1]); root = pathlib.Path(sys.argv[2])
def merge(target_path, tpl_path, open_marker, close_marker):
tpl = pathlib.Path(tpl_path)
if not tpl.exists():
print(f"WARNING: template not found: {tpl_path} — skipping"); return
block = tpl.read_text().rstrip("\n") + "\n"
target = pathlib.Path(target_path)
existing = target.read_text() if target.exists() else ""
if open_marker in existing and close_marker in existing:
pre = existing.split(open_marker, 1)[0]
post = existing.split(close_marker, 1)[1]
new = pre.rstrip("\n") + ("\n\n" if pre.strip() else "") + block + post.lstrip("\n")
action = "refreshed"
else:
sep = "" if (not existing or existing.endswith("\n\n")) else ("\n" if existing.endswith("\n") else "\n\n")
new = existing + sep + block
action = "appended"
target.write_text(new)
print(f"{action}: {open_marker.split()[1]} in {target}")
merge(root / ".gitignore", tpl_dir / ".gitignore-smith-additions",
"# >>> smith-gitignore-policy >>>", "# <<< smith-gitignore-policy <<<")
merge(root / ".gitattributes", tpl_dir / ".gitattributes-smith-additions",
"# >>> smith-gitattributes-policy >>>", "# <<< smith-gitattributes-policy <<<")
PYEOF
fi # end: SMITH_TPL_DIR non-empty (merge not skipped by staleness guard)
fi
Per Q4-A the merge only manages the region BETWEEN the sentinels and never deletes
user-authored lines; the warning above is the safe nudge for the operator to clean up
a stale blanket ignore by hand. Per Feature 38 the staleness guard ensures the merge
never applies a pre-Feature-36 (inverted, sentinel-less) installed template: in
/smith-update it auto-repairs from the upstream clone; with no clone reachable it
skips the merge with a warning rather than writing the wrong policy.
Phase 6: Cleanup
# Clean up temp clone (also handled by EXIT trap)
[ -n "${TMPCLONE:-}" ] && rm -rf "$TMPCLONE"
# Clear active-workflow marker
if [ -n "${MARKER_PATH:-}" ] && [ -f "$MARKER_PATH" ]; then
"$PROJECT_DIR/.specify/scripts/bash/clear-active-workflow.sh" "update-${TS}" 2>/dev/null || rm -f "$MARKER_PATH"
fi
# Summary
echo ""
echo "Smith updated to ${UPSTREAM_SHA:0:7}."
echo " Skills: refreshed in ~/.claude/skills/"
echo " Hooks: refreshed in ~/.claude/hooks/"
echo " Scheduler: refreshed in ~/.smith/scheduler/"
[ -d "$PROJECT_DIR/.smith" ] && echo " Per-project: .specify/scripts and .claude/commands/smith.* refreshed"
[ -d "$PROJECT_DIR/.smith" ] && echo " Git policy: .gitignore/.gitattributes Smith policy block refreshed"
echo " Snapshot: $BACKUP_DIR (delete after confirming the update works)"
Invoking Sub-Skills
/smith-update orchestrates two other skills as sub-actions:
/smith-index --migrate-templates— runs after the global update in any Smith-initialized project (Phase 5.2)/smith-indexor/smith-index --describe— runs only if Phase 5.4's bootstrap prompt is accepted
When the parent assistant runs /smith-update, it should treat the bash blocks above as the orchestration backbone and invoke the sub-skills via Claude Code's Skill tool at the marked points. The bash blocks emit Running /smith-index... placeholders to make the orchestration boundary visible in the session log.
Key Rules
- NEVER touch
.smith/vault/— user data is sacred (vault is the bank, ledger, sessions, queue, agents, todo — all user-owned). This protects vault data; merging the managed Smith policy region in the project-root.gitignore/.gitattributes(Phase 5.5) is project-config, not vault data, and is permitted. - NEVER touch project source code — only
.specify/scripts/,.claude/commands/smith.*,CLAUDE.md(via migrate-templates),constitution.md(via migrate-templates),.smith/index/(only on explicit prompt) - Active-workflow marker must be created BEFORE any file write (workflow-gate compliance)
- Snapshot before destructive work — if
install.shfails partway, restore from snapshot - Default-defer on LLM-heavy paths — Phase 5.4's bootstrap prompt defaults to (3); the schema-regen prompt in 5.3 defaults to (n)
- Settings.json dedupe touches only Smith-owned hook entries — never modify user-added entries (Q1-D)
python3notpython(Smith convention, per Rule 6 in~/.claude/CLAUDE.md)
Signals
- GitHub stars
- 52
- Forks
- 8
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
smith-update- Source
- github.com/attckdigital/smith