diff --git a/language-docker.cabal b/language-docker.cabal
--- a/language-docker.cabal
+++ b/language-docker.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 45d12a07b59b5903ce169f73c62a7e76c05e07f20c8a859dd83b4b7aaaa0b081
+-- hash: 1dcabc3e868541acb7c49590054c62c6637d1deaefc81e4b39de64333bc9d239
 
 name:           language-docker
-version:        10.4.3
+version:        11.0.0
 synopsis:       Dockerfile parser, pretty-printer and embedded DSL
 description:    All functions for parsing and pretty-printing Dockerfiles are exported through @Language.Docker@. For more fine-grained operations look for specific modules that implement a certain functionality.
                 See the <https://github.com/hadolint/language-docker GitHub project> for the source-code and examples.
@@ -73,6 +73,7 @@
       base >=4.8 && <5
     , bytestring >=0.10
     , containers
+    , data-default
     , data-default-class
     , megaparsec >=9.0.0
     , prettyprinter
@@ -86,6 +87,7 @@
   main-is: Spec.hs
   other-modules:
       Language.Docker.IntegrationSpec
+      Language.Docker.ParseAddSpec
       Language.Docker.ParseCmdSpec
       Language.Docker.ParseCopySpec
       Language.Docker.ParsePragmaSpec
@@ -108,6 +110,7 @@
     , base >=4.8 && <5
     , bytestring >=0.10
     , containers
+    , data-default
     , data-default-class
     , hspec
     , hspec-megaparsec
diff --git a/src/Language/Docker/Parser/Copy.hs b/src/Language/Docker/Parser/Copy.hs
--- a/src/Language/Docker/Parser/Copy.hs
+++ b/src/Language/Docker/Parser/Copy.hs
@@ -9,9 +9,10 @@
 import Language.Docker.Parser.Prelude
 import Language.Docker.Syntax
 
-data CopyFlag
+data Flag
   = FlagChown Chown
   | FlagChmod Chmod
+  | FlagLink Link
   | FlagSource CopySource
   | FlagInvalid (Text, Text)
 
@@ -21,14 +22,16 @@
   flags <- copyFlag `sepEndBy` requiredWhitespace
   let chownFlags = [c | FlagChown c <- flags]
   let chmodFlags = [c | FlagChmod c <- flags]
+  let linkFlags = [l | FlagLink l <- flags]
   let sourceFlags = [f | FlagSource f <- flags]
   let invalid = [i | FlagInvalid i <- flags]
   -- Let's do some validation on the flags
