Keyword names cannot be redefined or used as local variable names. All built-in keyword names are prefixed with #%, and a keyword binding is created for all primitive syntactic forms and procedures: for every built-in procedure or syntactic form x, there is a corresponding keyword #%x that accesses the same syntax or value.
There are no other built-in global keywords. Local keywords -- such as public within a class* expression -- are not globally enforced. This means, for example, that the name public may be bound to a value, but public as the first part of a class* sub-clause will not notice such a binding.
A new keyword is declared with (keyword-name s), where s is a symbol. Once a symbol s has been designated as a keyword, it cannot be bound locally or globally. (If s was not already defined, it will be defined as void.) Keywords declared this way are local to the namespace. Test for keywords in the current namespace with (keyword-name? s), where s is a symbol.
Once a name is declared as a keyword, it is syntactically disallowed in any binding position. In contrast, an attempt to change the value of a constant global variable (see section 9.3.2) is detected at run time.
A namespace can be created where the built-in #%-prefixed names are not keywords (see section 9.3), but some built-in syntax and procedures will break in this namespace if certain #%-prefixed names are re-defined or shadowed.