oh my god yes! this is exactly what i was looking for and SO MUCH MORE
They even have differentiable optimizers that are 1000x more elegant than what I’d hacked together
For posterity, this is a minimal example of what I was trying to accomplish, and it works with higher:
import higher
import torch
from torch import nn

"""
Goal: use meta gradients to tune differentiable hyper params of an update step
by updating them to maximise a corss-validation step online against a second update
""" 
train_inputs = torch.tensor(10.0)
xval_inputs = torch.tensor(10.0)

meta_param = torch.tensor(10.0, requires_grad=True)
meta_optimizer = torch.optim.Adam([meta_param], lr=3e-4)

my_model = nn.Linear(1, 1)
opt_a = torch.optim.Adam(my_model.parameters(), lr=3e-4)

with higher.innerloop_ctx(my_model, opt_a) as (fmodel, diffopt):
    # training step with higher wrappers
    pred = fmodel(train_inputs.unsqueeze(0))
    pred = pred * meta_param
    loss = -pred
    diffopt.step(loss)
    meta_optimizer.zero_grad() # <- does nothing, but I had to be sure 
    
    # meta param update ste[
    second_pred = fmodel(xval_inputs.unsqueeze(0))
    meta_objective = -second_pred
    meta_objective.backward() #  meta_param.grad now exists, is valid and doesn't sum grads from first loss 🎉🎉 
    meta_optimizer.step()

thanks