-  case (invalid, chownFlags, chmodFlags, sourceFlags) of
-    ((k, v) : _, _, _, _) -> unexpectedFlag k v
-    (_, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--chown"
-    (_, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--chmod"
-    (_, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--from"
+  case (invalid, chownFlags, chmodFlags, linkFlags, sourceFlags) of
+    ((k, v) : _, _, _, _, _) -> unexpectedFlag k v
+    (_, _ : _ : _, _, _, _) -> customError $ DuplicateFlagError "--chown"
+    (_, _, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--chmod"
+    (_, _, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--link"
+    (_, _, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--from"
     _ -> do
       let cho =
             case chownFlags of
@@ -38,12 +41,16 @@
             case chmodFlags of
               [] -> NoChmod
               c : _ -> c
+      let lnk =
+            case linkFlags of
+              [] -> NoLink
+              l : _ -> l
       let fr =
             case sourceFlags of
               [] -> NoSource
               f : _ -> f
-      try (heredocList (\src dest -> Copy (CopyArgs src dest cho chm fr)))
-        <|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest cho chm fr))
+      try (heredocList (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr)))
+        <|> fileList "COPY" (\src dest -> Copy (CopyArgs src dest) (CopyFlags cho chm lnk fr))
 
 parseAdd :: (?esc :: Char) => Parser (Instruction Text)
 parseAdd = do
@@ -51,13 +58,15 @@
   flags <- addFlag `sepEndBy` requiredWhitespace
   let chownFlags = [c | FlagChown c <- flags]
   let chmodFlags = [c | FlagChmod c <- flags]
+  let linkFlags = [l | FlagLink l <- flags]
   let invalidFlags = [i | FlagInvalid i <- flags]
   notFollowedBy (string "--") <?>
     "only the --chown flag, the --chmod flag or the src and dest paths"
-  case (invalidFlags, chownFlags, chmodFlags) of
-    ((k, v) : _, _, _) -> unexpectedFlag k v
-    (_, _ : _ : _, _) -> customError $ DuplicateFlagError "--chown"
-    (_, _, _ : _ : _) -> customError $ DuplicateFlagError "--chmod"
+  case (invalidFlags, chownFlags, linkFlags, chmodFlags) of
+    ((k, v) : _, _, _, _) -> unexpectedFlag k v
+    (_, _ : _ : _, _, _) -> customError $ DuplicateFlagError "--chown"
+    (_, _, _ : _ : _, _) -> customError $ DuplicateFlagError "--chmod"
+    (_, _, _, _ : _ : _) -> customError $ DuplicateFlagError "--link"
     _ -> do
       let cho = case chownFlags of
                   [] -> NoChown
@@ -65,7 +74,11 @@
       let chm = case chmodFlags of
                   [] -> NoChmod
                   c : _ -> c
-      fileList "ADD" (\src dest -> Add (AddArgs src dest cho chm))
+      let lnk =
+            case linkFlags of
+              [] -> NoLink
+              l : _ -> l
+      fileList "ADD" (\src dest -> Add (AddArgs src dest) (AddFlags cho chm lnk))
 
 heredocList :: (?esc :: Char) =>
                (NonEmpty SourcePath -> TargetPath -> Instruction Text) ->
@@ -97,12 +110,13 @@
 unexpectedFlag name "" = customFailure $ NoValueFlagError (T.unpack name)
 unexpectedFlag name _ = customFailure $ InvalidFlagError (T.unpack name)
 
-copyFlag :: (?esc :: Char) => Parser CopyFlag
+copyFlag :: (?esc :: Char) => Parser Flag
 copyFlag = (FlagSource <$> try copySource <?> "only one --from") <|> addFlag
 
-addFlag :: (?esc :: Char) => Parser CopyFlag
+addFlag :: (?esc :: Char) => Parser Flag
 addFlag = (FlagChown <$> try chown <?> "--chown")
   <|> (FlagChmod <$> try chmod <?> "--chmod")
+  <|> (FlagLink <$> try link <?> "--link")
   <|> (FlagInvalid <$> try anyFlag <?> "other flag")
 
 chown :: (?esc :: Char) => Parser Chown
@@ -116,6 +130,11 @@
   void $ string "--chmod="
   chm <- someUnless "the mode for chmod" (== ' ')
   return $ Chmod chm
+
+link :: Parser Link
+link = do
+  void $ string "--link"
+  return Link
 
 copySource :: (?esc :: Char) => Parser CopySource
 copySource = do
diff --git a/src/Language/Docker/PrettyPrint.hs b/src/Language/Docker/PrettyPrint.hs
--- a/src/Language/Docker/PrettyPrint.hs
+++ b/src/Language/Docker/PrettyPrint.hs
@@ -151,6 +151,12 @@
     Chmod c -> "--chmod=" <> pretty c
     NoChmod -> mempty
 
+prettyPrintLink :: Link -> Doc ann
+prettyPrintLink link =
+  case link of
+    Link -> "--link"
+    NoLink -> mempty
+
 prettyPrintCopySource :: CopySource -> Doc ann
 prettyPrintCopySource source =
   case source of
@@ -277,12 +283,15 @@
       prettyPrintRunNetwork network
       prettyPrintRunSecurity security
       prettyPrintArguments c
-    Copy CopyArgs {sourcePaths, targetPath, chownFlag, chmodFlag, sourceFlag} -> do
-      "COPY"
-      prettyPrintChown chownFlag
-      prettyPrintChmod chmodFlag
-      prettyPrintCopySource sourceFlag
-      prettyPrintFileList sourcePaths targetPath
+    Copy
+      CopyArgs {sourcePaths, targetPath}
+      CopyFlags {chmodFlag, chownFlag, linkFlag, sourceFlag} -> do
+        "COPY"
+        prettyPrintChown chownFlag
+        prettyPrintChmod chmodFlag
+        prettyPrintLink linkFlag
+        prettyPrintCopySource sourceFlag
+        prettyPrintFileList sourcePaths targetPath
     Cmd c -> do
       "CMD"
       prettyPrintArguments c
@@ -307,11 +316,14 @@
     From b -> do
       "FROM"
       prettyPrintBaseImage b
-    Add AddArgs {sourcePaths, targetPath, chownFlag, chmodFlag} -> do
-      "ADD"
-      prettyPrintChown chownFlag
-      prettyPrintChmod chmodFlag
-      prettyPrintFileList sourcePaths targetPath
+    Add
+      AddArgs {sourcePaths, targetPath}
+      AddFlags {chownFlag, chmodFlag, linkFlag} -> do
+        "ADD"
+        prettyPrintChown chownFlag
+        prettyPrintChmod chmodFlag
+        prettyPrintLink linkFlag
+        prettyPrintFileList sourcePaths targetPath
     Shell args -> do
       "SHELL"
       prettyPrintArguments args
diff --git a/src/Language/Docker/Syntax.hs b/src/Language/Docker/Syntax.hs
--- a/src/Language/Docker/Syntax.hs
+++ b/src/Language/Docker/Syntax.hs
@@ -140,6 +140,11 @@
       "" -> NoChmod
       _ -> Chmod (Text.pack ch)
 
+data Link
+  = Link
+  | NoLink
+  deriving (Show, Eq, Ord)
+
 data CopySource
   = CopySource !Text
   | NoSource
@@ -166,22 +171,40 @@
 data CopyArgs
   = CopyArgs
       { sourcePaths :: NonEmpty SourcePath,
-        targetPath :: !TargetPath,
-        chownFlag :: !Chown,
+        targetPath :: !TargetPath
+      }
+  deriving (Show, Eq, Ord)
+
+data CopyFlags
+  = CopyFlags
+      { chownFlag :: !Chown,
         chmodFlag :: !Chmod,
+        linkFlag :: !Link,
         sourceFlag :: !CopySource
       }
   deriving (Show, Eq, Ord)
 
+instance Default CopyFlags where
+  def = CopyFlags NoChown NoChmod NoLink NoSource
+
 data AddArgs
   = AddArgs
       { sourcePaths :: NonEmpty SourcePath,
-        targetPath :: !TargetPath,
-        chownFlag :: !Chown,
-        chmodFlag :: !Chmod
+        targetPath :: !TargetPath
       }
   deriving (Show, Eq, Ord)
 
+data AddFlags
+  = AddFlags
+      { chownFlag :: !Chown,
+        chmodFlag :: !Chmod,
+        linkFlag :: !Link
+      }
+  deriving (Show, Eq, Ord)
+
+instance Default AddFlags where
+  def = AddFlags NoChown NoChmod NoLink
+
 data Check args
   = Check !(CheckArgs args)
   | NoCheck
@@ -336,11 +359,11 @@
 -- | All commands available in Dockerfiles
 data Instruction args
   = From !BaseImage
-  | Add !AddArgs
+  | Add !AddArgs !AddFlags
   | User !Text
   | Label !Pairs
   | Stopsignal !Text
-  | Copy !CopyArgs
+  | Copy !CopyArgs !CopyFlags
   | Run !(RunArgs args)
   | Cmd !(Arguments args)
   | Shell !(Arguments args)
diff --git a/test/Language/Docker/ParseAddSpec.hs b/test/Language/Docker/ParseAddSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Language/Docker/ParseAddSpec.hs
@@ -0,0 +1,105 @@
+module Language.Docker.ParseAddSpec (spec) where
+
+import Data.Default
+import qualified Data.Text as Text
+import Language.Docker.Syntax
+import TestHelper
+import Test.Hspec
+
+
+spec :: Spec
+spec = do
+  describe "ADD" $ do
+    it "simple ADD" $
+      let file = Text.unlines ["ADD . /app", "ADD http://foo.bar/baz ."]
+       in assertAst
+            file
+            [ Add ( AddArgs [SourcePath "."] (TargetPath "/app") ) def,
+              Add
+                ( AddArgs [SourcePath "http://foo.bar/baz"] (TargetPath ".") )
+                def
+            ]
+    it "multifiles ADD" $
+      let file = Text.unlines ["ADD foo bar baz /app"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs
+                    (fmap SourcePath ["foo", "bar", "baz"])
+                    (TargetPath "/app")
+                )
+                def
+            ]
+    it "list of quoted files" $
+      let file = Text.unlines ["ADD [\"foo\", \"bar\", \"baz\", \"/app\"]"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs
+                    (fmap SourcePath ["foo", "bar", "baz"])
+                    (TargetPath "/app")
+                )
+                def
+            ]
+    it "with chown flag" $
+      let file = Text.unlines ["ADD --chown=root:root foo bar"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
+                ( AddFlags (Chown "root:root") NoChmod NoLink )
+            ]
+    it "with chmod flag" $
+      let file = Text.unlines ["ADD --chmod=640 foo bar"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
+                ( AddFlags NoChown (Chmod "640") NoLink )
+            ]
+    it "with link flag" $
+      let file = Text.unlines ["ADD --link foo bar"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
+                ( AddFlags NoChown NoChmod Link )
+            ]
+    it "with chown and chmod flag" $
+      let file = Text.unlines ["ADD --chown=root:root --chmod=640 foo bar"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
+                ( AddFlags (Chown "root:root") (Chmod "640") NoLink )
+            ]
+    it "with chown and chmod flag other order" $
+      let file = Text.unlines ["ADD --chmod=640 --chown=root:root foo bar"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
+                ( AddFlags (Chown "root:root") (Chmod "640") NoLink )
+            ]
+    it "with all flags" $
+      let file =
+            Text.unlines ["ADD --chmod=640 --chown=root:root --link foo bar"]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") )
+                ( AddFlags (Chown "root:root") (Chmod "640") Link )
+            ]
+    it "list of quoted files and chown" $
+      let file =
+            Text.unlines
+              [ "ADD --chown=user:group [\"foo\", \"bar\", \"baz\", \"/app\"]" ]
+       in assertAst
+            file
+            [ Add
+                ( AddArgs
+                    (fmap SourcePath ["foo", "bar", "baz"])
+                    (TargetPath "/app")
+                )
+                ( AddFlags (Chown "user:group") NoChmod NoLink )
+            ]
diff --git a/test/Language/Docker/ParseCopySpec.hs b/test/Language/Docker/ParseCopySpec.hs
--- a/test/Language/Docker/ParseCopySpec.hs
+++ b/test/Language/Docker/ParseCopySpec.hs
@@ -1,5 +1,6 @@
 module Language.Docker.ParseCopySpec where
 
