As I said in the comments, I would go the other way. If you use dependencies as managed dependencies, you can obscure them both in the library itself and inside your project.
Let's look at an example:
Suppose I have a project that takes a dependency on com.typesafe.config . I can shade it inside my own library, i.e. inside the com.typesafe.config code, as well as in the consumption library.
You define it as follows:
assemblyShadeRules in assembly ++= Seq( ShadeRule.rename("com.typesafe.config.**" -> " my_conf.@1 ") .inLibrary("com.typesafe" % "config" % "1.3.0") .inProject )
Which basically means "take something that creatures using com.typesafe.config , and drop it before my_conf ."
Please note that we use both inLibrary and inProject . The first means "change package names inside com.typesafe.config " and inProject means "change all links to com.typesafe.config inside my code."
Now the result is as follows:
Here's what the package looks like internally ( my_conf was originally com.typesafe.config before shading):

And this is the package your code refers to:

Yuval Itzchakov
source share