diff --git a/.clj-kondo/clj-kondo/slingshot/clj_kondo/slingshot/try_plus.clj b/.clj-kondo/clj-kondo/slingshot/clj_kondo/slingshot/try_plus.clj
new file mode 100644
index 00000000..48a4c174
--- /dev/null
+++ b/.clj-kondo/clj-kondo/slingshot/clj_kondo/slingshot/try_plus.clj
@@ -0,0 +1,44 @@
+(ns clj-kondo.slingshot.try-plus
+  (:require [clj-kondo.hooks-api :as api]))
+
+(defn expand-catch [catch-node]
+  (let [[catch catchee & exprs] (:children catch-node)
+        catchee-sexpr (api/sexpr catchee)]
+    (cond (vector? catchee-sexpr)
+          (let [[selector & exprs] exprs]
+            (api/list-node
+             [catch (api/token-node 'Exception) (api/token-node '_e#)
+              (api/list-node
+               (list* (api/token-node 'let)
+                      (api/vector-node [selector (api/token-node nil)])
+                      exprs))]))
+          :else catch-node)))
+
+(defn try+ [{:keys [node]}]
+  (let [children (rest (:children node))
+        [body catches]
+        (loop [body children
+               body-exprs []
+               catches []]
+          (if (seq body)
+            (let [f (first body)
+                  f-sexpr (api/sexpr f)]
+              (if (and (seq? f-sexpr) (= 'catch (first f-sexpr)))
+                (recur (rest body)
+                       body-exprs
+                       (conj catches (expand-catch f)))
+                (recur (rest body)
+                       (conj body-exprs f)
+                       catches)))
+            [body-exprs catches]))
+        new-node (api/list-node
+                  [(api/token-node 'let)
+                   (api/vector-node
+                    [(api/token-node '&throw-context) (api/token-node nil)])
+                   (api/token-node '&throw-context) ;; use throw-context to avoid warning
+                   (with-meta (api/list-node (list* (api/token-node 'try)
+                                                    (concat body catches)))
+                     (meta node))])]
+    ;; (prn (api/sexpr new-node))
+    {:node new-node}))
+
diff --git a/.clj-kondo/clj-kondo/slingshot/config.edn b/.clj-kondo/clj-kondo/slingshot/config.edn
new file mode 100644
index 00000000..446d4f0c
--- /dev/null
+++ b/.clj-kondo/clj-kondo/slingshot/config.edn
@@ -0,0 +1,2 @@
+{:hooks
+ {:analyze-call {slingshot.slingshot/try+ clj-kondo.slingshot.try-plus/try+}}}
diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn
new file mode 100644
index 00000000..51b99827
--- /dev/null
+++ b/.clj-kondo/config.edn
@@ -0,0 +1,19 @@
+{:config-paths ^:replace [] ;; don't adopt any user preferences
+
+ :hooks
+ ;; for now we'll use the simple macroexpand, can move to hooks for finer grained errors later
+ {:macroexpand
+  {etaoin.util/defmethods etaoin.util/defmethods
+   etaoin.util/with-tmp-dir etaoin.util/with-tmp-dir
+   etaoin.util/with-tmp-file etaoin.util/with-tmp-file
+
+   etaoin.api/with-key-down etaoin.api/with-key-down
+   etaoin.api/with-pointer-btn-down etaoin.api/with-pointer-btn-down
+   etaoin.api/with-pointer-left-btn-down etaoin.api/with-pointer-left-btn-down
+   etaoin.api/with-driver etaoin.api/with-driver
+   etaoin.api/with-chrome etaoin.api/with-chrome
+   etaoin.api/with-firefox etaoin.api/with-firefox}}
+
+ :linters
+ ;; etaoin is dsl-ish and does make use of :refer :all, can decide if we like that at some later date
+ {:refer-all {:level :off}}}
diff --git a/.clj-kondo/etaoin/api.clj b/.clj-kondo/etaoin/api.clj
new file mode 100644
index 00000000..3c371de7
--- /dev/null
+++ b/.clj-kondo/etaoin/api.clj
@@ -0,0 +1,41 @@
+(ns etaoin.api)
+
+(defmacro with-key-down
+  [input key & body]
+  `(-> ~input
+       (add-key-down ~key)
+       ~@body
+       (add-key-up ~key)))
+
+(defmacro with-pointer-btn-down
+  [input button & body]
+  `(-> ~input
+       (add-pointer-down ~button)
+       ~@body
+       (add-pointer-up ~button)))
+
+(defmacro with-pointer-left-btn-down
+  [input & body]
+  `(-> ~input
+       add-pointer-down
+       ~@body
+       add-pointer-up))
+
+;; simplified to remove with-pool which is of no consequence to linting
+(defmacro with-driver
+  [type opt bind & body]
+  `(let [~bind (boot-driver ~type ~opt)]
+     (try
+       ~@body
+       (finally
+         (quit ~bind)))))
+
+(defmacro with-firefox
+  [opt bind & body]
+  `(with-driver :firefox ~opt ~bind
+     ~@body))
+
+(defmacro with-chrome
+  [opt bind & body]
+  `(with-driver :chrome ~opt ~bind
+     ~@body))
diff --git a/.clj-kondo/etaoin/util.clj b/.clj-kondo/etaoin/util.clj
new file mode 100644
index 00000000..bc21e5a3
--- /dev/null
+++ b/.clj-kondo/etaoin/util.clj
@@ -0,0 +1,18 @@
+(ns etaoin.util)
+
+(defmacro defmethods
+  "Declares multimethods in batch. For each dispatch value from
+  dispatch-vals, creates a new method."
+  [multifn dispatch-vals & fn-tail]
+  `(doseq [dispatch-val# ~dispatch-vals]
+     (defmethod ~multifn dispatch-val# ~@fn-tail)))
+
+;; essence only for linting
+(defmacro with-tmp-file [prefix suffix bind & body]
+  `(let [~bind "somepath"]
+     ~@body))
+
+;; essence only for linting
+(defmacro with-tmp-dir [prefix bind & body]
+  `(let [~bind "somepath"]
+     ~@body))
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 17724ee7..128c411d 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -6,6 +6,7 @@ A release with an intentional breaking changes is marked with [breaking]
 
 * https://github.com/clj-commons/etaoin/issues/383[#383]: Drop testing for Safari on Windows, Apple no longer releases Safari for Windows
 * https://github.com/clj-commons/etaoin/issues/388[#388]: Drop testing for PhantomJS, development has long ago stopped for PhantomJS
+* https://github.com/clj-commons/etaoin/issues/387[#387]: No longer testing multiple key modifiers for a single webdriver send keys request
 * https://github.com/clj-commons/etaoin/issues/384[#384]: Look for `safaridriver` on PATH by default
 * https://github.com/clj-commons/etaoin/issues/402[#402]: Only send body for webdriver `POST` requests to appease `safaridriver`
 * https://github.com/clj-commons/etaoin/issues/403[#403]: The `select` fn now clicks on the `select` element before clicking the `option` element to appease `safaridriver`
@@ -16,7 +17,7 @@ A release with an intentional breaking changes is marked with [breaking]
 * Internal quality
 ** https://github.com/clj-commons/etaoin/issues/382[#382]: Fix process fork testing on Windows
 ** https://github.com/clj-commons/etaoin/issues/391[#391]: Identify browser name on failed ide tests
-** https://github.com/clj-commons/etaoin/issues/387[#387]: No longer testing multiple key modifiers for a single webdriver send keys request
+** https://github.com/clj-commons/etaoin/issues/390[#390]: Add internal clj-kondo config
 
 == v0.4.6
 
diff --git a/env/dev/demo.clj b/env/dev/demo.clj
index 93efdaae..df7b5b9e 100644
--- a/env/dev/demo.clj
+++ b/env/dev/demo.clj
@@ -1,4 +1,4 @@
-
+#_{:clj-kondo/ignore [:use]}
 (use 'etaoin.api)
 (require '[etaoin.keys :as k])
 
diff --git a/src/etaoin/api.clj b/src/etaoin/api.clj
index 87dbf9b8..c4d01137 100644
--- a/src/etaoin/api.clj
+++ b/src/etaoin/api.clj
@@ -34,8 +34,7 @@
             [slingshot.slingshot :refer [try+ throw+]])
 
   (:import java.util.Date
-           java.text.SimpleDateFormat
-           (java.io IOException)))
+           java.text.SimpleDateFormat))
 
 ;;
 ;; defaults
@@ -107,7 +106,7 @@
                      :method :get
                      :path [:session (:session driver) :element :active])))
   "
-  [{:keys [driver method path data result]}]
+  [{:keys [driver method path data]}]
   (client/call driver method path data))
 
 ;;
@@ -839,7 +838,7 @@
 
 (defmethod perform-actions
   :phantom
-  [driver input & inputs]
+  [_driver _input & _inputs]
   (util/error "Phantom doesn't support w3c actions."))
 
 (defmulti release-actions dispatch-driver)
@@ -854,7 +853,7 @@
 
 (defmethod release-actions
   :phantom
-  [driver input & inputs]
+  [_driver _input & _inputs]
   (util/error "Phantom doesn't support w3c actions."))
 
 ;;
@@ -1765,14 +1764,14 @@
 (defn scroll-top
   "Scrolls to top of the page keeping current horizontal position."
   [driver]
-  (let [{:keys [x y]} (get-scroll driver)]
+  (let [{:keys [x _y]} (get-scroll driver)]
     (scroll driver x 0)))
 
 (defn scroll-bottom
   "Scrolls to bottom of the page keeping current horizontal position."
   [driver]
   (let [y-max         (js-execute driver "return document.body.scrollHeight;")
-        {:keys [x y]} (get-scroll driver)]
+        {:keys [x _y]} (get-scroll driver)]
     (scroll driver x y-max)))
 
 (def ^{:doc "Default scroll offset in pixels."}
@@ -2266,7 +2265,7 @@
 
 (defn wait
   "Sleeps for N seconds."
-  ([driver sec]
+  (#_{:clj-kondo/ignore [:unused-binding]} [driver sec]
    (wait sec))
   ([sec]
    (Thread/sleep (* sec 1000))))
@@ -2822,7 +2821,7 @@
 
   Under the hood, it sends the file's name as a sequence of keys
   to the input."
-  (fn [driver q file]
+  (fn [_driver _q file]
     (type file)))
 
 (defmethod upload-file String
@@ -2999,7 +2998,7 @@
 
 (defmethod screenshot-element
   :default
-  [driver q file]
+  [_driver _q _file]
   (util/error "This driver doesn't support screening elements."))
 
 (defmethods screenshot-element
@@ -3355,7 +3354,7 @@
 
   (try (delete-session driver)
        (catch Exception e
-         (if (not (= 404 (:status (ex-data e))))
+         (when (not (= 404 (:status (ex-data e))))
            ;; the exception was caused by something other than "session not found"
            (throw e))))
 
diff --git a/src/etaoin/client.clj b/src/etaoin/client.clj
index fade1ba5..c9c46512 100644
--- a/src/etaoin/client.clj
+++ b/src/etaoin/client.clj
@@ -45,9 +45,6 @@
 (defn- get-url-path [items]
   (str/join "/" (map url-item-str items)))
 
-(defn- status-selector [resp]
-  (-> resp :status integer?))
-
 (defmacro with-pool [opt & body]
   `(client/with-connection-pool ~opt
      ~@body))
diff --git a/src/etaoin/dev.clj b/src/etaoin/dev.clj
index a289ba7b..935097cf 100644
--- a/src/etaoin/dev.clj
+++ b/src/etaoin/dev.clj
@@ -11,7 +11,7 @@
 (defn try-parse-int
   [line]
   (try (Integer/parseInt line)
-       (catch Exception e
+       (catch Exception _e
          line)))
 
 
@@ -101,9 +101,9 @@
                          :headers headers}))
 
       :network/responsereceived
-      (let [{:keys [response]}                                params
-            {:keys [method headers mimeType remoteIPAddress]} response
-            {:keys [status]}                                  headers]
+      (let [{:keys [response]}                         params
+            {:keys [headers mimeType remoteIPAddress]} response
+            {:keys [status]}                           headers]
         (assoc acc
                :state 2
                :response {:status    (try-parse-int status)
diff --git a/src/etaoin/driver.clj b/src/etaoin/driver.clj
index 82adf6dc..6ee60fe7 100644
--- a/src/etaoin/driver.clj
+++ b/src/etaoin/driver.clj
@@ -110,27 +110,27 @@
 
 (defmethod options-name
   :firefox
-  [driver]
+  [_driver]
   :moz:firefoxOptions)
 
 (defmethod options-name
   :chrome
-  [driver]
+  [_driver]
   :chromeOptions)
 
 (defmethod options-name
   :safari
-  [driver]
+  [_driver]
   :safariOptions)
 
 (defmethod options-name
   :edge
-  [driver]
+  [_driver]
   :edgeOptions)
 
 (defmethod options-name
   :opera
-  [driver]
+  [_driver]
   :operaOptions)
 
 (defn set-options-args
@@ -148,7 +148,7 @@
 
 (defmethod set-profile
   :default
-  [driver profile]
+  [driver _profile]
   (log/infof "This driver doesn't support setting a profile.")
   driver)
 
@@ -191,7 +191,7 @@
 
 (defmethod set-window-size
   :default
-  [driver w h]
+  [driver _w _h]
   (log/infof "This driver doesn't support setting window size.")
   driver)
 
@@ -216,7 +216,7 @@
 
 (defmethod set-url
   :default
-  [driver url]
+  [driver _url]
   (log/infof "This driver doesn't support setting initial URL.")
   driver)
 
@@ -262,7 +262,7 @@
 
 (defmethod is-headless?
   :phantom
-  [driver]
+  [_driver]
   true)
 
 ;;
@@ -299,7 +299,7 @@
 
 (defmethod set-prefs
   :default
-  [driver prefs]
+  [driver _prefs]
   (log/infof "This driver doesn't support setting preferences.")
   driver)
 
@@ -314,8 +314,8 @@
 ;; Download folder
 ;;
 
-(defn- ^String add-trailing-slash
-  [^String path]
+(defn- add-trailing-slash
+  ^String [^String path]
   (let [sep java.io.File/separator]
     (if (string/ends-with? path sep)
       path
@@ -327,7 +327,7 @@
 
 (defmethod set-download-dir
   :default
-  [driver path]
+  [driver _path]
   (log/infof "This driver doesn't support setting a download directory.")
   driver)
 
@@ -497,13 +497,11 @@
   {:arglists '([driver user-agent])}
   dispatch-driver)
 
-
 (defmethods set-user-agent
   [:chrome :edge]
   [driver user-agent]
   (set-options-args driver [(str "--user-agent=" user-agent)]))
 
-
 (defmethods set-user-agent
   [:firefox]
   [driver user-agent]
@@ -511,6 +509,6 @@
 
 (defmethods set-user-agent
   [:default]
-  [driver user-agent]
+  [driver _user-agent]
   (log/infof "This driver doesn't support setting a user-agent.")
   driver)
diff --git a/src/etaoin/ide/api.clj b/src/etaoin/ide/api.clj
index e8450087..e093b424 100644
--- a/src/etaoin/ide/api.clj
+++ b/src/etaoin/ide/api.clj
@@ -43,7 +43,7 @@
    "COMMAND"      k/command
    "CONTROL"      k/control-left
    "CTRL"         k/control-left
-   "DECIMAL"      k/num-.
+   "DECIMAL"      #_{:clj-kondo/ignore [:unresolved-var]} k/num-.
    "DELETE"       k/delete
    "DIVIDE"       k/num-slash
    "DOWN"         k/arrow-down
@@ -93,7 +93,7 @@
    "NUMPAD7"      k/num-7
    "NUMPAD8"      k/num-9
    "NUMPAD9"      k/num-9
-   "NUM_PERIOD"   k/num-.
+   "NUM_PERIOD"   #_{:clj-kondo/ignore [:unresolved-var]} k/num-.
    "NUM_PLUS"     k/num-+
    "NUM_DIVISION" k/num-slash
    "NUM_MULTIPLY" k/num-*
@@ -174,6 +174,7 @@
 
 
 (defn dispatch-command
+  #_{:clj-kondo/ignore [:unused-binding]}
   [driver command & [opt]]
   (some-> command :command))
 
@@ -183,20 +184,20 @@
 
 (defmethod run-command
   :default
-  [driver command & _]
+  [_driver command & _]
   (log/warnf "The \"%s\" command is not implemented" (:command command)))
 
 
 (defmethod run-command
   :assert
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [_driver {:keys [target value command]} & [{vars :vars}]]
   (let [stored-value (str (get @vars (str->var target)))]
     (assert (= stored-value value) (make-assert-msg command stored-value value))))
 
 
 (defmethods run-command
   [:assertAlert :assertConfirmation :assertPrompt]
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [alert-msg (get-alert-text driver)]
     (dismiss-alert driver)
     (assert (= alert-msg target) (make-assert-msg command alert-msg target))))
@@ -204,21 +205,21 @@
 
 (defmethod run-command
   :assertChecked
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (selected? driver (make-query target))]
     (assert actual (make-assert-msg command actual true))))
 
 
 (defmethod run-command
   :assertNotChecked
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (selected? driver (make-query target))]
     (assert (not actual) (make-assert-msg command actual false))))
 
 
 (defmethod run-command
   :assertEditable
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [q      (make-query target)
         actual (and (enabled? driver (make-query target))
                     (nil? (get-element-attr driver q :readonly)))]
@@ -227,7 +228,7 @@
 
 (defmethod run-command
   :assertNotEditable
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [q      (make-query target)
         actual (and (enabled? driver (make-query target))
                     (nil? (get-element-attr driver q :readonly)))]
@@ -236,21 +237,21 @@
 
 (defmethod run-command
   :assertElementPresent
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (exists? driver (make-query target))]
     (assert actual (make-assert-msg command actual true))))
 
 
 (defmethod run-command
   :assertElementNotPresent
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (absent? driver (make-query target))]
     (assert actual (make-assert-msg command actual true))))
 
 
 (defmethods run-command
   [:assertValue :assertSelectedValue]
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-val (get-element-value driver (make-query target))]
     (assert (= actual-val value)
             (make-assert-msg command actual-val value))))
@@ -258,7 +259,7 @@
 
 (defmethod run-command
   :assertNotSelectedValue
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-val (get-element-value driver (make-query target))]
     (assert (not= actual-val value)
             (make-assert-msg command actual-val value))))
@@ -266,7 +267,7 @@
 
 (defmethod run-command
   :assertText
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-text (get-element-text driver (make-query target))]
     (assert (= actual-text value)
             (make-assert-msg command actual-text value))))
@@ -274,7 +275,7 @@
 
 (defmethod run-command
   :assertNotText
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-text (get-element-text driver (make-query target))]
     (assert (not= actual-text value)
             (make-assert-msg command actual-text value))))
@@ -282,7 +283,7 @@
 
 (defmethod run-command
   :assertSelectedLabel
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [q            (make-query target)
         selected-val (get-element-value driver q)
         option-el    (query driver q {:value selected-val})
@@ -293,14 +294,14 @@
 
 (defmethod run-command
   :assertTitle
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [title (get-title driver)]
     (assert (= title target) (make-assert-msg command title target))))
 
 
 (defmethod run-command
   :check
-  [driver {:keys [target]} & [{base-url :base-url}]]
+  [driver {:keys [target]} & [{_base-url :base-url}]]
   (let [q (make-query target)]
     (when-not (selected? driver q)
       (click driver q))))
@@ -308,7 +309,7 @@
 
 (defmethod run-command
   :click
-  [driver {:keys [target]} & [opt]]
+  [driver {:keys [target]} & [_opt]]
   (click driver (make-query target)))
 
 
@@ -320,13 +321,13 @@
 
 (defmethod run-command
   :doubleClick
-  [driver {:keys [target]} & [opt]]
+  [driver {:keys [target]} & [_opt]]
   (double-click driver (make-query target)))
 
 
 (defmethod run-command
   :dragAndDropToObject
-  [driver {:keys [target value]} & [opt]]
+  [driver {:keys [target value]} & [_opt]]
   (drag-and-drop driver
                  (make-query target)
                  (make-query value)))
@@ -334,7 +335,7 @@
 
 (defmethod run-command
   :echo
-  [driver {:keys [target]} {vars :vars}]
+  [_driver {:keys [target]} {vars :vars}]
   (println (fill-str-with-vars target @vars)))
 
 
@@ -357,14 +358,14 @@
 
 (defmethod run-command
   :pause
-  [driver {:keys [target]} & [opt]]
+  [_driver {:keys [target]} & [_opt]]
   (wait (/ (Integer/parseInt target) 1000)))
 
 
 ;; TODO refactor select fn, add select by-value
 (defmethods run-command
   [:select :addSelection :removeSelection]
-  [driver {:keys [target value]} & [opt]]
+  [driver {:keys [target value]} & [_opt]]
   (let [[type val] (str/split value #"=" 2)
         q          (make-query target)]
     (case type
@@ -378,7 +379,7 @@
 
 (defmethod run-command
   :selectFrame
-  [driver {:keys [target]} & [opt]]
+  [driver {:keys [target]} & [_opt]]
   (cond
     (= target "relative=top")
     (switch-frame-top driver)
@@ -428,14 +429,14 @@
 
 (defmethod run-command
   :setWindowSize
-  [driver {:keys [target]} & [opt]]
+  [driver {:keys [target]} & [_opt]]
   (let [[width height] (map #(Integer/parseInt %) (str/split target #"x"))]
     (set-window-size driver width height)))
 
 
 (defmethod run-command
   :store
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [_driver {:keys [target value]} & [{vars :vars}]]
   (swap! vars assoc (str->var value) target))
 
 
@@ -456,8 +457,8 @@
 
 (defmethod run-command
   :storeTitle
-  [driver {:keys [target value]} & [{vars :vars}]]
-  (let [title (get-title driver (make-query target))]
+  [driver {:keys [value]} & [{vars :vars}]]
+  (let [title (get-title driver)]
     (swap! vars assoc (str->var value) title)))
 
 
@@ -484,7 +485,7 @@
 
 (defmethod run-command
   :submit
-  [driver {:keys [target]} & [{vars :vars}]]
+  [driver {:keys [target]} & [{_vars :vars}]]
   (fill-el driver (query (make-query target) {:tag :input}) k/enter))
 
 
@@ -497,7 +498,7 @@
 
 (defmethod run-command
   :unCheck
-  [driver {:keys [target]} & [{base-url :base-url}]]
+  [driver {:keys [target]} & [{_base-url :base-url}]]
   (let [q (make-query target)]
     (when (selected? driver q)
       (click driver q))))
@@ -512,21 +513,21 @@
 
 (defmethod run-command
   :verifyChecked
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (selected? driver (make-query target))]
     (is (true? actual) (make-assert-msg command actual true))))
 
 
 (defmethod run-command
   :verifyNotChecked
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (selected? driver (make-query target))]
     (is (false? actual) (make-assert-msg command actual false))))
 
 
 (defmethod run-command
   :verifyEditable
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [q      (make-query target)
         actual (and (enabled? driver (make-query target))
                     (nil? (get-element-attr driver q :readonly)))]
@@ -535,7 +536,7 @@
 
 (defmethod run-command
   :verifyNotEditable
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [q      (make-query target)
         actual (and (enabled? driver (make-query target))
                     (nil? (get-element-attr driver q :readonly)))]
@@ -544,21 +545,21 @@
 
 (defmethod run-command
   :verifyElementPresent
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (exists? driver (make-query target))]
     (is (true? actual) (make-assert-msg command actual true))))
 
 
 (defmethod run-command
   :verifyElementNotPresent
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [actual (absent? driver (make-query target))]
     (is (true? actual) (make-assert-msg command actual true))))
 
 
 (defmethod run-command
   [:verifyValue :verifySelectedValue]
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-val (get-element-value driver (make-query target))]
     (is (= actual-val value)
         (make-assert-msg command actual-val value))))
@@ -566,7 +567,7 @@
 
 (defmethod run-command
   :verifyNotSelectedValue
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-val (get-element-value driver (make-query target))]
     (is (not= actual-val value)
         (make-assert-msg command actual-val value))))
@@ -574,7 +575,7 @@
 
 (defmethod run-command
   :verifyText
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-text (get-element-text driver (make-query target))]
     (is (= actual-text value)
         (make-assert-msg command actual-text value))))
@@ -582,7 +583,7 @@
 
 (defmethod run-command
   :verifyNotText
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [actual-text (get-element-text driver (make-query target))]
     (is (not= actual-text value)
         (make-assert-msg command actual-text value))))
@@ -590,7 +591,7 @@
 
 (defmethod run-command
   :verifySelectedLabel
-  [driver {:keys [target value command]} & [{vars :vars}]]
+  [driver {:keys [target value command]} & [{_vars :vars}]]
   (let [q            (make-query target)
         selected-val (get-element-value driver q)
         option-el    (query driver q {:value selected-val})
@@ -601,56 +602,56 @@
 
 (defmethod run-command
   :verifyTitle
-  [driver {:keys [target command]} & [{vars :vars}]]
+  [driver {:keys [target command]} & [{_vars :vars}]]
   (let [title (get-title driver)]
     (is (= title target) (make-assert-msg command title target))))
 
 
 (defmethod run-command
   :waitForElementEditable
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (wait-enabled driver (make-query target)
                 {:timeout (/ (Integer/parseInt value) 1000)}))
 
 
 (defmethod run-command
   :waitForElementNotEditable
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (wait-disabled driver (make-query target)
                  {:timeout (/ (Integer/parseInt value) 1000)}))
 
 
 (defmethod run-command
   :waitForElementPresent
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (wait-exists driver (make-query target)
                {:timeout (/ (Integer/parseInt value) 1000)}))
 
 
 (defmethod run-command
   :waitForElementNotPresent
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (wait-absent driver (make-query target)
                {:timeout (/ (Integer/parseInt value) 1000)}))
 
 
 (defmethod run-command
   :waitForElementVisible
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (wait-visible driver (make-query target)
                 {:timeout (/ (Integer/parseInt value) 1000)}))
 
 
 (defmethod run-command
   :waitForElementNotVisible
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (wait-invisible driver (make-query target)
                   {:timeout (/ (Integer/parseInt value) 1000)}))
 
 
 (defmethod run-command
   :waitForText
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [target value]} & [{_vars :vars}]]
   (let [q (make-query target)]
     (wait-visible driver q)
     (wait-has-text driver q value)))
@@ -659,13 +660,13 @@
 (defmethods run-command
   [:webdriverChooseCancelOnVisibleConfirmation
    :webdriverChooseCancelOnVisiblePrompt]
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [_target _value]} & [{_vars :vars}]]
   (dismiss-alert driver))
 
 
 (defmethods run-command
   [:webdriverChooseOkOnVisibleConfirmation]
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [driver {:keys [_target _value]} & [{_vars :vars}]]
   (accept-alert driver))
 
 