+import Data.Default
 import qualified Data.Text as Text
 import Language.Docker.Syntax
 import TestHelper
@@ -13,64 +14,115 @@
       let file = Text.unlines ["COPY . /app", "COPY baz /some/long/path"]
        in assertAst
             file
-            [ Copy $ CopyArgs [SourcePath "."] (TargetPath "/app") NoChown NoChmod NoSource,
-              Copy $ CopyArgs [SourcePath "baz"] (TargetPath "/some/long/path") NoChown NoChmod NoSource
+            [ Copy ( CopyArgs [ SourcePath "." ] ( TargetPath "/app" ) ) def,
+              Copy
+                ( CopyArgs
+                    [ SourcePath "baz" ]
+                    ( TargetPath "/some/long/path" )
+                )
+                def
             ]
     it "multifiles COPY" $
       let file = Text.unlines ["COPY foo bar baz /app"]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo", "bar", "baz"]) (TargetPath "/app") NoChown NoChmod NoSource
+            [ Copy
+                ( CopyArgs
+                    (fmap SourcePath ["foo", "bar", "baz"])
+                    (TargetPath "/app")
+                )
+                def
             ]
     it "list of quoted files" $
       let file = Text.unlines ["COPY [\"foo\", \"bar\", \"baz\", \"/app\"]"]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo", "bar", "baz"]) (TargetPath "/app") NoChown NoChmod NoSource
+            [ Copy
+                ( CopyArgs
+                    (fmap SourcePath ["foo", "bar", "baz"])
+                    (TargetPath "/app")
+                )
+                def
             ]
     it "supports windows paths" $
       let file = Text.unlines ["COPY C:\\\\go C:\\\\go"]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["C:\\\\go"]) (TargetPath "C:\\\\go") NoChown NoChmod NoSource
