Fork me on GitHub
  • Public
  • Public/Protected
  • All


Table of Contents

  1. Requirements
  2. Installation
  3. Setup
  4. Analyzing Your Project
  5. Language Support
  6. Setting Up Continuous Analysis
  7. Configuration
  8. Getting New Releases
  9. Editor Integration
  10. Library Integration
  11. Creating a Plugin



npm i -g vile


cd my_project_src/
vile init

Note: If you don't like installing vile's CLI globally, you can easily access the locally installed CLI using something like npx.

Analyzing Your Project

  1. Make an account on

  2. Create a New Project.

  3. Grab an API Token.

  4. Upload your first commit:

export VILE_TOKEN=my-all-token
export VILE_PROJECT=my-project-name

vile analyze -u

Language Support

The core vile package comes with a general set of plugins that support basic multi language analysis.

To analyze your code further, such as tracking outdated RubyGems, plugging in your favourite linter, tracking code complexity, or checking for vulnerabilities, you need to install extra plugins first.

See also below for tips and known caveats for various languages and frameworks.


For an everyday JavaScript (or Node.js) project:

npm i -D vile vile-synt vile-git vile-escomplex vile-nsp


There is currently limited support for Flow using non-core plugins. Some plugins may work, and others (that specifically parse JS) may fail.

For example vile-synt currently does not work (yet).


Just like Flow there is limited support.

A good workaround is to ignore all .jsx files and also any .js files with JSX code in them.

For example, with a plugin like vile-escomplex:

    - "*.jsx"
    - path/to/jsx

Non-Standard JS

If you are using EMCAScript Stage-3 and below proposals, some plugins might not work out of the box or just yet.

A good workaround is to map lib data to src using the CLI's -x src:lib option, while also ignoring src for the specific plugins:

  ignore: src
  ignore: src


A basic Ruby project example (using Bundler):

npm i -D vile vile-git vile-rubycritic vile-rubocop vile-sass-lint vile-bundler-audit vile-bundler-outdated

# you can also add these to your Gemfile
gem install rubocop rubycritic bundler bundler-audit

# depending on your setup, you may need to use `bundle exec`
bundle exec vile analyze

Note: Some plugins don't support Vile's allow/ignore out of the box.

For example, vile-rubycritic requires you set specific allow paths to avoid traversing node_modules.

The same goes for vile-rubocop.


For an in depth article about using Rails + Vile checkout Continuous Analysis For Your Rails Project Using Vile and CircleCI.


Depending on your setup and if you are using sandboxes, you may need to use cabal exec:

cabal exec -- vile analyze

Setting Up Continuous Analysis

Vile is most helpful when you integrate it into your CI/CD process and run it right after your build and test steps.

See below for some popular examples.

Note: don't forget to set VILE_TOKEN and VILE_PROJECT on your build server!


Example circle.yml:

    version: 6.10.1

# see:
    - "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow"
    - git checkout -f $CIRCLE_BRANCH

    - vile a -u -n


Example appveyor.yml:

  - node_modules -> package.json

    - nodejs_version: 6
      npm_version: 4.x.x

  - x86
  - x64

# if you are using unix style line endings
  - git config --global core.autocrlf input

# might need higher value for better churn calculation
clone_depth: 10

build: off

  - ps: Install-Product node $env:nodejs_version
  - ps: npm install -g npm@$env:npm_version
  - npm install

  - # run tests here
  - vile a -u -n


Example .travis.yml:

  - linux

language: node_js

  - "6"

    - node_modules

  - NPM_VER=4.x.x

  - npm install -g npm@$NPM_VER

  depth: 10

  - # run tests here
  - vile a -u -n


If you run into issues reporting churn or generating git data, you may need to do this prior to analyzing:

git checkout -f $CI_BRANCH


You can easily configure Vile and it's plugins via a .vile.yml file.

The file should reside in your project root and look something like this:

    - foo/bar
    - baz

    some_opt: "some val"
  ignore: plugin_specific_ignore
  allow: plugin_specific_allow

You can also specify a custom plugin list in your config:

    - "tslint"

Ignore Lists

Vile already ignores known directories and paths for you, such as node_modules, coverage, etc.