@@ -686,13 +687,13 @@
 
 (defmethod run-command
   :forEach
-  [driver {:keys [target value]} & [{vars :vars}]]
+  [_driver {:keys [target value]} & [{vars :vars}]]
   [(str->var value) (get @vars (str->var target))])
 
 
 (defmethod run-command
   :times
-  [driver {:keys [target]} & [{vars :vars}]]
+  [_driver {:keys [target]} & [{_vars :vars}]]
   (Integer/parseInt target))
 
 
diff --git a/src/etaoin/ide/flow.clj b/src/etaoin/ide/flow.clj
index 88281148..f8901f81 100644
--- a/src/etaoin/ide/flow.clj
+++ b/src/etaoin/ide/flow.clj
@@ -4,7 +4,7 @@
   "
   (:require
    [cheshire.core :as json]
-   [clojure.java.io :as io]
+   [clojure.set :as cset]
    [clojure.spec.alpha :as s]
    [etaoin.api :refer :all]
    [etaoin.ide.api :refer [run-command-with-log str->var]]
@@ -68,7 +68,7 @@
         _             (run-command-with-log driver cmd opt)
         _             (wait (/ windowTimeout 1000))
         final-handles (set (get-window-handles driver))
-        handle        (first (clojure.set/difference final-handles init-handles))]
+        handle        (first (cset/difference final-handles init-handles))]
     (swap! vars assoc (str->var windowHandleName) handle)))
 
 