+            [ Copy
+                ( CopyArgs
+                    (fmap SourcePath ["C:\\\\go"])
+                    (TargetPath "C:\\\\go")
+                )
+                def
             ]
     it "does not get confused with trailing whitespace" $
       let file = Text.unlines ["COPY a b  "]
        in assertAst
             file
-            [ Copy $ CopyArgs [SourcePath "a"] (TargetPath "b") NoChown NoChmod NoSource
-            ]
+            [ Copy ( CopyArgs [SourcePath "a"] (TargetPath "b") ) def ]
 
   describe "Copy with flags" $ do
     it "with chown flag" $
       let file = Text.unlines ["COPY --chown=user:group foo bar"]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo"]) (TargetPath "bar") (Chown "user:group") NoChmod NoSource
+            [ Copy
+                ( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
+                ( CopyFlags ( Chown "user:group" ) NoChmod NoLink NoSource )
             ]
     it "with chmod flag" $
       let file = Text.unlines ["COPY --chmod=777 foo bar"]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo"]) (TargetPath "bar") NoChown (Chmod "777") NoSource
+            [ Copy
+                ( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
+                ( CopyFlags NoChown ( Chmod "777" ) NoLink NoSource )
             ]
+    it "with link flag" $
+      let file = Text.unlines [ "COPY --link source /target" ]
+       in assertAst
+            file
+            [ Copy
+                ( CopyArgs [ SourcePath "source" ] ( TargetPath "/target" ) )
+                ( CopyFlags NoChown NoChmod Link NoSource )
+            ]
     it "with from flag" $
       let file = Text.unlines ["COPY --from=node foo bar"]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo"]) (TargetPath "bar") NoChown NoChmod (CopySource "node")
+            [ Copy
+                ( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
+                ( CopyFlags NoChown NoChmod NoLink ( CopySource "node" ) )
             ]
-    it "with all three flags" $
-      let file = Text.unlines ["COPY --from=node --chmod=751 --chown=user:group foo bar"]
+    it "with all flags" $
+      let file =
+            Text.unlines
+              [ "COPY --from=node --chmod=751 --link --chown=user:group foo bar" ]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo"]) (TargetPath "bar") (Chown "user:group") (Chmod "751") (CopySource "node")
+            [ Copy
+                ( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
+                ( CopyFlags
+                    (Chown "user:group")
+                    (Chmod "751")
+                    Link
+                    (CopySource "node")
+                )
             ]
-    it "with all three flags in different order" $
-      let file = Text.unlines ["COPY --chown=user:group --from=node --chmod=644 foo bar"]
+    it "with all flags in different order" $
+      let file =
+            Text.unlines
+              [ "COPY --link --chown=user:group --from=node --chmod=644 foo bar" ]
        in assertAst
             file
-            [ Copy $ CopyArgs (fmap SourcePath ["foo"]) (TargetPath "bar") (Chown "user:group") (Chmod "644") (CopySource "node")
+            [ Copy
+                ( CopyArgs [ SourcePath "foo" ] (TargetPath "bar") )
+                ( CopyFlags
+                    (Chown "user:group")
+                    (Chmod "644")
+                    Link
+                    (CopySource "node")
+                )
             ]
 
   describe "Copy with Heredocs" $ do
@@ -78,65 +130,112 @@
       let file = Text.unlines ["COPY <<EOF /target", "EOF"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "EOF"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [SourcePath "EOF"] (TargetPath "/target") )
+                  def
               ]
     it "foo heredoc" $
       let file = Text.unlines ["COPY <<FOO /target", "foo", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [SourcePath "FOO"] (TargetPath "/target") )
+                  def
               ]
     it "foo heredoc lowercase +extensions" $
-      let file = Text.unlines ["COPY <<foo.txt /target", "foo content", "line 2", "foo.txt"]
+      let file =
+            Text.unlines
+              [ "COPY <<foo.txt /target", "foo content", "line 2", "foo.txt" ]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "foo.txt"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [SourcePath "foo.txt"] (TargetPath "/target") )
+                  def
               ]
     it "foo heredoc single quoted marker" $
       let file = Text.unlines ["COPY <<\'FOO\' /target", "foo", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [SourcePath "FOO"] (TargetPath "/target") )
+                  def
               ]
     it "foo heredoc double quoted marker" $
       let file = Text.unlines ["COPY <<\"FOO\" /target", "foo", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [SourcePath "FOO"] (TargetPath "/target") )
