Skip to content

AI-native LMS · open source

Courses built from your docs. Every claim cited.

AI drafts lessons from your material. You review every change before publishing.

Example · policy lifecyclev1 v2
01 / 07

The CEO uploads policy and style guide

Start with the files your team already uses.

  • Upload PDF, Markdown, DOCX or plain text.
  • Add images and a style guide for the course design.
  • Keep the policy as the source for lessons.

CEO: Upload policy PDF, Brand style guide. Extract PDF text → Cited source context → LLM reads the policy. § 4 · Customer data: Delete customer exports after 30 days.

Illustrative policy lifecycle. Authors approve source updates before publication.

live demos

Six academies, one platform

Each demo is a separate tenant with its own theme, course and data, running on the same ulams install. Open it as a learner or step into its admin.

  • Gravity Lab

    A real-data solar system you learn inside.

    Style
    3D simulation
    Lessons
    12
    Topics
    54
    Price
    Free
  • Poland, Measured

    35 years of Poland in cited public data, in English and Polish.

    Style
    Map and charts
    Lessons
    12
    Topics
    48
    Price
    Free
  • The Scottish Book

    Ulam, the Lwów School and the Scottish Book, with five live interactives.

    Style
    Mathematics and history
    Lessons
    11
    Topics
    47
    Price
    Free
  • Coffee Academy

    A slow, magazine-style course from seed to cup: film, podcast, interactive diagrams, a quiz and a final project.

    Style
    Editorial · self-paced
    Lessons
    6
    Topics
    19
  • On-Call

    Incident command for platform engineers: a 4-week cohort with an outage simulator, a live drill and a reviewed postmortem.

    Style
    Cohort · dark pro tool
    Lessons
    5
    Topics
    16
  • Night Sky Explorers

    Seven short missions to the stars with Orbi the robot guide, badges and a printable diploma.

    Style
    Gamified · kids 10–14
    Lessons
    7
    Topics
    16
    Price
    Free

Demos reset every hour. No sign-up: you are logged in automatically.

Stanisław Ulam
Stanisław Ulam · illustrated portrait

The thinking behind the name

Knowledge grows when we build it together.

In the cafés of Lwów, Stanisław Ulam and fellow mathematicians discussed problems and recorded them in a shared notebook: the Scottish Book. Questions, solutions and new ideas grew through collaboration.

Ulam later translated the collection so it could reach more people, inviting readers to contribute corrections and further developments.

The Scottish Book · Ulam’s preface, University of St Andrews(opens in a new tab)

That spirit inspires ULAMS: turn your organisation’s documents into shared learning, work with people and agents, and keep improving the knowledge together. Open source, free to use and open to contribution.

Build with us on GitHub(opens in a new tab)

run it from anywhere

Manage your academy from the admin panel, Claude, Claude Code or your terminal

ULAMS is a standard LMS. The admin panel is there for courses, people, enrolments and reports. You can also use Claude Code, Claude, Codex, OpenCode, Gemini CLI or another MCP-compatible agent, the ULAMS CLI or the REST API. The studio is a visual workspace for your team.

Six ways to run ulams: the admin panel, Claude Code, Claude with the ulams MCP server, the ulams command line, the REST API and SDK, and the studio.

  • Section: Courses
  • Section: People
  • Section: Enrolments
  • Section: Reports
  • Course: On-Call. Published | 86
  • Course: Gravity Lab. Published | 42
  • Course: The Coffee Atlas. Draft | 0

The admin panel is the usual way in: courses, people, enrolments and reports.

  • You ask Claude Code: Build a 3-lesson course on incident response from ./runbook.md and publish it
  • Claude Code: I'll start a builder run on runbook.md and bring you the outline before anything goes live.
  • Tool call: Bash ulams builder start --from runbook.md --defaults --json
  • Running: Reading runbook.md, drafting the outline
  • Output: {"status":"outline_review","session":"01J9Z3K8M2"}
  • Claude Code: Outline ready: 1. Detect and declare, 2. Triage and mitigate, 3. Write the postmortem. Every lesson cites runbook.md. Approve and publish?
  • You ask Claude Code: Yes, approve and publish.
  • Tool call: Bash ulams builder outline approve 01J9Z3K8M2 --json
  • Output: {"status":"apply_review","session":"01J9Z3K8M2"}
  • Tool call: Bash ulams builder apply 01J9Z3K8M2 --json
  • Output: {"status":"applied","courseId":17}
  • Tool call: Bash ulams courses publish 17 --json
  • Output: {"id":17,"status":"published"}
  • Claude Code: Done. Incident response is live as course 17: 3 lessons, every claim cited to runbook.md.

Describe the course in plain language. Claude Code runs the ulams CLI, shows you the outline, and publishes only after you approve.

  • You: Which courses are still drafts? Publish the coffee one.
  • Tool call: courses_list status: draft returned 2 courses
  • Claude: Two drafts: Learn coffee the slow way and Incident response. I'll publish Learn coffee the slow way. Go ahead?
  • You: Yes, publish it.
  • Tool call: courses_publish id: 3 returned published
  • Claude: Done. Learn coffee the slow way is published. Incident response is still a draft.