diff --git a/src/etaoin/query.clj b/src/etaoin/query.clj
index cae58cb7..04fb433e 100644
--- a/src/etaoin/query.clj
+++ b/src/etaoin/query.clj
@@ -19,7 +19,7 @@
   (query locator-css term))
 
 (defmulti to-query
-  (fn [driver q]
+  (fn [_driver q]
     (type q)))
 
 (defmethod to-query clojure.lang.Keyword
@@ -31,14 +31,14 @@
   (query (:locator driver) q))
 
 (defmethod to-query clojure.lang.IPersistentMap
-  [driver {:keys [xpath css] :as q}]
+  [_driver {:keys [xpath css] :as q}]
   (cond
     xpath (query-xpath xpath)
     css   (query-css css)
     :else (query-xpath (xpath/expand q))))
 
 (defmethod to-query :default
-  [driver q]
+  [_driver q]
   (util/error "Wrong query: %s" q))
 
 (defn expand [driver q]
diff --git a/src/etaoin/util.clj b/src/etaoin/util.clj
index f1f5298e..2902dddc 100644
--- a/src/etaoin/util.clj
+++ b/src/etaoin/util.clj
@@ -4,7 +4,6 @@
            java.nio.file.Files
            org.apache.commons.io.FileUtils))
 
-
 (defn map-or-nil?
   [x]
   (or (map? x) (nil? x)))