+                  def
               ]
     it "foo heredoc +dash" $
       let file = Text.unlines ["COPY <<-FOO /target", "foo", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [SourcePath "FOO"] (TargetPath "/target") )
+                  def
               ]
     it "foo heredoc single quoted marker +dash" $
       let file = Text.unlines ["COPY <<-\'FOO\' /target", "foo", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [ SourcePath "FOO" ] ( TargetPath "/target" ) )
+                  def
               ]
     it "foo heredoc double quoted marker +dash" $
       let file = Text.unlines ["COPY <<-\"FOO\" /target", "foo", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [ SourcePath "FOO" ] ( TargetPath "/target" ) )
+                  def
               ]
     it "multiple heredocs" $
-      let file = Text.unlines ["COPY <<FOO <<BAR /target", "foo", "FOO", "bar", "BAR"]
+      let file =
+            Text.unlines
+              [ "COPY <<FOO <<BAR /target", "foo", "FOO", "bar", "BAR" ]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO", SourcePath "BAR"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs
+                      [ SourcePath "FOO", SourcePath "BAR" ]
+                      ( TargetPath "/target" )
+                  )
+                  def
               ]
     it "multiple heredocs with single/double quotes and dash mixed" $
-      let file = Text.unlines ["COPY <<FOO <<-\"BAR\" <<\'FIZZ\' <<-BUZZ /target", "foo", "FOO", "bar", "BAR", "fizz", "FIZZ", "buss", "BUZZ"]
+      let file =
+            Text.unlines
+              [ "COPY <<FOO <<-\"BAR\" <<\'FIZZ\' <<-BUZZ /target",
+                "foo",
+                "FOO",
+                "bar",
+                "BAR",
+                "fizz",
+                "FIZZ",
+                "buss",
+                "BUZZ"
+              ]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO", SourcePath "BAR", SourcePath "FIZZ", SourcePath "BUZZ"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs
+                      [ SourcePath "FOO",
+                        SourcePath "BAR",
+                        SourcePath "FIZZ",
+                        SourcePath "BUZZ"
+                      ]
+                      ( TargetPath "/target" )
+                  )
+                  def
               ]
     it "foo heredoc with line continuations" $
       let file = Text.unlines ["COPY <<FOO /target", "foo \\", "bar", "FOO"]
        in assertAst
             file
