:Deniteでlistを渡せない

:help denite-source-grepを見ると

                                                *denite-source-grep*
grep            Gather grep results and nominates them.
                The source executes [command, default_opts, recursive_opts,
                args[1]..., `pattern_opt, args[2]`..., separator, args[0]...
                or final_opts] command line.
                Note: The command result must be "path:linenr:text" pattern.

                Source args:
                        0. path string or list of paths
                        1. string or list of arguments
                        2. pattern string or list of patterns

Source argsの0と2はlistでも良いようだが、:Deniteのコマンドでlistを渡す方法がなさそう。 :Deniteplugin/denite.vimで定義されている。

command! -nargs=+ -range -complete=customlist,denite#helper#complete
      \ Denite
      \ call denite#helper#call_denite('Denite',
      \                                <q-args>, <line1>, <line2>)

denite#helper#call_denite()autoload/denite/helper.vimで定義されていて

function! denite#helper#call_denite(command, args, line1, line2) abort
  let [args, context] = denite#helper#_parse_options_args(a:args)
  ...
  call denite#start(args, context)
endfunction

denite#helper#_parse_options_args()を見て見ると

function! denite#helper#_parse_options_args(cmdline) abort
  let _ = []
  let [args, options] = s:parse_options(a:cmdline)
  for arg in args
    " Add source name.
    let source_name = matchstr(arg, '^[^:]*')
    let source_arg = arg[len(source_name)+1 :]
    let source_args = source_arg  ==# '' ? [] :
          \  map(split(source_arg, '\\\@<!:', 1),
          \      'substitute(v:val, ''\\\(.\)'', "\\1", ''g'')')
    call add(_, { 'name': source_name, 'args': source_args })
  endfor

  return [_, options]
endfunction
function! s:parse_options(cmdline) abort
  let args = []
  let options = {}

  " Eval
  let cmdline = (a:cmdline =~# '\\\@<!`.*\\\@<!`') ?
        \ s:eval_cmdline(a:cmdline) : a:cmdline

  for arg in split(cmdline, '\%(\\\@<!\s\)\+')
    let arg = substitute(arg, '\\\( \)', '\1', 'g')
    let arg_key = substitute(arg, '=\zs.*$', '', '')

    let name = substitute(tr(arg_key, '-', '_'), '=$', '', '')[1:]
    if name =~# '^no_'
      let name = name[3:]
      let value = 0
    else
      let value = (arg_key =~# '=$') ? arg[len(arg_key) :] : 1
    endif

    if index(keys(denite#init#_user_options())
          \ + keys(denite#init#_deprecated_options()), name) >= 0
      let options[name] = value
    else
      call add(args, arg)
    endif
  endfor

  return [args, options]
endfunction

s:parse_options()でevalとスペース区切りで引数とオプションを分けている。
denite#helper#_parse_options_args()ではs:parse_options()の戻り値のargsをfor文で回し、argを:区切りで分けてsourceごとの引数を作っている。この辺にこういう書き方ならば配列にするという処理がないので、配列では渡せなそう。
更に見ていくと、_という配列にsource_nameとsource_argsを以下の形で入れている。

    call add(_, { 'name': source_name, 'args': source_args })

でそれを

  return [_, options]

で、最初に見たdenite#helper#call_denite()に返している。そして最終的に

  call denite#start(args, context)

でdeniteを呼び出している。というわけで、:Deniteのコマンドでは配列を渡せなさそうである。配列を渡したいなら、コマンドではなく、関数をよぶ

call denite#start([{'name': 'grep', 'args': [['/path/to/hoge', '/path/to/fuga'], '', 'pattern']}])