The Amiga Installer

The Amiga Installer is the canonical tool for installing software on AmigaOS, comparable in role to Windows' MSI / msiexec, RPM, or apt. It is a script-driven program: the developer writes a .install script, the user double-clicks it (or invokes Installer from the Shell), and a standard, friendly GUI walks them through the install with yes/no prompts and contextual help. Source: Installer.guide V44.6 / V45.x reference manual, included in the NDK 3.9 and updated through the NDK 3.2 R4 release-notes line.

History and versions

The Installer was created in 1991 at Commodore-Amiga. Loren Wilton wrote the original; Heinz Wrobel (HAAGE & Partner) reworked it through the V43 series. The V44 generation (1999, NDK 3.9) added visual effects, datatypes, and a backtrace mechanism. The NDK 3.2 R4 (2002–2022) carries the maintenance line V43.4 → V45.5 with overflow and security fixes.

Version Date Notes
pre-V42 1991–1993 Original Loren Wilton implementation.
V42 1994 First widely-redistributed version.
V43 1995–1996 Heinz Wrobel rewrite.
V43.4 1995 First Amiga Technologies release.
V44 1999 Visual effects, datatypes, backtrace.
V44.6 1999 Added (effect ...), (showmedia ...), (trace ...), (retrace ...), (back ...).
V45 2016–2018 Converted assembly to C, hardened against overflow, 2GB+ volume support.
V45.5 2018 Final documented maintenance release.

After V45.5, no further public releases. Installer remains the standard for commercial Amiga software (WHDLoad, AmiKit, OS distribution, demos, etc.) and is shipped with AmigaOS 3.2.

Invocation

From Workbench

Double-click the Installer icon, then drag the icon of the directory containing the .install script onto the Installer window, or use the Install button in the Installer requester. The Installer scans the chosen directory recursively for Install-named icons and .install text files and presents them as candidates.

From the Shell

Installer [APP=appname] [MINUSERLEVEL=n] [NOPRETEND] [LOG] [FAKE] [HELP=key] SCRIPT=<path>
  • APP=appname — sets the pre-defined variable @app-name (used in the welcome / complete messages).
  • MINUSERLEVEL=n — refuse to run if the user's user-level is below n (0 = novice, 1 = average, 2 = expert). The minimum is set by the script via (user ...) or here.
  • NOPRETEND — disable Pretend mode (Pretend is a "do nothing, log everything" mode for testing).
  • LOG — write a log file of every action.
  • FAKE — same as Pretend.
  • HELP=key — assign a help key other than the default HELP.
  • SCRIPT=<path> — path to the .install script. Defaults to looking for Install in the current directory.

The .install file

The installer script is a text file with one of two layouts:

  1. Bare script — a file with commands, conventionally named Install (no extension) or <Name>.install. The installer runs it directly.
  2. Project icon — a Workbench drawer with an .info icon, where the Install text file is the default tool type. The user double-clicks the drawer.