-              [ Copy $ CopyArgs [SourcePath "FOO"] (TargetPath "/target") NoChown NoChmod NoSource
+              [ Copy
+                  ( CopyArgs [ SourcePath "FOO" ] ( TargetPath "/target" ) )
+                  def
               ]
diff --git a/test/Language/Docker/ParseRunSpec.hs b/test/Language/Docker/ParseRunSpec.hs
--- a/test/Language/Docker/ParseRunSpec.hs
+++ b/test/Language/Docker/ParseRunSpec.hs
@@ -569,8 +569,6 @@
                 ( CopyArgs
                     [ SourcePath "EOF" ]
                     (TargetPath "/foobar.sh")
-                    NoChown
-                    NoChmod
-                    NoSource
                 )
+                ( def :: CopyFlags )
             ]
diff --git a/test/Language/Docker/ParserSpec.hs b/test/Language/Docker/ParserSpec.hs
--- a/test/Language/Docker/ParserSpec.hs
+++ b/test/Language/Docker/ParserSpec.hs
@@ -335,53 +335,3 @@
     it "should handle lowercase instructions (#7 - https://github.com/beijaflor-io/haskell-language-dockerfile/issues/7)" $
       let content = "from ubuntu"
        in assertAst content [From (untaggedImage "ubuntu")]
