Note that splines::ns has an argument intercept
args(ns)
function (x, df = NULL, knots = NULL, intercept = FALSE, Boundary.knots = range(x))
which by default is FALSE. The reason for this is that often you will include multiple terms (say, splines of different variables) and if each of them included the intercept in its basis you would have a problem ... (this is by the way the exact same reason that factors usually are encoded omitting one level).
But, if for some reason you want the intercept included you just say splines:ns( ... , intercept=TRUE). But when using the usual modeling functions in R and its packages, this should not be necessary.
If the question is if regressions using spline basis functions do not need an intercept, the answer is no. Splines are no different in principle than other basis functions, for instance polynomials or factors expanded in dummys (or so-called one-hot encoding). You used the tag nonlinear-regression, but using splines do not make for a nonlinear regression. So the question about intercept is answered by When is it ok to remove the intercept in a linear regression model?
lm(y~ns(x))returns an intercept term. Do you mean the matrix returned byns(x)does not return an intercept? – Demetri Pananos Aug 26 '22 at 20:02