Skip to content

Local HTTP API Daemon (KalcDaemon)

KalcDaemon is an embedded, lightweight HTTP REST microservice running locally on your Mac. Built using Apple's high-performance Network.framework (NWListener), it provides a persistent loopback calculation endpoint for launcher apps like Raycast, Alfred, Hammerspoon, and local developer scripts.

By keeping the engine resident in memory, KalcDaemon answers calculation queries with sub-millisecond latency ($< 0.5\text{ ms}$) without spawning process overhead.


1. Network Configuration & Security

  • Binding Address: Strict loopback 127.0.0.1 (IPv4)
  • Default Port: 15055 (configurable in Preferences)
  • Protocol: HTTP/1.1 REST
  • Security Boundary: The daemon explicitly rejects external interfaces (0.0.0.0 or local Wi-Fi IPs) and cross-origin foreign requests. It is accessible exclusively by processes running on your local machine.

2. API Reference: POST /calculate

Evaluates single expressions or multi-line calculation documents.

Request

  • Method: POST
  • Path: /calculate
  • Headers: Content-Type: application/json

Single Expression Request Payload

json
{
  "input": "$100 + 15% in EUR"
}

Multi-Line Document Request Payload

json
{
  "text": "rate = $125/hr\nhours = 35 hrs\ntotal = rate * hours"
}

Response (200 OK)

Single Expression Response

json
{
  "status": "ok",
  "input": "$100 + 15% in EUR",
  "result": "105.80 EUR",
  "value": 105.80,
  "unit": "EUR",
  "precision": 2,
  "latencyMs": 0.38
}

Multi-Line Document Response

json
{
  "status": "ok",
  "lines": [
    { "line": 1, "result": "$125.00 / hr" },
    { "line": 2, "result": "35 hrs" },
    { "line": 3, "result": "$4,375.00" }
  ],
  "latencyMs": 0.64
}

Error Handling (400 Bad Request)

If an expression contains a syntax error or incompatible dimensional conversion, KalcDaemon returns an HTTP 400 status with a structured diagnostic payload without destabilizing the server:

json
{
  "status": "error",
  "error": {
    "lineIndex": 1,
    "range": { "start": 0, "end": 15 },
    "severity": "error",
    "code": "incompatible_units",
    "message": "Cannot convert mass (kg) to length (meter)"
  }
}

3. Integration Examples

Terminal curl

bash
$ curl -s -X POST http://127.0.0.1:15055/calculate \
  -H "Content-Type: application/json" \
  -d '{"input": "sqrt(144) + 25"}' | jq .result

"37"

Raycast / Alfred Script Filter (Python)

python
#!/usr/bin/env python3
import sys
import json
import urllib.request

query = sys.argv[1] if len(sys.argv) > 1 else "2 + 2"

req = urllib.request.Request(
    "http://127.0.0.1:15055/calculate",
    data=json.dumps({"input": query}).encode("utf-8"),
    headers={"Content-Type": "application/json"}
)

try:
    with urllib.request.urlopen(req) as response:
        data = json.loads(response.read().decode())
        result = data.get("result", "")
        # Output Raycast / Alfred JSON format
        print(json.dumps({
            "items": [{
                "title": result,
                "subtitle": query,
                "arg": result
            }]
        }))
except Exception as e:
    print(json.dumps({"items": [{"title": "Kalc Daemon Offline", "subtitle": str(e)}]}))

4. Enabling the Daemon in Settings

  1. Open Preferences (⌘ ,).
  2. Select the Rates & Daemon tab.
  3. Check "Enable Local Calculation Daemon".
  4. Set your preferred port (default 15055).
  5. Kalc will initialize the background socket on application launch.

Native macOS Computational Notepad • Pure Swift with Strict Concurrency