Grunt is a JavaScript task runner. It is being used heavily for web development to automate repititive tasks like minification, compilation, unit testing, linting, etc. After you've configured it, a task runner can do most of that mundane work for you—and your team—with basically zero effort.

For a recent project, I had to repeatedly upload some files to my Android device whenever some changes were made on the code base. Being familiar with adb, it was my immediate choice to upload files. Just a simple command adp push and your files are on the device in no time. Since I was already working with Grunt on the project with a watch task configured to identify when some files change, it was really simple to add another task to run the command to upload files.

First you would need the grunt-shell task to execute shell commands. Then, just put in the configuration for shell task and you are ready to go.

shell : {  
  sync_android: {
    command: "<%= adbPath %> push 'path/to/local/directory' '<%= pathOnDevice %>'"
  }
} 

The variables adbPath and pathOnDevice are defined in grunt config as follows:

config: {  
  adbPath: '/Applications/Android\\ Studio.app/sdk/platform-tools/adb',
  pathOnDevice: grunt.option('android_path') || '<default/path/on/device>'
}

Now, just run the task from command line: grunt shell:sync_android [--android_path=] or wire with watch to auto upload files.