Can I setup a core hook that gets applied to all of my projects?

[This used to be part of the knowledge base on the main Shotgun support site, but it’s too technical/Toolkitty for that site, and too workflow-specific/edge-casey for the Shotgun Developer Docs site, so we thought this would be a good place for this info]

Unlike engine and app hooks, where you explicitly specify where to look for them in your environment config files, core hooks are set up differently: you have to put them in a specific location (the config/core/hooks/ dir in your pipeline config) in order for Toolkit to see and use them.

So, you can’t simply put a core hook in a single location and have all projects point to it.

If you’re using a localized core in each pipeline configuration (the default), you can work around this challenge by using symlinks to link to a central directory that contains your core hooks.

If you’re on Windows and symlinks won’t work for you, you can place your common core hook logic in a Python module, then in your pipeline configuration(s), your core hook can be a Python stub in that adds the path of your centralized core hook modules, then imports the correct one. So you’d only have to drop these stubs into your pipeline configurations once, then any updates you made to the hook(s) could be done in one place.

An example stub for the cache_location core hook is below. It also uses an environment variable to help determine where the central location for core hook module is for the studio:

#! /usr/bin/env python

This is a stub to allow loading Core Hooks from a central location.

.. module:: `cache_location`
   :platform: Unix, Windows
   :synopsis: Stub to load Core Hook from central location.

import os
import sys

# Add Core Hook version folder to sys path
hook_folder = r'${SOME_STUDIO_DIRECTORY}\toolkit_config\hooks\cache_location\v1.0.0'
hook_folder = os.path.expandvars(hook_folder)

from cache_location import CacheLocation as BaseCacheLocation

# Needed for SGTK to work
class CacheLocation(BaseCacheLocation): pass

Thanks to @sebastian.kral at Pixomondo for the contribution