diff --git a/test/etaoin/api_test.clj b/test/etaoin/api_test.clj
index 24b8bb2e..783045e0 100644
--- a/test/etaoin/api_test.clj
+++ b/test/etaoin/api_test.clj
@@ -691,7 +691,7 @@
         (with-postmortem *driver* {:dir dir-tmp}
           (click *driver* :non-existing-element))
         (is false "should be caught")
-        (catch Exception e
+        (catch Exception _e
           (is true "caught")
           (let [files               (file-seq (io/file dir-tmp))
                 expected-file-count (if (supports-logs? *driver*) 3 2)]
diff --git a/test/etaoin/proc_test.clj b/test/etaoin/proc_test.clj
index fc1dfc8c..e8057166 100644
--- a/test/etaoin/proc_test.clj
+++ b/test/etaoin/proc_test.clj
@@ -40,6 +40,6 @@
     (let [port    9999
           process (proc/run ["chromedriver" (format "--port=%d" port)])
           _       (wait-running {:port port :host "localhost"})
-          driver  (chrome {:host "localhost" :port port :args ["--no-sandbox"]})]
+          _driver  (chrome {:host "localhost" :port port :args ["--no-sandbox"]})]
       (is (= 1 (get-count-chromedriver-instances)))
       (proc/kill process))))