Only allowing two-argument functions doesn’t cut it, and you need some means of returning multiple values as well. You also need a means of abstraction (e.g., Clojure fns) and combinators for application, abstraction, and stack manipulation. A full implementation of an interpreter for a concatenative DSL would be rather longer than this—though still probably in the realm of 100 lines.
Factjor supports quotations, currying, composition, and has most of the primary combinators: dip, keep, cleave, spread, application, etc. It's only about 100 lines.
It's difficult to have simpler semantics than SK calculus. Perhaps a more appropriate modifier in this instance would be "more convenient".
With non-variadic arithmetic functions:
(defn add [x]
(cons (+ (first x) (second x)) (rest (rest x))))
(defn dup [x]
(cons (first x) x))
(defn zap [x]
(defn swap [x]
(cons (second x) (cons (first x) (rest (rest x)))))
(defn ap [x]
(apply (first x) (rest x)))
It uses prefix notation: instead of a data stack, each function takes the remainder of the program for rewriting.