NanoMDM is a minimalist Apple MDM server heavily inspired by MicroMDM

Related tags

Messaging nanomdm



NanoMDM is a minimalist Apple MDM server heavily inspired by MicroMDM.

Getting started & Documentation

  • Quickstart
    A quick guide to get NanoMDM up and running using ngrok.

  • Operations Guide
    A brief overview of the various command-line switches and HTTP endpoints and APIs available to NanoMDM.


  • Horizontal scaling: zero/minimal local state. Persistence in storage layers. MySQL backend provided in the box.
  • Multiple APNs topics: potentially multi-tenant.
  • Multi-command targeting: send the same command (or pushes) to multiple enrollments without individually queuing commands.
  • Migration endpoint: allow migrating MDM enrollments between storage backends or (supported) MDM servers
  • Otherwise we share many features between MicroMDM and NanoMDM, such as:
    • A MicroMDM-emulating HTTP webhook/callback.
    • Enrollment-certificate authorization
    • API-driven interaction (queuing of commands, APNs pushes, etc.)

$x not included

NanoMDM is but one component for a functioning MDM server. At a minimum you need a SCEP server and TLS termination, for example. If you've used MicroMDM before you might be interested to know what NanoMDM does not include, by way of comparison.

  • SCEP.
    • Spin up your own scep server. Or bring your own.
  • TLS.
    • You'll need to provide your own reverse proxy/load balancer that terminates TLS.
  • ADE (DEP) API access.
    • While ADE/DEP enrollments are supported there is no DEP API access.
  • Enrollment (Profiles).
    • You'll need to create and serve your own enrollment profiles to devices.
  • Blueprints.
    • No 'automatic' command sending upon enrollment. Entirely driven my webhook or other integrations.
  • JSON command API.
    • Commands are submitted in raw Plist form only. See the tool that helps generate raw commands
    • The micro2nano project provides an API translation server between MicroMDM's JSON command API and NanoMDM's raw Plist API.
  • VPP.
  • Enrollment (device) APIs.
    • No ability, yet, to inspect enrollment details or state.
    • This is partly mitigated by the fact that both the file and mysql storage backends are "easy" to inspect and query.

Architecture Overview

NanoMDM, at its core, is a thin composable layer between HTTP handlers and a set of storage abstractions.

  • The "front-end" is a set of standard Golang HTTP handlers that handle MDM and API requests. The core MDM handlers adapt the requests to the service layer. These handlers exist in the http package.
  • The service layer is a composable interface for processing and handling MDM requests. The main NanoMDM service dispatches to the storage layer. These services exist under the service package.
  • The storage layer is a set of interfaces and implementations that store & retrieve MDM enrollment and command data. These exist under the storage package.

