/add-stdlib-package — New Standard Library Package Skill
SkillDev toolsCreates a new stdlib package for the ELPS interpreter. Follows the established pattern from existing packages like libmath.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the /add-stdlib-package — New Standard Library Package Skill skill
About this capability
An embedded lisp interpreter
What this skill tells your AI
The instructions your AI receives, as published by luthersystems/elps in .claude/skills/add-stdlib-package/SKILL.md and read by ahel’s review.
Creates a new stdlib package for the ELPS interpreter. Follows the established pattern from existing packages like libmath.
Trigger
Use when asked to add a new standard library package (e.g., file I/O, crypto, HTTP client, etc.).
Workflow
1. Plan the Package
Before writing code, define:
- Package name (lowercase, e.g.,
"file","crypto") - Functions to export with their signatures
- Any global constants to expose
- Package-level documentation
2. Create the Package Directory
Create lisp/lisplib/lib<name>/lib<name>.go:
package lib<name>
import (
"github.com/luthersystems/elps/lisp"
"github.com/luthersystems/elps/lisp/lisplib/libutil"
)
const DefaultPackageName = "<name>"
func LoadPackage(env *lisp.LEnv) *lisp.LVal {
name := lisp.Symbol(DefaultPackageName)
e := env.DefinePackage(name)
if !e.IsNil() {
return e
}
e = env.InPackage(name)
if !e.IsNil() {
return e
}
env.SetPackageDoc(`One-line description of the package.
Detailed description of what the package provides.`)
// Optional: global constants
// env.PutGlobal(lisp.Symbol("my-const"), lisp.Int(42))
// env.SetSymbolDoc("my-const", "Description of the constant.")
// env.Runtime.Package.Exports("my-const")
for _, fn := range builtins {
env.AddBuiltins(true, fn)
}
return lisp.Nil()
}
var builtins = []*libutil.Builtin{
libutil.FunctionDoc("my-func",
lisp.Formals("arg1", "arg2"),
builtinMyFunc,
`Description of what my-func does.
Returns the result of ...`),
}
func builtinMyFunc(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal {
arg1 := args.Cells[0]
arg2 := args.Cells[1]
// Implementation
_ = arg1
_ = arg2
return lisp.Nil()
}
Key Rules
- Always use
libutil.FunctionDoc()— neverlibutil.Function(). All functions must have docstrings. CI enforces this viaelps doc -m. - Use
lisp.Formals()for argument declarations. Available modifiers:- Required:
lisp.Formals("arg1", "arg2") - Optional:
lisp.Formals("required", lisp.FmtString("&optional"), "opt-arg") - Variadic:
lisp.Formals("required", lisp.FmtString("&rest"), "rest-args") - Keyword:
lisp.Formals("required", lisp.FmtString("&key"), "key-arg")
- Required:
- Error propagation: Return
env.Errorf("message: %v", detail)for errors — never use Go'serrorinterface - Export symbols: Call
env.Runtime.Package.Exports("func1", "func2", ...)for all public symbols
3. Register in LoadLibrary()
Edit lisp/lisplib/lisplib.go:
- Add import:
"github.com/luthersystems/elps/lisp/lisplib/lib<name>" - Add to the package loader list in
LoadLibrary():
e = lib<name>.LoadPackage(env)
if !e.IsNil() {
return e
}
4. Write Tests
Create a lisp test file at lisp/lisplib/lib<name>/lib<name>_test.go:
package lib<name>_test
import (
"testing"
"github.com/luthersystems/elps/elpstest"
)
func TestLib<Name>(t *testing.T) {
runner := &elpstest.Runner{}
runner.RunTestFile(t, "testdata/<name>_test.lisp")
}
Create the lisp test at lisp/lisplib/lib<name>/testdata/<name>_test.lisp:
(use-package 'testing)
(use-package '<name>)
(test "my-func basic usage"
(assert-equal (my-func "arg1" "arg2") expected-result))
(test "my-func edge case"
(assert-nil (my-func "" "")))
(test "my-func error handling"
(assert-error (my-func))) ; missing args
5. Verify
go test ./lisp/lisplib/lib<name>/... # Package tests pass
make test # Full suite passes
./elps doc -m # No missing docstrings
./elps doc <name> # Package docs render correctly
Checklist
- Package directory created at
lisp/lisplib/lib<name>/ -
LoadPackage()follows DefinePackage → InPackage → SetPackageDoc → AddBuiltins pattern - All functions use
libutil.FunctionDoc()(notFunction()) - All public symbols exported via
Exports() - Package registered in
lisplib.goLoadLibrary() - Tests written with
elpstest.Runner+.lisptest file -
elps doc -mpasses (no missing docstrings) -
make testpasses -
docs/lang.mdupdated if package is user-facing
Signals
- GitHub stars
- 36
- Forks
- 9
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
add-stdlib-package- Source
- github.com/luthersystems/elps