How do I add an arg to $@?

In any POSIX shell,

set -- "$@" "value"

would add value to the end of the list of positional parameters (it would actually replace the list with a new longer list), and

set -- "value" "$@"

would add it in the beginning (and would technically be the reverse of a shift as shift removes the first element). This holds true for zsh.

The -- is used to protect the following values from accidentally being interpreted as options, in case they start with -.

The special variable $@ is almost exclusively used as "$@" as this would expand to the value of each positional parameter individually quoted. The expression "$@ somethingelse" would expand to the list of individually quoted positional parameters, with <space>somethingelse appended to the last of them.

To use the values of the positional parameters as a single string delimited by spaces (or whatever the first character of $IFS may be), use "$*" ("$* somethingelse" is well defined as a single string). This is however not what you want to do in this instance as it would collapse your list of values to one single value.


With zsh specifically, in addition to the standard set -- "$@" ... shown by @Kusalananda, the positional parameters are also available via the $argv array (like in csh), so you can also do:

argv+=arg             # append one argument to the end
argv+=(arg2 arg3)     # append several arguments
argv[1,0]=(arg1 arg2) # insert in front
argv[3,0]=(x)         # insert before the 3rd element
2+=(x)                # same as above (insert after the 2nd)
2+=x                  # append x to the second argument (not to confuse with
                      # the above).
argv[2,5]=(y)         # replace 4 elements 2 to 5 with one y argument
argv[3,-1]=()         # truncate
1=()                  # same as "shift"