You can read more about the architecture in the blog post Introducing NanoMDM.

  • Update pkcs7 library as a fix for ber2der error

    Update pkcs7 library as a fix for ber2der error

    What's up?

    Been getting the occasional error for certain unlucky enrollments with certain Mdm-Signature.

    err=ber2der: BER tag length is more than available data

    When this happens, PUT /mdm returns a 400 response.

    The fix?

    Not sure, but after upgrading the PKCS7 library, replaying the same request works. Maybe it's this?

    Regardless, reproduced that error happens in pkcs7.Parse() in main and upgrading the library solved it.

    opened by daemonsy 6
  • PostgreSQL storage

    PostgreSQL storage

    PostgreSQL storage added. Based on mysql storage package. Much of the code is duplicated, but as Go-authors said, sometimes a little more copy-paste is better than a little more dependencies. - is used as db driver.

    opened by sheshenia 5
  • Accomodate large command results

    Accomodate large command results


    When handling the command result response for InstalledApplicationList, nanomdm issues the following plea:

    level=info handler=checkin-command msg=command report results err=storing command report: Error 1406: Data too long for column 'result' at row 1

    The InstalledApplicationList response for my current device - with only base Apple apps - is 117,465 characters of base64-endcoded text. TEXT support 65,525 characters; MEDIUMTEXT, 16,777,215 (this corresponds to ~16.78 mb: "L + 3 bytes, where L < 2^24" -

    This works with current nanomdm release (in as much as I migrated with schema.00005.sql and everything continued to work/InstalledApplicationList started working). MySQL docs do not have any warnings regarding migrating between text types that I found.

    opened by w0de 4
  • Context logging

    Context logging

    Adds a simple ctxlog package which permits associating multiple CtxKVFuncs with a context. Then, when it's time to log, these are ran using the request context to pull out logging key-value pairs and create a new logger.

    The end result is something like this for a typical NanoMDM push request.


    2022/03/16 14:03:09 level=info handler=log addr=::1 method=GET path=/v1/push/D7083AF3-DCCB-5661-A678-BCE8F4D9A2C8 agent=curl/7.64.1
    2022/03/16 14:03:09 level=info service=push msg=retrieved push cert
    2022/03/16 14:03:09 level=debug handler=push msg=push count=1 errs=0
    2022/03/16 14:03:09 level=info handler=log addr= method=PUT path=/mdm agent=MDM-OSX/1.0 mdmclient/1455 real_ip=2301:602:8a02:9b0f:422:25a8:481b:bd42
    2022/03/16 14:03:09 level=info service=nanomdm status=Idle id=D7083AF3-DCCB-5661-A678-BCE8F4D9A2C8 type=Device
    2022/03/16 14:03:09 level=debug service=nanomdm msg=no command retrieved id=D7083AF3-DCCB-5661-A678-BCE8F4D9A2C8


    2022/03/16 14:02:44 level=info handler=log trace_id=84172eff419691ca addr=::1 method=GET path=/v1/push/D7083AF3-DCCB-5661-A678-BCE8F4D9A2C8 agent=curl/7.64.1
    2022/03/16 14:02:44 level=info service=push trace_id=84172eff419691ca msg=retrieved push cert
    2022/03/16 14:02:44 level=debug handler=push trace_id=84172eff419691ca msg=push count=1 errs=0
    2022/03/16 14:02:44 level=info handler=log trace_id=c35015253617eb34 addr= method=PUT path=/mdm agent=MDM-OSX/1.0 mdmclient/1455 real_ip=2301:602:8a02:9b0f:422:25a8:481b:bd42
    2022/03/16 14:02:45 level=info service=nanomdm trace_id=c35015253617eb34 id=D7083AF3-DCCB-5661-A678-BCE8F4D9A2C8 type=Device status=Idle
    2022/03/16 14:02:45 level=debug service=nanomdm trace_id=c35015253617eb34 id=D7083AF3-DCCB-5661-A678-BCE8F4D9A2C8 type=Device msg=no command retrieved

    Note the trace_id value which tracks each log's request from its origin. Note also that id and type in the service=nanomdm layer is also a context value rather than explicitly logged now.

    opened by jessepeterson 3
  • Cutting a release?

    Cutting a release?

    Hi, there's been a lot of improvements since the last release in June 2021.

    As much as we can, we'd like to rely on official releases. Was wondering:

    1. Can we get a release cut? 😸
    2. Maybe it's good to discuss what do releases mean for NanoMDM and if it makes sense to have a certain type of cadence of cutting releases?

    e.g. I can imagine if there was a time or feature based release schedule that followed some level of semantic versioning in spirit, we would try our best frequently update to the nearest minor version and run some form of QA process before a major / breaking version change.

    opened by daemonsy 3
  • stdlogfmt (default logger) changes

    stdlogfmt (default logger) changes

    Optionize stdlogfmt package/New, add filename and line logging, use timestamp format.

    Output looks like:

    ts=2022-07-21T08:41:40-07:00 level=info msg=storage setup storage=pgsql caller=cli.go:60
    ts=2022-07-21T08:41:40-07:00 level=info msg=storage setup storage=mysql caller=cli.go:60
    ts=2022-07-21T08:41:40-07:00 level=info msg=storage setup storage=file caller=cli.go:60
    ts=2022-07-21T08:41:40-07:00 level=info msg=storage setup storage=multi-storage count=3 caller=cli.go:93
    ts=2022-07-21T08:41:40-07:00 level=debug msg=declarative management setup url= caller=main.go:102
    ts=2022-07-21T08:41:40-07:00 level=info service=certauth msg=allowing retroactive associations caller=certauth.go:95
    ts=2022-07-21T08:41:40-07:00 level=info msg=starting server listen=:9000 caller=main.go:208
    opened by jessepeterson 2
  • HTTP codes (well, 500) for API responses

    HTTP codes (well, 500) for API responses

    In lieu of parsing responses for push_error etc, I would prefer to rely on the HTTP code to judge success. This is a bit awkward when enqueuing commands for multiple IDs, as not all may have failed. I argue to that one failure should return 500 for the entire operation - if the client sent multiple IDs, it is the client's responsibility to read the json response and discover the precise error.

    I didn't get fancy with specific error codes, willing to though.

    I'm a go noob, so I apologize for any glaring mistake, bad pattern, etc. Please let me know!

    opened by w0de 2
  • Attempt to make Quickstart easier to follow

    Attempt to make Quickstart easier to follow

    Found the two ngrok urls to be hard to grok :), have to keep going back to see if that was the SCEP one or nanomdm one. So I thought this adding the prefix makes it easier to follow.

    Also, ngrok supports multiple tunnels on one process on the free plan, but it's easy to overlook. Added a line on configuring multiple tunnels.

    opened by daemonsy 2
  • Mode to recapture client certificate

    Mode to recapture client certificate

    By default NanoMDM will save the client identity certificate for a device enrollment during the Authenticate check-in message (for both the file and mysql backends). However if enrollments happened in such a way that client certificates were missed (say, via migration) then we should support a way to "recapture" client certificates in storage by saving the identity certificate. It would be wasteful to do this on every request so perhaps it would be only be turned on with a flag.

    opened by jessepeterson 2
  • add github action for mysql backend

    add github action for mysql backend

    Currently the MySQL backend is not tested, as it requires MySQL server to run. I have added an integration test to the GitHub workflows which starts MySQL server in a container, which allows the backend to be tested. This ignores several "issues" that exist with the tests, such as the fact that the test is non-idempotent, and fails to run twice.

    opened by 4e554c4c 1
  • Error trying to enroll a iOS device

    Error trying to enroll a iOS device

    Hi! I'm new to nanoMDM, I was trying to set it up for testing and followed the steps on When the server was up and running i opened safari on my iphone and went to '{my_local_ip}/mdm' to enroll the device, and then the server responded with a bad request and the logs look like this

    2022/09/07 08:49:02 level=info handler=log addr= method=GET path=/mdm agent=Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6.1 Mobile/15E148 Safari/604.1
    2022/09/07 08:49:02 level=debug handler=cert-extract msg=empty Mdm-Signature header
    2022/09/07 08:49:02 level=info handler=cert-verify msg=error verifying MDM certificate err=missing MDM certificate

    Am I doing something wrong?

    The command I'm running is ./nanomdm-darwin-amd64 -ca ca.pem -api nanomdm -debug

    opened by sbenedetti21 1
  • Simplify MySQL delete statement

    Simplify MySQL delete statement

    depends on #58

    Currently the delete statement in the MySQL backend is a complicated multiple-table statement, which is a proprietary MySQL extension to the SQL language. Furthermore, we have observed issues with this delete statement deadlocking with itself (when two statements run for the same command row) due to lock-upgrading issues that occur between the query and delete steps.

    I have changed this DELETE statement to be an ordinary delete, with two simple select statements (with no joins). These select statements may not have to be annotated FOR UPDATE, but I wanted to err on the side of avoiding deadlocks.


    • Observe that MySQL integration tests pass TODO:
    • Make sure that deadlocks no longer occur.
    opened by 4e554c4c 0
  • remove view from mysql backend

    remove view from mysql backend

    The view_queue is not materialized, and thus functions as syntactic sugar for a complex query. Furthermore, our infrastructure works poorly with views. Therefore, this usage adds a significant maintainership burden for little gain.

    This commit removes the view from NanoMDM code paths, but it still exists in the schema. This is purely for convenience and interactive users.

    Furthermore, I added an index used by the queue query, which should have existed for the view. This should improve performance.


    • Tested migration - see the schema migration script
    • Tested base functionality
    • Passes new integration test

    depends on #58 fixes #53 for mysql backend

    opened by 4e554c4c 0
  • MongoDB Storage Capabilities

    MongoDB Storage Capabilities

    Enabling mongoDB storage support and integrating it into the cli startup capabilities

    Note: The feature TODOs are not mission critical to the daily operation

    Happy to support as necessary going forward 😀

    opened by Yohan460 2
  • SQL backends: remove VIEWs from code

    SQL backends: remove VIEWs from code

    As discussed in #3 would like to move away from direct VIEW usage for the command queue in the storage backend. We can keep it in the schema.sql files as a helper for folks, but would like to move to direct table query in the code.

    The MySQL backend:

    The Postgres backend:

    opened by jessepeterson 0
  • Publish Docker image

    Publish Docker image

    Since there is already a Dockerfile in the repo and its actively using GitHub Actions, it would be great to publish a container to Docker Hub or the Github Container registry for easy access. Personally it would make creating a helm chart much easier if I don't have to build this locally.

    opened by samcat116 0
  • v0.4.0(Aug 18, 2022)

    Thank you to our contributors for this release: @sheshenia and @4e554c4c.

    New Features/Capabilities

    • PostgreSQL storage backend! #51
    • Logging updates:
      • Source code filename and line logging now included and the log timestamp is part of the logfmt: 5db6e3403a2f4fc6fedf8a50c8ba62431a56fb05
      • Plist parsing errors are now specially handled to log the problematic plist: #54

    Bug fixes

    • Guard potential nil enrollment metadata: 6772a991942d50544b1b22ecd7738324a8b11d60


    • Documentation fixes/improvements: ea9ff80192ce4dcab3ac2592f9bc07c779123274, 560ced9ec8cc839c65703f10e53db39b72ebf9fa
    • Better handle DDM URL concatenation: 3368d221abc1bc212927943231266ec5cf125a7b
    • Trace ID callback signature now passes in the request: 92c977e42859ba56e73d1fc2377732a9ab6e5e01, 773ad3b47884cb56ec0062d22c7f7cc07760c39e
    Source code(tar.gz)
    Source code(zip) MB) MB) MB)
  • v0.3.0(Jun 14, 2022)

    NOTE: This release has MySQL storage backend schema changes. Please apply the schema.00008.sql file if you have an existing MySQL backend installation.

    Thank you to our contributors for this release: @daemonsy, @leojh, @zwass, @chilcote, @discentem, @steviec.

    New Features/Capabilities

    • Declarative Device Management (DDM) "proxy." Use the -dm switch to extract and forward the Declarative Management protocol Endpoints to a specialized HTTP server. Check out last year's blog post about DDM for more info: #24
    • Context (trace) logging: allows consistent logging of an MDM request through NanoMDM's components: #39, b1d46ad07d5acaafee5c70c7105825874263f613
    • Added ScheduleOSUpdate, ScheduleOSUpdateScan, AccountConfiguration, Settings, DeviceLock, EraseDevice commands: #37, #38, 6c4be9a9eddd51a24e098ffeaa29e69d7dbd2b91, 6457764c51ca2cae64bb5bc16090b56cdf4bdfa4, #46, 46dc2e1e48e34f12f4e0d16cce70cff32b44e14d, 2fb9eee48167546312217907dc282062393b0f70
    • MySQL backend now keeps track of the "last seen" timestamp for an enrollment: #42
    • MySQL backend can now delete commands that have been responded to. Use the -storage-options delete=1 switch: #48.

    Bug fixes

    • Fix for ber2der error by updating pkcs7 library: #32
    • Fix certificate signature verifier (not used by default) PEM loading: 0f72a64
    • Update for Python compatibility: fbe081c
    • Do not allow encrypted private keys to be uploaded to APNs push cert endpoint /v1/pushcert: 79dd081715814f37ead322cb5a2089078975e67a, 17969225c3b10e08621e987551c92089afe2bb0b
    • Fix variable shadow bug in /v1/pushcert endpoint: 3faeabe49a0f75e2325c1118e4c3d671c9bfadad


    • Added tests for the certauth service middle package: 60d4fc8
    • Documentation fixes/improvements: #34, #35, #36, #45, #47, 68cbc1cfb9127414b37c3aa7f3a632686d526538, 5a0a160c8d89259bdd5feca346c0a9c4a93f95cc
    • Updated plist library: e4210b8
    • Various refactoring: 6463c280d61549623253e79391d245c445852c95, fb69bf2d981e55e75c50d0de6cbd847b4c8dc731, c1f85305fe864a2c258d97c7576116ff5615cadf, adc65efe5f6dccd3a16f131f0029b8945ec04e02, 371382135f5e188c48bdf9941cc5aaa97cd9905c, a7654ff43eaf2f7dcd2c21a36f43f88c6cb177b2, 105d0df74daece8310cdaa49f25496416442410c, ca03a5052853f85d7f2da0dc63dfaeeea9bb977f, 28f0e62ae5f1c16f86d88f9dd38d5b838301fbf1, ca2dcc89a05b6d0aa89952573cd289cbe712ea20, 2e67ef65e3efc94ba8fbe18f162b58e1cea8d230
    • Logging improvements to API endpoints: 2a46dfd0e55f1895b774f4a6b5d80c92660d0ece, 014aec3326c319faa67521edefad4bfb4f328df2, 9448647ab9d038955f70e7509643804c67124070
    • Use x_forwarded_for logger key instead of real_ip: 80a07d3dd4bc8edf13bda7cf3ae20a534c1838a8
    • Added tests for MySQL storage backend: cbda10fa327dee659b940bbee24c7888208707a8, 56c9b7e2178772c551e59ea716f6ce6c8130f10f
    • Push and enqueue API endpoints now respond with 200, 207, or 500 HTTP status: 1ce70774d14647898a7325b8482797fb49883e0a
    • Changed release zip files to include both binaries and support files: 0d25a8dab4ea40f891cb7e5a3eba15e576f16a2f
    • Move to go 1.17.x in actions: 35c54a62fed2b4b51484c9883b0568e066c625c2
    Source code(tar.gz)
    Source code(zip) MB) MB) MB)
  • v0.2.0(Sep 2, 2021)

    NOTE: This release has MySQL storage backend schema changes. Please apply the schema.00001.sql through schema.00007.sql files if you have a previous installation.

    Thank you to our contributors for this release: @gmarnin, @daemonsy, @w0de, @leojh

    New Features/Capabilities

    • Added enrollment migration nano2nano tools: ability to migrate between NanoMDM storage backends: f99f83a
    • Added new signature (only) certificate verifier (not enabled by default): fb68ac0
    • Bootstrap Token support: #15
    • Support basic UserAuthenticate enrollment: #8, 4a54502, 4d5561f
    • TokenUpdate "tally": a simple counter for TokenUpdates per enrollment. Allows seeing which TokenUpdates are the first (and thus enroll-time) and is propagated to the webhook: #16
    • Added Storage backend tests: af61878
    • Support HTTP parameter pass-through to webhook: #17
    • Better tracking of NotNow responses in MySQL backend: #13

    Bug fixes

    • Fixes to MySQL schema #22, #23, #25
    • Use larger column type for commands and responses in MySQL storage backend: #26, 419b2ef
    • Log server shutdown (previously silently ignoring): 5fe88c6
    • Fix push expiration handling: f46dad5


    • Added Dockerfile (and Makefile support for Docker) 86b6188, 795cfc5
    • -mdm switch is now called -disable-mdm 795cfc5
    • Documentation fixes/improvements #19, #21, 8b4c39f, 7b0214d, 5d3d46b, 9516060, #28, #29
    • Created GitHib actions: #9, 78a8930
    • Added the NanoMDM Operations Guide: 71c41cf
    • Various refactoring: 032aae1, 3c9a161, c03b3b8, d16aa2a, 84cf636, a841235, a9d0462, 3907f14, 970c5b3, 513d43e, 1406f5c, cb51bf0, 65fb96a
    • More efficient multi-command targeting in MySQL storage backend: 52dd9ae
    • Added OpenAPI docs: c4b8ada, 66ccbce
    • Update to newer PKCS#7 dependency: 9b0010e
    Source code(tar.gz)
    Source code(zip) MB) MB) MB) MB) MB) MB)
