type CommandId = enum
  cmdSearch
  cmdDownload
type Command = object
  case id: CommandId
  of cmdSearch:
    opts: SearchOpts
  of cmdDownload:
    opts: DownloadOpts     # Error: attempt to redefine: 'v'
And note that the type must be explicit, no generics allowed. The reason for that being that you must know the explicit field at compileTime so you can link the appropriate procs to it.
Keep in mind that "id" is a runtime field. You can't know at compileTime what it'll be.
So if you have
proc doThing(x: SearchOpts) = echo "search"
proc doThing(x: DownloadOpts) = echo "download"
command.opts.doThing()
 You can not know at compileTime which of these procs you're supposed to call here. That means the compiler can not compile your program.It does if you have the same type
type CommandId = enum
  cmdSearch
  cmdDownload
type Command = object
  case id: CommandId
  of cmdSearch, cmdDownload:
    opts: int
Otherwise, there are several RFCs related to variants, sum types and ADTs:
at the very least.
Also @Araq has been working on a new design of ADTs in the past week.