CLI tool
ComposeGears/Valkyrie avatar
ComposeGears/Valkyrie

Valkyrie converts SVG and XML icons into Compose ImageVector code

SVG/XML to Compose ImageVector: IntelliJ IDEA / Android Studio plugin + build-in previewer without compilation, CLI tool, Gradle plugin

902 stars26 forksKotlinApache-2.0

At a glance

What is it?
Valkyrie is a Kotlin project that turns SVG and XML icons into Compose ImageVector sources, delivered as an IntelliJ IDEA and Android Studio plugin, a CLI and a Gradle plugin. It targets teams who want generated icon code they can still edit, not a black box that emits files nobody touches.
Who is it for?
Valkyrie suits an Android or Compose Multiplatform team that has a folder of SVG or XML icons, wants them as typed ImageVector sources, and would rather review generated Kotlin than hand-write path data. It is the wrong tool for a project with no Compose dependency, for a team that only needs a handful of one-off icons, and for anyone who needs the legacy icon set that Compose used to ship, which the README itself says is no longer maintained.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why the existing converters were not good enough

The motivation section explains the problem in the project's own terms, and the reason is worth taking seriously because it is not that converters are missing. The README says that during Jetpack Compose and Compose Multiplatform development the team often had to convert icons from SVG or XML into ImageVector, and that while existing tools exist for this, they often fell short in usability, reliability and the quality of the generated code, and in some cases were paid products.

Three separate complaints are packed into that sentence, and they lead to three different design decisions later on. Usability points at the IDE experience. Reliability points at the converter and its tests. Code quality points at the generator, which is written on top of kotlinpoet and applies its own formatting rules instead of emitting a wall of raw path strings.

There is also a timing note. A callout in the README states that the project is especially relevant now as the built-in icon set is no longer maintained and is not recommended for use in apps, with a link to the Android developer documentation on Compose graphics. That is the practical driver: a team that used to lean on a bundled icon set now has a reason to source icons from elsewhere, and SVG is what most icon libraries ship.

The stated primary goal follows from all this: a fast, reliable and user-friendly solution for converting SVG and XML icons to ImageVector, while allowing the generated code to be customised to individual project needs.

The generator formats Kotlin instead of dumping path data

The core feature list is where the difference from a naive converter shows. The generator is a custom one built on kotlinpoet, and the README enumerates what it does to the output: code alignment and formatting, removal of redundant code by default such as the public keyword, removal of unused imports such as the kotlin.* package, skipping of default ImageVector parameters, optional trailing comma with an explicit mode, and a configurable code indent.

Each of those is a small thing on its own, and together they are the difference between output you have to reformat before committing and output you can accept. Removing the public keyword matters in Kotlin, where visibility defaults are usually not written out. Skipping default ImageVector parameters keeps the generated constructor call down to the values that actually differ from the defaults. And a configurable indent matters when the icons live in a project that does not use four spaces.

The generator can also emit the icon as a backing property or as a lazy property, which the README lists as a choice under output formats. The lazy form defers the vector construction until first use, which is the better choice for a pack with hundreds of icons where most screens touch only a few.

On speed, the README states that processing 6k icons takes roughly 5 seconds. That is the project's own figure for the batch path, and it is the number that matters for the icon pack workflow, where a whole library is converted in one pass rather than one file at a time.

Simple mode and IconPack mode answer different jobs

The IDE plugin offers two conversion modes, and the split is the most useful thing to understand before installing it.

Simple mode is for individual icons. The README describes it as quick conversion of single SVG or XML icons to ImageVector, suited to one-off conversions, prototyping or testing icons without setting up a full icon pack structure. Its quick actions are a rename for the icon, a preview of the ImageVector on different backgrounds (a pixel grid, white and black), and an export of the generated ImageVector to a file or to the clipboard. That last set is what makes it useful for a single icon: you can drop a file in, see it against light and dark, and paste the code into your source without leaving the editor.

IconPack mode is for a set. It facilitates creating an organised icon pack with extension properties for the pack object, previewing the list of icons, and batch importing them to a specified directory. Creating a new pack walks you through the configuration: destination path, package name, an optional licence header, the name of the icon pack object such as AppIcons or MyIcons, and nested packs for hierarchical organisation, with Outlined, Filled and Colored given as examples of that hierarchy.

The nested pack structure is the part that shows the design intent. A pack can hold sub-packs, so a project with outlined, filled and coloured variants of the same icon set keeps them in one place instead of in three directories that drift apart.

A previewer that renders ImageVector without compiling

The feature that most directly addresses the complaint about existing tools is the built-in ImageVector previewer, which renders any icon without compilation. The README lists four variants of it: an embedded previewer, an auto-completion previewer, a gutter previewer and a project view previewer.

These are different places to look rather than different rendering techniques. The gutter previewer puts the icon in the margin beside the code, so a developer can see what a vector looks like while reading the declaration that produces it. The auto-completion previewer shows it inside code completion, which is where a developer first meets an unfamiliar icon name. The project view previewer covers icons sitting in a directory rather than in a file you are reading, and the embedded one is the in-editor rendering.