-  describe "ADD" $ do
-    it "simple ADD" $
-      let file = Text.unlines ["ADD . /app", "ADD http://foo.bar/baz ."]
-       in assertAst
-            file
-            [ Add $ AddArgs [SourcePath "."] (TargetPath "/app") NoChown NoChmod,
-              Add $ AddArgs [SourcePath "http://foo.bar/baz"] (TargetPath ".") NoChown NoChmod
-            ]
-    it "multifiles ADD" $
-      let file = Text.unlines ["ADD foo bar baz /app"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo", "bar", "baz"]) (TargetPath "/app") NoChown NoChmod
-            ]
-    it "list of quoted files" $
-      let file = Text.unlines ["ADD [\"foo\", \"bar\", \"baz\", \"/app\"]"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo", "bar", "baz"]) (TargetPath "/app") NoChown NoChmod
-            ]
-    it "with chown flag" $
-      let file = Text.unlines ["ADD --chown=root:root foo bar"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") (Chown "root:root") NoChmod
-            ]
-    it "with chmod flag" $
-      let file = Text.unlines ["ADD --chmod=640 foo bar"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") NoChown (Chmod "640")
-            ]
-    it "with chown and chmod flag" $
-      let file = Text.unlines ["ADD --chown=root:root --chmod=640 foo bar"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") (Chown "root:root") (Chmod "640")
-            ]
-    it "with chown and chmod flag other order" $
-      let file = Text.unlines ["ADD --chmod=640 --chown=root:root foo bar"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo"]) (TargetPath "bar") (Chown "root:root") (Chmod "640")
-            ]
-    it "list of quoted files and chown" $
-      let file = Text.unlines ["ADD --chown=user:group [\"foo\", \"bar\", \"baz\", \"/app\"]"]
-       in assertAst
-            file
-            [ Add $ AddArgs (fmap SourcePath ["foo", "bar", "baz"]) (TargetPath "/app") (Chown "user:group") NoChmod
-            ]
diff --git a/test/Language/Docker/PrettyPrintSpec.hs b/test/Language/Docker/PrettyPrintSpec.hs
--- a/test/Language/Docker/PrettyPrintSpec.hs
+++ b/test/Language/Docker/PrettyPrintSpec.hs
@@ -3,6 +3,7 @@
 
 module Language.Docker.PrettyPrintSpec where
 
+import Data.Default
 import qualified Data.Text as Text
 import Prettyprinter
 import Prettyprinter.Render.Text
@@ -17,101 +18,79 @@
   describe "pretty print ADD" $ do
     it "with just copy" $ do
       let add = Add
-                  ( AddArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      NoChown
-                      NoChmod
-                  )
+                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( def :: AddFlags )
        in assertPretty "ADD foo bar" add
     it "with just chown" $ do
       let add = Add
-                  ( AddArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      (Chown "root:root")
-                      NoChmod
-                  )
+                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( AddFlags ( Chown "root:root" ) NoChmod NoLink )
        in assertPretty "ADD --chown=root:root foo bar" add
     it "with just chmod" $ do
       let add = Add
-                  ( AddArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      NoChown
-                      (Chmod "751")
-                  )
+                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( AddFlags NoChown ( Chmod "751" ) NoLink )
        in assertPretty "ADD --chmod=751 foo bar" add