Ask Claude, or any MCP-compatible agent, about your academy. It uses the ulams MCP server and asks before it sends anything.

  • Command: ulams login --url http://coffee.localhost --demo admin
  • Output: Signed in as [email protected]
  • Command: ulams courses list --json | jq -r '.data[] | "\(.id) \(.title)"'
  • Output: 3 Learn coffee the slow way
  • Command: ulams get Course "Learn coffee the slow way" --output yaml > course.yaml
  • Comment: # edit the grind-size lesson in course.yaml
  • Command: ulams apply --file course.yaml --dry-run
  • Output: Course Learn coffee the slow way updated (dry run, nothing written)
  • Command: ulams apply --file course.yaml
  • Running: Applying 1 change
  • Output: Course Learn coffee the slow way updated

Course as code: export a course to YAML, edit it in your editor, review the plan, apply it back.

  • Command: curl -s -X POST https://oncall.example.com/api/admin/topics \
  • Command, continued: -H "Authorization: Bearer $ULAMS_TOKEN" -H "Content-Type: application/json" \
  • Command, continued: -d '{"title":"Reading a page","lesson_id":12,"topicable_type":"EscolaLms\\TopicTypes\\Models\\TopicContent\\RichText","value":"What the alert means."}'
  • Output: {"success":true,"data":{"id":88,"title":"Reading a page","lesson_id":12}}
  • Command: node -e "import('@ulams/sdk').then(async ({createClient}) => { const ulams = createClient({baseUrl: 'https://oncall.example.com'}); console.log((await ulams.courses.list()).data.length) })"
  • Output: 1

Everything the studio does goes through the HTTP API. Plain curl works; so does @ulams/sdk for reading.

  • You: Add a quiz after lesson 2 from the runbook.
  • Claude: I drafted 5 questions. Each one cites a section of runbook.md, and nothing changes until you approve.
  • Proposal: Proposed change: new quiz after Triage and mitigate, 5 questions, all cited Approve | Reject

The studio is the visual course builder: every AI change is a diff you approve.

One platform: the admin your team expects, and every interface they already work in.

Claude and Claude Code are products of Anthropic. ulams is independent and not affiliated with or endorsed by Anthropic.

standards

Delivered anywhere

Standards over lock-in: bring existing packages, track learning anywhere, integrate through the API.

  • H5Pinteractive content
  • SCORM 1.2 / 2004
  • cmi5
  • xAPIbuilt-in LRS
  • LTI 1.3Platform + Tool
  • OpenAPIREST API
  • WebhooksComing

self-host

Your servers. Your data.

Run the complete stack with one command on your laptop, Docker server or Kubernetes cluster. Use your own VPS, AWS, Google Cloud or Azure. Your deployment, your data.

Helm chart coming soon.

            
            $ npm install -g https://github.com/ulams-dev/ulams/releases/download/cli-v0.2.0/ulams-0.2.0.tgz$ ulams stack up✓ academy, Studio, API, admin, H5P and storage$ ulams stack up --mode production \  --domain learn.example.org$ ulams stack up --target kubernetes
          

CONTACT

Talk with the ULAMS team

Questions about self-hosting, integrations or contributing? Send us a note.

Email

Your message goes to the private ULAMS contact inbox. Do not include passwords or sensitive personal information.

FAQ

Questions before you start

What is ULAMS?

ULAMS is an open-source LMS for organisations, universities and technical teams. Its headless API supports branded learning sites, course authoring and integrations.

Is ULAMS free to self-host?

Yes. ULAMS is MIT licensed. You provide hosting; paid AI provider calls, if enabled, are billed by your chosen provider. H5P runs as a separate service with its own GPL licence.

Can I try the whole stack locally?

Yes. Install the CLI and run ulams stack up with Docker Compose available. The development trial uses deterministic AI responses without paid model calls. Node.js 22.12 or newer is required.

Where can I deploy it?

Use Docker Compose on your own server or native Kubernetes manifests on an existing cluster. A VPS or virtual machine on AWS, Google Cloud or Azure can host the stack. Production needs DNS, HTTPS and persistent storage.

Can agents operate ULAMS?

The CLI and MCP interface let compatible agents work with the platform. You can use Claude Code, Codex, OpenCode or Gemini CLI, or integrate directly through the REST API.

Does AI publish a course automatically?

No. AI prepares a draft with source citations. The author reviews the outline and content, then approves publication. Production starts with AI disabled until you configure a provider.

Can each academy use its own brand and domain?

Yes. Each tenant has its own learning site, theme and isolated database. The initial academy is created by the stack launcher; additional tenants use the platform tenant workflow.

How do I stop it without losing courses?

Run ulams stack down. Data and credentials remain available when you run stack up again in the same installation directory. Only stack down --purge --yes deliberately removes persistent data.

More questions on the FAQ page