The script is text-encoded in ISO-8859-1 (or the locale's character set on V44+). Comments start with ; and run to end of line.

Basic elements

The Installer language is Lisp-like: statements are parenthesized lists of commands and arguments.

Literals

5         ; decimal integer
$a000     ; hexadecimal integer
%0010010  ; binary integer
-3        ; negative integer
"Hello"   ; double-quoted string
'Hello'   ; single-quoted string (identical to "Hello" but no escape processing)

Symbols (variables)

Prefix Type Example
#name Long (integer) #count, #loopvar
$name String $username, $destpath
@name Pre-defined (read-only or pre-set) @installer-version, @default-dest

Assignment:

(set #count 5)                ; integer
(set $name "Foo")             ; string
(set @pretend 0)              ; pre-defined

Statements

(set #x 42)
(set #y (* #x 2))
(if (= #x 42)
    (message "Got the answer.")
    (message "Wrong."))

The format is (<command> <arg> <arg> ...). The opening parenthesis starts the statement; the closing one terminates it. Statements can be nested arbitrarily.

Comments

; this is a comment
(set #x 5)   ; trailing comment to end of line

The standard install script pattern

A typical .install runs through these phases:

  1. Welcome message.
  2. Verify requirements (OS version, free space, dependencies).
  3. Ask the user where to install (directory, options).
  4. Create the destination directory.
  5. Copy files.
  6. Set ToolTypes on icons.
  7. Add entries to the Locale:Catalogs/ tree, if localized.
  8. Update the Workbench database.
  9. Add a S:User-Startup line, if needed.
  10. Run a post-install command, if needed.
  11. Complete message.

Common statements

(welcome ...) and (complete ...)

(welcome)
(message "Welcome to Foo 1.3 by Acme Ltd.")
(message "This will install Foo into a drawer of your choice.")

(askdir ...), (askfile ...), (askbool ...), (askchoice ...), (askoptions ...)

(set #dest-dir
  (askdir (prompt "Where to install Foo?")
          (help "Pick a directory. The Installer will create it if missing.")
          (default "Work:")
          (disk)))

(if (= #dest-dir "")
    (abort "Installation cancelled."))

(askbool) returns 0 or 1; (askchoice) returns the index of the chosen item; (askoptions) lets the user toggle multiple flags independently.

(makedir ...)

(makedir #dest-dir
         (prompt "Creating the destination directory...")
         (help "Foo needs its own program drawer.")
         (confirm))

(copyfiles ...)

(copyfiles (source "Foo")
           (dest #dest-dir)
           (prompt "Copying Foo files...")
           (help "Foo consists of these files.")
           (infos)              ; copy icons too
           (files)              ; only files, not subdirs
           (optional fail))     ; abort on any copy failure

Options include source, dest, pattern, choices, all, files, infos, noposition, fonts, nogauge, optional <fail|nofail|oknodelete|force|askuser>, confirm, safe, compression.

(copylib ...) — version-aware copy

(copylib (source "libs/foo.library")
         (dest "LIBS:")
         (prompt "Installing foo.library")
         (help "foo.library is the Foo runtime library.")
         (confirm))

(copylib) checks the $VER: string of the source against the destination; the destination is overwritten only if the new version is higher. Creates a single missing directory level (e.g., LIBS:midi if LIBS: exists).

(tooltype ...)

(tooltype (dest (tackon #dest-dir "Foo"))
          (setdefaulttool "icon")
          (setstack 20000)
          (noposition))

Sets or modifies ToolTypes on an icon. (tackon) joins two path components with the appropriate separator.

(startup ...), (textfile ...), (run ...), (execute ...), (rexx ...)

(startup "Foo"
         (prompt "Adding Foo to your S:User-Startup")
         (help "Adds the line 'Assign Foo: ..' to S:User-Startup.")
         (command "Assign Foo: %s" #dest-dir))

(textfile (dest (tackon #dest-dir "Foo.config"))
          (prompt "Writing Foo configuration")
          (append "verbose = 1%nport = 1234%n"))

(run (command "lha x ram:foo.lha RAM:") (prompt "Unpacking archive"))
(execute (command "Foo") (prompt "Running Foo once for first-time setup"))
(rexx (script "rexx/FooSetup.rexx") (prompt "Running ARexx setup"))

(setmedia ...), (showmedia ...), (closemedia ...) — datatypes previews (V44+)

(setmedia "Foo" "Drawers/Preview.ilbm")
(showmedia)
(message "This is what the icon will look like.")
(closemedia)

(effect ...) — visual transitions (V44+)

(effect (back) (delay 0) (step 1))   ; dissolve back

Control flow

(if (condition)
    (then-statement ...)
    (else-statement ...))

(while (condition)
    (body-statement ...))

(foreach #item in '(list of items)
    (body ...))

(select (key)
    (case value1 (action1 ...))
    (case value2 (action2 ...))
    (default (actionN ...)))

(sequence
    (statement-1 ...)
    (statement-2 ...))

(abort "fatal message")
(exit)

Conditions use the same (= ...) / (< ...) / (> ...) / (<= ...) / (>= ...) / (<> ...) Lisp-like prefix syntax. Boolean operators: (and ...) and (or ...).

Functions (built-in)

The Installer ships with ~30 built-in functions. Selected highlights:

Function Returns Purpose
(askdir ...) dest-dir string User picks a directory.
(askfile ...) file path User picks a file.
(askstring ...) string User enters a string.
(asknumber ...) integer User enters a number.
(askchoice ...) integer User picks from a list.
(askbool ...) 0 or 1 Yes/no prompt.
(askdisk ...) volume name User picks a disk.
(exists <path>) 0 or 1 Does the file/dir exist?
(earlier <path>) 0 or 1 Was a previous version installed?
(getsize <path>) size in bytes File size.
(getdiskspace <vol>) free bytes Available space on volume.
(getversion <path>) integer $VER: of a file as a single int.
(getenv <name>) string DOS environment variable.
(getassign <name>) string Multi-assign string.
(iconinfo <path>) type Detect if icon is a tool/project/drawer.
(database ...) rc Update or query the Workbench database.
(patmatch <pat> <str>) 0 or 1 AmigaDOS pattern match.
(cat a b c ...) string Concatenate strings.
(substr <s> <off> <len>) string Substring.
(strlen <s>) integer String length.
(tackon <dir> <name>) string Join path components.
(fileonly <path>) string Trailing filename.
(pathonly <path>) string Leading directory.

Pre-defined variables

Pre-defined symbols are set by the Installer and read by the script:

Variable Meaning
@installer-version Version number of the running Installer (e.g., 45 for V45.x).
@default-dest The Installer's suggested install path. Update this if the user picks a non-default.
@user-level Current user level (0 = novice, 1 = average, 2 = expert).
@pretend 1 if Pretend mode is active.
@app-name The APPNAME startup argument, if any.
@icon Full path of the icon used to start the Installer.
@ioerr Last DOS error code, after a failed (run), (execute), or (rexx).
@error-msg Error text, set by a (trap) for inspection.
@special-msg Custom error text the script wants to substitute.
@each-name, @each-type Per-iteration variables in a (foreach).
@copyfiles-help, @makedir-help, ... Default help strings for the common statements; can be appended to per-call help.

User-defined procedures

A script can define its own commands via (procedure ...):

(procedure P_install_files #src #dst
  (makedir #dst (prompt "Creating drawer") (help @copyfiles-help))
  (copyfiles (source #src) (dest #dst)
             (prompt "Copying files")
             (help @copyfiles-help)))

; then call it later
(P_install_files "Source/Foo" #dest-dir)

This is how complex install scripts stay readable: each procedure is a small, named, parameterised block.

Worked example

A complete, real-world style .install for a small program:

; Foo 1.3 install script

(set @app-name "Foo")
(set #needed-version 39)        ; requires Workbench 2.04 (KS 39) or later
(set #needed-bytes 200000)      ; ~200 KB

(welcome)
(message "Welcome to Foo 1.3, by Acme Ltd.")
(message "This will install Foo into a drawer of your choice.")

; --- check OS version ---
(if (< @installer-version 43)
    (abort "Foo 1.3 requires Installer V43 or later. Please update your Installer."))
(set #os-version (getversion "LIBS:exec.library"))
(if (< #os-version #needed-version)
    (abort "Foo 1.3 requires Workbench 2.04 (Kickstart %d) or later.\n"
           #needed-version))

; --- check destination space ---
(set #dest-dir
  (askdir (prompt "Where do you want to install Foo?")
          (help "Pick the drawer where Foo will be installed.")
          (default "Work:")
          (disk)))
(if (= #dest-dir "")
    (abort "Installation cancelled."))
(if (< (getdiskspace (getdevice #dest-dir)) #needed-bytes)
    (abort "Not enough free space on %s. Need %d bytes."
           (getdevice #dest-dir) #needed-bytes))

; --- install ---
(makedir #dest-dir (prompt "Creating drawer") (help @makedir-help))
(copyfiles (source "Foo")
           (dest #dest-dir)
           (infos)
           (prompt "Copying Foo files")
           (help @copyfiles-help))

(copylib (source "libs/foo.library")
         (dest "LIBS:")
         (prompt "Installing foo.library")
         (help @copylib-help))

(tooltype (dest (tackon #dest-dir "Foo"))
          (setdefaulttool "Foo")
          (setstack 20000))

(startup "Foo"
         (prompt "Adding Foo to your S:User-Startup")
         (help "Adds the line 'Assign Foo: %s' to S:User-Startup." #dest-dir)
         (command "Assign Foo: %s" #dest-dir))

(database (tackon #dest-dir "Foo.info") 4)   ; add to WB database as a drawer

(complete 0)
(message "Foo 1.3 installed successfully.")
(message "Find Foo in %s" #dest-dir)
(exit)

Best practices

  • (help ...) every prompt. The user can press HELP at any time; an empty help is hostile.
  • Default values for (askdir) etc. — Work: is the right default for AmigaOS 3.x.
  • (complete 0) at the end to clear the backtrace stack before (exit).
  • Don't hardcode C: or other system paths. Use assigns.
  • Re-run-safe: use (copylib) for libraries, (earlier) to check for prior versions.
  • Hide system files: in (copyfiles), pass (pattern "~(c|l|s|.#?|#.info)") to skip c/l/s/source/object files when copying a drawer.
  • Log everything important: pass (confirm) only on the actions the user should be able to veto, not on every copy.

See Also


Sources: HAAGE & Partner Computer GmbH, "Installer.guide" V44.6 (25.10.1999), NDK 3.9 distribution; Amiga Inc., Installer release notes V44–V45.5. Source: raw/installer/installer-guide-extract.txt (extracted from NDK 3.9 Tools/Installer/Installer.guide). Raw: raw/installer/Installer.guide; raw/installer/Installer_relnotes Updated: 2026-10-04