-    it "with both chown and chmod" $ do
+    it "with just link" $ do
       let add = Add
-                  ( AddArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      (Chown "root:root")
-                      (Chmod "751")
-                  )
-       in assertPretty "ADD --chown=root:root --chmod=751 foo bar" add
+                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( AddFlags NoChown NoChmod Link )
+       in assertPretty "ADD --link foo bar" add
+    it "with chown, chmod and link" $ do
+      let add = Add
+                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( AddFlags ( Chown "root:root" ) ( Chmod "751" ) Link )
+       in assertPretty "ADD --chown=root:root --chmod=751 --link foo bar" add
+
   describe "pretty print COPY" $ do
     it "with just copy" $ do
       let copy = Copy
-                  ( CopyArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      NoChown
-                      NoChmod
-                      NoSource
-                  )
+                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( def :: CopyFlags )
        in assertPretty "COPY foo bar" copy
     it "with just chown" $ do
       let copy = Copy
-                  ( CopyArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      (Chown "root:root")
-                      NoChmod
-                      NoSource
-                  )
+                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( CopyFlags ( Chown "root:root" ) NoChmod NoLink NoSource )
        in assertPretty "COPY --chown=root:root foo bar" copy
     it "with just chmod" $ do
       let copy = Copy
-                  ( CopyArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      NoChown
-                      (Chmod "751")
-                      NoSource
-                  )
+                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( CopyFlags NoChown ( Chmod "751" ) NoLink NoSource )
        in assertPretty "COPY --chmod=751 foo bar" copy
-    it "with source baseimage" $ do
+    it "with just link" $ do
       let copy = Copy
-                  ( CopyArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      NoChown
-                      NoChmod
-                      (CopySource "baseimage")
-                  )
+                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+                  ( CopyFlags NoChown NoChmod Link NoSource )
+       in assertPretty "COPY --link foo bar" copy
+    it "with source baseimage" $ do
+      let copy =
+            Copy
+              ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+              ( CopyFlags NoChown NoChmod NoLink ( CopySource "baseimage" ) )
        in assertPretty "COPY --from=baseimage foo bar" copy
     it "with both chown and chmod" $ do
-      let copy = Copy
-                  ( CopyArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      (Chown "root:root")
-                      (Chmod "751")
-                      NoSource
-                  )
+      let copy =
+            Copy
+              ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+              ( CopyFlags
+                  ( Chown "root:root" ) ( Chmod "751" ) NoLink NoSource
+              )
        in assertPretty "COPY --chown=root:root --chmod=751 foo bar" copy
-    it "with all three: from, chown and chmod" $ do
-      let copy = Copy
-                  ( CopyArgs
-                      [SourcePath "foo"]
-                      (TargetPath "bar")
-                      (Chown "root:root")
-                      (Chmod "751")
-                      (CopySource "baseimage")
-                  )
-       in assertPretty "COPY --chown=root:root --chmod=751 --from=baseimage foo bar" copy
+    it "with all flags" $ do
+      let copy =
+            Copy
+              ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
+              ( CopyFlags
+                  ( Chown "root:root")
+                  ( Chmod "751")
+                  Link
+                  ( CopySource "baseimage" )
+              )
+       in assertPretty
+            "COPY --chown=root:root --chmod=751 --link --from=baseimage foo bar"
+            copy
+
   describe "pretty print # escape" $ do
     it "# escape = \\" $ do
       let esc = Pragma (Escape (EscapeChar '\\'))
@@ -119,6 +98,7 @@
     it "# escape = `" $ do
       let esc = Pragma (Escape (EscapeChar '`'))
        in assertPretty "# escape = `" esc
+
   describe "pretty print # syntax" $ do
     it "# syntax = docker/dockerfile:1.0" $ do
       let img = Pragma
@@ -132,6 +112,7 @@
                     )
                   )
        in assertPretty "# syntax = docker/dockerfile:1.0" img
+
 
 assertPretty :: Text.Text -> Instruction Text.Text -> Assertion
 assertPretty expected inst = assertEqual