Because the preview needs no compilation, it works before the project builds. That is the practical difference from checking an icon by running the app, and it is why a plugin that only converted files would still leave the designer in a build-and-look loop.

The plugin also ships the conversions in both directions, SVG to XML and ImageVector to XML, plus a Web Import that downloads and converts icons from popular online icon libraries directly. Drag and drop of files and directories is supported, as is pasting content from the clipboard, and the plugin can add more icons into an existing project icon pack rather than forcing a regeneration.

A CLI and a Gradle plugin for the same conversion

The IDE plugin is not the only delivery mechanism, and the difference between the three is a question of when the conversion happens.

The CLI tool exposes three commands, listed in the README table of contents: an iconpack command, an svgxml2imagevector command and a changelog command. The naming makes the split obvious. The single-file command handles one SVG or XML file at a time, which is the scripted equivalent of Simple mode, and the pack command handles a set of icons with the same structure the IDE produces, which is the equivalent of IconPack mode. A changelog command in the same tool is a small sign that the tool is expected to be run repeatedly against a growing set of icons.

The Gradle plugin moves the conversion into the build. The README documents a compatibility section, a plugin configuration section and samples for three cases: basic conversion, icon pack configuration, and icon pack with nested packs configuration. A tips and tricks section closes that part of the documentation. Running the conversion as a build task means the icons are regenerated from source SVG whenever the sources change, and a nested pack hierarchy survives that regeneration because the hierarchy is configuration rather than a one-time choice made in a dialog.

The plugin itself is built with Compose Multiplatform, and the README notes that since version 1.0.0 it is powered by the Jewel UI framework with Tiamat used for navigation. A web app is listed in the tools section but marked as under development.

Apache-2.0 terms, a separate plugin release line, and an evolving CLI

The licence is Apache-2.0, with the LICENSE file at the top level of the repository and the licence badge in the README linking to it. The practical caveat is the usual one for an icon converter: the tool's licence says nothing about the icons you convert. A set of icons carries whatever terms its own designer or library set, and the generated Kotlin in your project inherits that question, not the tool's.

The release line is worth understanding because the three deliverables version separately. The recent releases are all named for the IDE plugin: idea-plugin-1.7.1 on 2026-09-23, idea-plugin-1.7.0 on 2026-08-25 and idea-plugin-1.6.1 on 2026-07-22. The CLI and the Gradle plugin are released from the same repository but carry their own badges in the README, pointing at the GitHub releases, the Homebrew tap and the Gradle Plugin Portal respectively. The plugin releases land about monthly.

Activity is current: the last push was on 2026-10-20, and the default branch is main. The repository layout is a Gradle build with build-logic, components, sdk and tools directories, alongside a gradlew wrapper, an AGENTS.md, a DEVELOPMENT.md and a stability_config.conf, which is the kind of setup that suggests the project is developed with an explicit API stability policy for its own surface.

For an adopter, the practical upgrade cost is low if you stay inside one deliverable, since the plugin is what ships most often. The risk is mixing surfaces: converting with the CLI and then regenerating with Gradle can produce different output unless the same configuration is applied in both.

Editorial conclusion

Valkyrie suits an Android or Compose Multiplatform team that has a folder of SVG or XML icons, wants them as typed ImageVector sources, and would rather review generated Kotlin than hand-write path data. It is the wrong tool for a project with no Compose dependency, for a team that only needs a handful of one-off icons, and for anyone who needs the legacy icon set that Compose used to ship, which the README itself says is no longer maintained. Before you adopt it, decide whether you want the IDE plugin, the CLI or the Gradle plugin, since they solve the same problem at different points in the build, check that the generated code matches the style your project already has, since the kotlinpoet based generator applies its own formatting rules, and read the Apache-2.0 licence file, which is permissive for the tool but says nothing about the licensing of the icons you feed into it.

Frequently asked questions

What can Valkyrie convert into Compose ImageVector code?

Both SVG and XML sources. The README lists support for conversion from SVG and XML as the first core feature, and the CLI exposes a svgxml2imagevector command alongside an iconpack command for whole icon sets.

Does the Valkyrie IDE plugin need the project to compile to show an icon?

No. The plugin includes a built-in ImageVector previewer that renders icons without compilation, in four variants: embedded, auto-completion, gutter and project view. Simple mode also previews a generated ImageVector on a pixel grid, white and black backgrounds.

Can Valkyrie generate a whole icon pack with nested groups?

Yes. IconPack mode creates a project icon pack with an object name such as AppIcons or MyIcons, configurable destination path, package name and optional licence header, and nested packs for hierarchical organisation, with Outlined, Filled and Colored given as examples.

What output formats does the Valkyrie generator support?

The generated icon can be produced as a backing property or as a lazy property. The generator is built on kotlinpoet and applies formatting rules including removal of the public keyword, removal of unused imports, skipping default ImageVector parameters, an optional trailing comma and a configurable code indent.

Official sources

  1. ComposeGears/Valkyrie on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/composegears-valkyrie.svg)](https://hysenlabs.com/projects/composegears-valkyrie)

Was this useful?