macOS MDM and related services
⚡ HTTP/2 Apple Push Notification Service (APNs) push provider for Go — Send push notifications to iOS, tvOS, Safari and OSX apps, using the APNs HTTP/2 protocol.

APNS/2 APNS/2 is a go package designed for simple, flexible and fast Apple Push Notifications on iOS, OSX and Safari using the new HTTP/2 Push provide

Adam Jones 2.7k Jan 1, 2023
🔊Minimalist message bus implementation for internal communication

?? Bus Bus is a minimalist event/message bus implementation for internal communication. It is heavily inspired from my event_bus package for Elixir la

Mustafa Turan 282 Jan 3, 2023
:notes: Minimalist websocket framework for Go

melody ?? Minimalist websocket framework for Go. Melody is websocket framework based on that abstracts away the tedious p

Ola 2.7k Dec 30, 2022
Memlog - A Kafka log structure inspired in-memory and append-only data structure

Benchmark with log size 1000 go test -bench=. -cpu 1,2,4,8,16 -benchmem goos: darwin goarch: amd64 pkg: cpu: Intel(R) Core(T

Michael Gasch 72 Dec 25, 2022
Scalable real-time messaging server in language-agnostic way

Centrifugo is a scalable real-time messaging server in language-agnostic way. Centrifugo works in conjunction with application backend written in any

Centrifugal 6.7k Jan 2, 2023
golang long polling library. Makes web pub-sub easy via HTTP long-poll server :smiley: :coffee: :computer:

golongpoll Golang long polling library. Makes web pub-sub easy via an HTTP long-poll server. New in v1.1 Deprecated CreateManager and CreateCustomMana

J Cuga 620 Jan 6, 2023
Golang push server cluster

gopush-cluster gopush-cluster is a go push server cluster. Features light weight high performance pure golang implementation message expired offline m

Terry.Mao 2.1k Dec 28, 2022
A push notification server written in Go (Golang).

gorush A push notification micro server using Gin framework written in Go (Golang) and see the demo app. Contents gorush Contents Support Platform Fea

Bo-Yi Wu 6.7k Jan 8, 2023
websocket based messaging server written in golang

Guble Messaging Server Guble is a simple user-facing messaging and data replication server written in Go. Overview Guble is in an early state (release

Sebastian Mancke 154 Oct 19, 2022
Server-sent live updates: protocol and reference implementation

Protocol and Reference Implementation Mercure is a protocol allowing to push data updates to web browsers and other HTTP clients in a convenient, fast

Kévin Dunglas 3.2k Jan 1, 2023
Uniqush is a free and open source software system which provides a unified push service for server side notification to apps on mobile devices.

Homepage Download Blog/News @uniqush Introduction Uniqush (\ˈyü-nə-ku̇sh\ "uni" pronounced as in "unified", and "qush" pronounced as in "cushion") is

Uniqush 1.5k Jan 9, 2023
⚡️ A lightweight service that will build and store your go projects binaries, Integrated with Github, Gitlab, Bitbucket and Bitbucket Server.

Rabbit A lightweight service that will build and store your go projects binaries. Rabbit is a lightweight service that will build and store your go pr

Ahmed 196 Nov 19, 2022
High-Performance server for NATS, the cloud native messaging system.

NATS is a simple, secure and performant communications system for digital systems, services and devices. NATS is part of the Cloud Native Computing Fo

NATS - The Cloud Native Messaging System 12k Jan 2, 2023
Notifie Server is a learning list notifier

Notifie Server Notifie Server is a learning list notifier. E.g; If you want to l

Mehmet KAYKISIZ 0 Dec 24, 2021
Converter EPG XMLTV to OTT-play (by Alex) server side JSON

EPG converter for OTT-play FOSS Описание Инструмент создания телепрограммы для OTT-Play FOSS, использует 1 поток, и буферное чтение из файла, что позв

prog4food 7 Jan 6, 2023
A brief demo of real-time plotting with Plotly, Go, and server-sent events

Golang SSE Demo A brief demo of real-time plotting with Plotly, Go, and server-side events. Overview I first learned about Server-Sent Events from @mr

Damon P. Cortesi 14 Nov 28, 2022
mdmb is a tool for simulating Apple devices interacting with Apple MDM servers.

mdmb mdmb — short for MDM Benchmark, à la ab — is a tool for simulating Apple devices interacting with Apple MDM servers. mdmb creates sets of fake Ap

Jesse Peterson 42 Dec 1, 2022
Sekura is an Encryption tool that's heavily inspired by the Rubberhose file system.

It allows for multiple, independent file systems on a single disk whose existence can only be verified if you posses the correct password.

null 52 Oct 16, 2022
A standalone nREPL/prepl client written in Go and heavily inspired by Grenchman

Trenchman A standalone nREPL/prepl client written in Go, heavily inspired by Grenchman Trenchman is a standalone nREPL/prepl client, which means that

Shogo Ohta 58 Dec 11, 2022
xlsxlang is a tiny toy script programming language. xlsxlang is heavily inspired by Lisp

xlsxlang Table of Contents 1. Usage 1.1. Examples 2. Installation 3. Supported functions 4. LICENSE xlsxlang is a tiny toy script programming language

jiro 5 Feb 11, 2022