Setting vile.ignore in your config will ignore paths/files globally.

If plugin_name.ignore is set, then it will be merged into vile.ignore and passed to the respective plugin when it is run.

Allow Lists

The vile.allow (and plugin specific) setting specifies paths to only include.

Note: Unlike ignore, certain levels will overwrite others, when set.

From highest to lowest precedence, they are:

  1. Specified via vile a --gitdiff
  2. Specified via vile a file dir ...
  3. Specified via vile.allow
  4. Specified via my_plugin.allow

So, say you call vile a -g it will ignore plugin/top level allow lists, and any path arguments provided.

Getting New Releases

cd my_project_src/
npx npm-check-updates -u
npm install
git commit package.json -m "Updated some vile packages."

For a global install:

npx npm-check-updates -g -f vile
npm install -g vile

Editor Integration

You should be able to integrate vile into any text editor (ex: via the -f syntastic flag).


Via syntastic.

See forthright/syntastic for now. Just replace the upstream install with the master branch.

Note: There is a lot of overlap with current syntax checkers that already exist. For the most part they are faster (ex: hlint), so check those out first.

Current syntax checkers:

An example config supporing slim, ruby, and sass, with passive mode enabled:

  " Command to toggle syntastic passive mode
  nnoremap <C-w>e :SyntasticCheck<CR>
  nnoremap <C-w>E :SyntasticReset<CR>

  " Recommended statusline (see :help syntastic)
  set statusline+=%#warningmsg#
  set statusline+=%{SyntasticStatuslineFlag()}
  set statusline+=%*

  let g:syntastic_always_populate_loc_list = 1
  let g:syntastic_auto_loc_list = 1
  let g:syntastic_enable_signs = 1
  let g:syntastic_aggregate_errors = 0
  let g:syntastic_check_on_open = 1
  let g:syntastic_auto_jump = 0

  " Put into passive mode, and set desired checkers
  let g:syntastic_mode_map = { "mode": "passive" }
  let g:syntastic_ruby_checkers=["mri", "vile_rubycritic", "vile_rubocop", "vile_rails_best_practices"]
  let g:syntastic_slim_checkers=["vile_slim_lint", "vile_rails_best_practices"]
  let g:syntastic_sass_checkers=["vile_sass_lint"]

Library Integration


npm i vile


const vile = require("vile")


  .then((issues : vile.IssueList) => {
    // ...

See src/index for the full API.

Creating A Plugin

A plugin itself should be an npm package prefixed with vile-, and have a main module that exports a punish method.

The punish method should return an array of issues, or a promise that resolves into one:

module.exports = {
  punish: (plugin_config) =>
    [issues] || a_promise_that_resolves_to_array_of_issues

You can also require("vile") in your plugin and use its API, which provides some helpers.

See vile.Issue for how Issues are structured.

Writing Non-JavaScript Plugins

As long as you have a shim index.js file, you can use any lang to generate issue data.

For now, vile.spawn is your best bet for running external commands.

For an example, see something like vile-hlint.

Writing In TypeScript

Checkout vile-rubycritic for an example of how to pull in and use Vile's typings.


At the moment, each plugin is expected to support both the ignore and allow lists (if applicable).

Ignore Lists

You can use the vile.ignored("path", ignore_list) library method help with matching.

For reference, node-ignore is currently used for matching.

Allow Lists

Similarily, you can use vile.allowed("path", allow_list).


There are also some helper methods to abstract away some onerous work.

For example: vile.filter is great for using with vile.promise_each, or in general.

let vile = require("vile")

module.exports = {
  punish: (config) => {
    let filtered = vile.filter(config.ignore, config.allow)

    return get_some_filepaths_to_check()
      .filter((filepath) => filtered(filepath))

Windows/Unix Paths

Plugins should stick to using unix style paths in issues and where ever else. Library utilities such as ignore and allow attempt to auto convert windows style paths, but not necessarily from things like config lists.

Files Without Issues

Any files that are not ignored globally via vile.ignore and have no issues are sent along with any reported issues.

Currently, you can disable this with the --dont-post-process option.

Generated using TypeDoc