# Visualize package dependencies with mermaid and 'bnd xref'

**URL:** <https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371>\
**Category:** TIPS\
**Created:** [October 20, 2023, 7:42pm UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371 "2023-10-20T19:42:53Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrisrueger](https://yyz2.discourse-cdn.com/free1/user_avatar/bnd.discourse.group/chrisrueger/32/18_2.png) [@chrisrueger](https://bnd.discourse.group/u/chrisrueger)\
**Post date:** [October 20, 2023, 7:42pm UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371/1 "2023-10-20T19:42:53Z")

</div>

1. Run the [bnd xref](https://bnd.bndtools.org/releases/3.5.0/commands/xref.html) command in your comand line (e.g. install via [brew on MacOS](https://formulae.brew.sh/formula/bnd)):

`bnd xref */generated/*.jar | sed -r 's/ < / --> /g'`

The sed replaces the `<` in the output with `-->`. The direction might not be correct, but I just wanted to get something working.

1. Paste the output or parts of the output to [https://mermaid.live/](https://mermaid.live/)

2. Get a visual graph or something like this:

 ![image](https://global.discourse-cdn.com/free1/uploads/bnd/original/1X/29ced18ad4266663e381d6e8fec2185e989ba89d.png)

Feel free to modify it as needed with filtering and what not. Inspired by this [github issue](https://github.com/bndtools/bnd/issues/4693#issuecomment-868636764).

---

<div class="post-metadata">

**Author:** ![pkriens](https://yyz2.discourse-cdn.com/free1/user_avatar/bnd.discourse.group/pkriens/32/3_2.png) [@pkriens](https://bnd.discourse.group/u/pkriens)\
**Post date:** [October 27, 2023, 12:43pm UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371/2 "2023-10-27T12:43:18Z")

</div>

The bndlib contains a DOT class that makes it trivial to turn this into a dot file. (graphviz).

---

<div class="post-metadata">

**Author:** ![pkriens](https://yyz2.discourse-cdn.com/free1/user_avatar/bnd.discourse.group/pkriens/32/3_2.png) [@pkriens](https://bnd.discourse.group/u/pkriens)\
**Post date:** [October 27, 2023, 12:49pm UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371/3 "2023-10-27T12:49:01Z")

</div>

Note that the bnd resolve command has such an option

---

<div class="post-metadata">

**Author:** ![chrisrueger](https://yyz2.discourse-cdn.com/free1/user_avatar/bnd.discourse.group/chrisrueger/32/18_2.png) [@chrisrueger](https://bnd.discourse.group/u/chrisrueger)\
**Post date:** [October 27, 2023, 2:04pm UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371/4 "2023-10-27T14:04:04Z")

</div>

Thanks @pkriens . Any hints about the `bnd resolve` command?  
I tried:

```auto
cd myworkspace_with_a_cnf_folder
bnd resolve dot my.bundle.with.the.bndruns/myapp.bndrun

```

But I got “Resolution failed Unable to resolve” … although when I click resolve in Eclipse on the `myapp.bndrun`, it resolves.

Am I in the wrong folder?

---

<div class="post-metadata">

**Author:** ![pkriens](https://yyz2.discourse-cdn.com/free1/user_avatar/bnd.discourse.group/pkriens/32/3_2.png) [@pkriens](https://bnd.discourse.group/u/pkriens)\
**Post date:** [October 30, 2023, 10:32am UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371/5 "2023-10-30T10:32:53Z")

</div>

You have to be in the project directory. I guess the resolve command has a -p to direct this to another directory.

```auto
bnd resolve dot test.bndrun 
................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................digraph "test.bndrun" {
  "<<INITIAL>>" -> "biz.aQute.websocket.jetty.provider[4]"
  "<<INITIAL>>" -> "org.apache.felix.webconsole[16]"
  "<<INITIAL>>" -> "org.apache.felix.configadmin[8]"
  "<<INITIAL>>" -> "org.apache.felix.gogo.runtime[10]"
  "<<INITIAL>>" -> "org.apache.felix.log[14]"
  "<<INITIAL>>" -> "org.apache.felix.http.jetty[12]"
  "<<INITIAL>>" -> "biz.aQute.graphql.gqljava.provider[3]"
  "biz.aQute.websocket.jetty.provider[4]" -> "org.apache.felix.http.servlet-api[13]"
  "biz.aQute.websocket.jetty.provider[4]" -> "biz.aQute.api.websocket[1]"
  "biz.aQute.websocket.jetty.provider[4]" -> "org.osgi.service.component[17]"
  "biz.aQute.websocket.jetty.provider[4]" -> "org.apache.felix.http.jetty[12]"
  "biz.aQute.websocket.jetty.provider[4]" -> "org.apache.felix.scr[15]"
  "org.apache.felix.gogo.command[9]" -> "org.apache.felix.gogo.runtime[10]"
  "org.osgi.util.promise[19]" -> "org.osgi.util.function[18]"
  "org.apache.commons.fileupload[6]" -> "org.apache.commons.io[7]"
  "org.apache.commons.fileupload[6]" -> "org.apache.felix.http.servlet-api[13]"
  "org.apache.felix.webconsole[16]" -> "org.apache.commons.io[7]"
  "org.apache.felix.webconsole[16]" -> "org.apache.felix.http.servlet-api[13]"
  "org.apache.felix.webconsole[16]" -> "org.apache.commons.fileupload[6]"
  "org.apache.felix.webconsole[16]" -> "org.apache.felix.http.jetty[12]"
  "org.apache.felix.configadmin[8]" -> "org.apache.felix.log[14]"
  "biz.aQute.api.graphql[0]" -> "biz.aQute.graphql.gqljava.provider[3]"
  "biz.aQute.graphql.framework.example[2]" -> "biz.aQute.api.graphql[0]"
  "biz.aQute.graphql.framework.example[2]" -> "reactive-streams[20]"
  "biz.aQute.graphql.framework.example[2]" -> "org.apache.felix.http.jetty[12]"
  "biz.aQute.graphql.framework.example[2]" -> "org.apache.felix.scr[15]"
  "biz.aQute.wrapper.graphql[5]" -> "reactive-streams[20]"
  "biz.aQute.api.websocket[1]" -> "biz.aQute.websocket.jetty.provider[4]"
  "org.osgi.service.component[17]" -> "org.osgi.util.promise[19]"
  "org.apache.felix.gogo.runtime[10]" -> "org.apache.felix.gogo.shell[11]"
  "org.apache.felix.log[14]" -> "org.apache.felix.configadmin[8]"
  "org.apache.felix.http.jetty[12]" -> "org.apache.felix.http.servlet-api[13]"
  "org.apache.felix.http.jetty[12]" -> "org.apache.felix.configadmin[8]"
  "org.apache.felix.http.jetty[12]" -> "org.apache.felix.log[14]"
  "org.apache.felix.scr[15]" -> "org.osgi.util.promise[19]"
  "org.apache.felix.scr[15]" -> "org.apache.felix.configadmin[8]"
  "org.apache.felix.scr[15]" -> "org.osgi.service.component[17]"
  "org.apache.felix.scr[15]" -> "org.apache.felix.gogo.runtime[10]"
  "org.apache.felix.scr[15]" -> "org.apache.felix.log[14]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "org.apache.felix.http.servlet-api[13]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "reactive-streams[20]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "biz.aQute.api.graphql[0]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "biz.aQute.graphql.framework.example[2]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "biz.aQute.wrapper.graphql[5]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "biz.aQute.api.websocket[1]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "org.apache.felix.gogo.runtime[10]"
  "biz.aQute.graphql.gqljava.provider[3]" -> "org.apache.felix.scr[15]"
  "org.apache.felix.gogo.shell[11]" -> "org.apache.felix.gogo.command[9]"
  "org.apache.felix.gogo.shell[11]" -> "org.apache.felix.gogo.runtime[10]"
}

```

---

<div class="post-metadata">

**Author:** ![chrisrueger](https://yyz2.discourse-cdn.com/free1/user_avatar/bnd.discourse.group/chrisrueger/32/18_2.png) [@chrisrueger](https://bnd.discourse.group/u/chrisrueger)\
**Post date:** [July 12, 2026, 10:15am UTC](https://bnd.discourse.group/t/visualize-package-dependencies-with-mermaid-and-bnd-xref/371/6 "2026-07-12T10:15:45Z")

</div>

FYI A similar thing but on bundle level is now included in bndtools via the [Bundle Graph](https://bndtools.org/manual/bundlegraph.html)
