# Ann: SWI-Prolog 10.1.11

**URL:** <https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-11/9722>\
**Category:** Releases\
**Created:** [July 5, 2026, 8:46am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-11/9722 "2026-07-05T08:46:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 5, 2026, 8:46am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-11/9722/1 "2026-07-05T08:46:46Z")

</div>

# SWI-Prolog Changelog since version 10.1.10

This release provides several improvements required by the SWI-Prolog  
MCP server (pack `mcp`): support for HTTP SSE (Server Sent Events) and  
additional APIs for various normally interactive tools (help,  
profiler, coverage analysis, linter (check/0)) to allows LLMs to use  
the `stdin` MCP server to query running Prolog processes.

The Windows version should now be able to run from a UNC path.

A major cleanup of open issues (dropped from 134 to less than 60) on  
GitHub. Most were closed as already fixed, irrelevant, stale, etc.  
A handful has been fixed.

```
Enjoy --- Jan

```

**Highlights**

- **FIXED** : `PL_initialise()` no longer changes the process  
`LC_NUMERIC` locale (#1093), so embedders keep the C locale for  
`atof()` and `printf("%f")`.

- **FIXED** : clause indexing bug where a deep list index preempted  
a deterministic primary argument, leaving a spurious choice point  
(#1386).

- **FIXED** : `wrap_predicate/4` on meta-predicates now carries the  
module/determinism qualification, so tracing `foldl/4` and friends  
resolves higher-order goals in the correct module (#1245).

- **FIXED** : Windows UNC support for relative file names and shared  
object loading; `absolute_file_name/3`, `access_file/2`,  
`open_shared_object/2` and `use_foreign_library/1` now work when  
the working directory is a UNC path.

- **FIXED** : `nb_setval/2` did not duplicate a plain attributed  
variable (#1359).

- **FIXED** : `is_stream/1` crash on a standard stream alias whose  
slot is `NULL`.

- **FIXED** : `PL_get_stream()` verifies the returned stream has the  
requested input/output mode (#1233) and rejects invalid modes.

- **FIXED** : `PL_get_text()` with only `CVT_STRING` now raises  
`type_error(string, X)`.

- **FIXED** : `number_string/2` type error (#695).

- **FIXED** (clib): `process_create/3` restores the signal mask in  
the child before `exec`, so the new process’s `ITIMER_PROF` timer  
actually delivers ticks and `profile/1` no longer divides by zero.

- **FIXED** (pack): dependency resolution now considers already  
installed packs when a pack’s `requires` is only discovered after  
download (e.g. installed from a URL).

- **FIXED** (xpce terminal): DEC application cursor mode sent digit  
`0` instead of capital `O`, so every arrow key in `vim` insert  
mode dropped back to normal mode and ran the wrong command.

- **ADDED** (http): `library(http/sse)` server-sent events helper,  
honouring the `http:cors` setting.

- **ADDED** : `prolog_edit:locations/2` and `help_apropos/4`.

- **DOC** : clarified `absolute_file_name/3` default behaviour when  
the spec resolves to a directory (#782), and `--home` / the `home`  
Prolog flag in both the manual and the `swipl(1)` man page (#793).

- **BUILD** : detect Intel-Mac Homebrew at `/usr/local` for dependency  
paths, fixing a broken Ninja graph on Intel Macs. Cross-build  
Prolog steps use a _native friend_ with correct `library` and  
`foreign` search paths (#1503).

**Full ChangeLog**

- FIXED: #726 Less confusing message for unbound type in a  
type\_error(Expected,Found) error.

- BUILD: Setup library and foreign search paths in the build tree For  
cross-compilation using the _native friend_ to run the Prolog steps  
of build, we need to setup `library` to point at the current (cross)  
target and `foreign` to point at the directories holding the foreign  
modules of the _native friend_.

- BUILD: #1503 Simplify the way we setup paths for running in the  
build directory. The now aproach should notably fix getting paths  
setup correctly for running the Prolog build steps using a _native  
friend_, providing the ability to do cross building where we cannot  
run the cross-compiled executable and therefore use a _native friend_  
to perform these steps.

- FIXED: #1093 PL\_initialise() no longer mutates the process LC\_NUMERIC  
locale initLocale() used to call setlocale(LC\_NUMERIC, “”) to bootstrap  
the default PL\_locale from localeconv(). As a side effect it changed  
the embedder’s process-wide decimal separator, breaking atof()  
and printf(“%f”) in host code that expects the C locale. Read the  
environment’s numeric conventions via newlocale()/uselocale() (POSIX  
2008) instead, with a save/setlocale/restore fallback under L\_LOCALE  
for platforms without them. locale\_create/3 uses the same helper.

- FIXED: #1386 candidate deep list index preempting deterministic primary  
For a small static predicate whose primary argument discriminates  
but whose non-primary compound argument shares a top-level functor  
across clauses, set\_candidate\_indexes() emits a list hash index on  
the compound argument. At call time existing\_hash() matched that  
index (top-level functor bound), the deep drill entered a sub-list  
whose inner arguments were variables, and the recursion fell back  
to next\_clause\_unindexed(), leaving a spurious choice point on the  
non-matching clause.

- FIXED: #1245 wrap\_predicate/4 supervisor to carry meta/det qualification  
prefix. $c\_wrap\_predicate/5 installed a bare S\_CALLWRAPPER supervisor,  
bypassing the S\_MQUAL/S\_LMQUAL prefix that chainPredicateSupervisor()  
normally prepends for meta-predicates. Tracing a meta-predicate such  
as foldl/4 therefore lost the caller-module context on higher-order  
arguments, so the wrapped goal looked up prolog\_trace:my\_plus/3 rather  
than user:my\_plus/3.

- FIXED: PL\_get\_stream() invalid mode detection.

- FIXED: #1233 PL\_get\_stream() to verify returned stream has correct  
(input/output) mode.

- FIXED: #1359 nb\_setval/2 did not duplicate a plain attvar.

- DOC: #782 absolute\_file\_name/3 default behavior when spec resolves to a  
directory The docs claimed the predicate “only returns non-directories”  
unless file\_type(directory) is given or access is none. Since the  
default access is none, that “unless” clause covers the default –  
but readers naturally miss it. Also, the file\_type section stated  
the opposite of what the code does regarding when file\_type(regular)  
is the default.

- DOC: #793 clarify --home and the `home` Prolog flag Explain what  
the home directory is used for (boot.prc, library/) and distinguish  
the two forms of --home: with =DIR sets the home directory (and  
adds SWI\_HOME\_DIR to the environment); without argument reports  
the located home directory. Cross-reference the --home option,  
the `home` Prolog flag, and the findhome section from each other.  
Update both the swipl(1) man page and the user manual.

- FIXED: Windows: UNC support for relative file names and shared object  
loading. When the process working directory is a UNC path (e.g. set  
via a Windows shortcut’s “Start in” field), resolving a relative  
file name via absolute\_file\_name/3, access\_file/2 and friends failed,  
and open\_shared\_object/2, use\_foreign\_library/1 could not load DLLs  
identified by a UNC path.

- FIXED: #695 number\_string/2: correct type error.

- FIXED: PL\_get\_text() with only `CVT_STRING` to return  
type\_error(string, X)

- FIXED: pack installer: consider installed packs when resolving  
dependencies When installing a pack whose requires only becomes known  
after download (e.g. installed from a URL), download\_plan/3 recursed  
into pack\_resolve/5 with only the just-downloaded plan as Existing,  
losing the list of locally installed packs. Dependencies already  
satisfied by an installed pack were then presented as fresh installs  
and, if the user declined, the whole install failed.

- FIXED: require\_prolog\_version/2: Git version comparison.

- BUILD: detect Intel-Mac Homebrew at /usr/local for dependency paths On  
Intel Macs, Homebrew installs to /usr/local rather than /opt/homebrew.  
The auto-detection in Darwin.cmake only checked /opt/homebrew,  
so Intel Mac users fell through to MACOSX\_DEPENDENCIES\_FROM=None,  
leaving LibArchive (and OpenSSL, BDB) unfound by CMake. This caused  
a broken man/archive file dependency in the Ninja build graph and a  
ninja failure.

- ADDED: prolog\_edit:locations/2, provide data access to location  
discovery.

- ADDED: help\_apropos/4, providing access to the apropos database.

- FIXED: is\_stream/1: crash when querying a standard stream alias whose  
slot is NULL. In a thread created without PL\_THREAD\_CUR\_STREAMS the  
protocol slot is never copied, and freeStream() also resets it to  
NULL when the protocol stream is closed. get\_stream\_handle() then  
dereferenced LD-\>IO.streams[n] without a NULL check. The downstream  
code already treats NULL as “no such stream”, so just guard the  
SIO\_CMAGIC test.

## Package clib

- FIXED: process\_create/3: restore signal mask in child before  
exec SIGPROF is blocked around fork() to keep profiler ticks from  
interrupting it, but the previous mask was only restored in the parent.  
The child therefore inherited SIGPROF blocked across execve(), so the  
new process’s ITIMER\_PROF profiler ran but no ticks were ever delivered.  
profile/1 then divided by zero in prolog\_profile:show\_profile\_/1.

## Package cpp

- TEST: Fixed PL\_get\_stream() calls asking for the wrong in/out stream.

## Package http

- ADDED: library(http/sse): honour http:cors setting in sse\_open/0,1  
Browser-based EventSource clients on a different origin need an  
Access-Control-Allow-Origin response header. sse\_open/0,1 now calls  
cors\_enable/0 from library(http/http\_cors), so the existing http:cors  
setting controls whether the header is emitted. Non-browser clients  
and same-origin pages are unaffected (default setting is ).

- ADDED: library(http/sse): high-level helper for Server-Sent Events  
sse\_open/0,1 emits the response headers and switches the CGI output  
stream into event\_stream transfer mode. sse\_send/1,2 writes events  
given as a dict (with optional event, data, id, retry and comment  
keys), an atom/string, or a list of events, splitting multi-line data  
on ‘\n’ into separate “data:” lines. sse\_comment/1,2 emits a heartbeat.

- FIXED: cgi\_stream: stop emitting a second header block when an  
event\_stream handler returns For event\_stream responses the headers are  
sent by cgi\_hook(send\_header) when the transfer encoding is selected,  
and each subsequent write is flushed straight through to the client.  
cgi\_close() was still calling the send\_header hook again, producing  
a spurious extra HTTP header block at the end of the body. Skip the  
call for event\_stream; the chunked path is already special-cased.

## Package xpce

- FIXED: terminal: send capital ‘O’, not digit ‘0’, in DECCKM arrow  
keys In DEC application cursor mode (DECCKM, \e[?1h), arrow / Home /  
End should send SS3 sequences \eOA \eOB \eOC \eOD \eOH \eOF, but we  
sent the digit zero instead of capital O. Vim enables DECCKM via  
terminfo’s smkx, so every arrow press in insert mode bounced vim out  
of insert mode and ran “0” / “A” as normal-mode commands.

- ENHANCED: terminal: DCS swallow, CSI intermediate bytes and OSC 10/11  
Vi/vim probes the terminal with sequences our parser did not recognise,  
which surfaced as `ESCP`, `ESC\`, `Unknown ANSI CSI: \e[0%` and `Unknown OSC command: 11` messages, and left vim guessing the colour scheme.  
Handle them:

- FIXED: Prevent help\_message window from being destroyed.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [July 10, 2026, 2:57am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-11/9722/2 "2026-07-10T02:57:42Z")

</div>

Today’s update to the `swipl-devel` repository fails during the QLF compile phase on my macOS system (both M4 and Intel, running macOS Tahoe 26.3).

The build fails with the following error: `ERROR: -g qlf_make: No permission to redefine module 'pce_edit' (Already loaded from .../home/xpce/prolog/lib/swi_edit.pl)`

This occurs even after a full `git clean -fdx` and a fresh `cmake` configuration. It appears to be a regression in the current bootstrap sequence.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 10, 2026, 7:27am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-11/9722/3 "2026-07-10T07:27:48Z")

</div>

> [@kuniaki.mukai](#):
>
> `ERROR: -g qlf_make: No permission to redefine module 'pce_edit' (Already loaded from .../home/xpce/prolog/lib/swi_edit.pl)`

Thanks for reporting. Pushed a fix. I thought a module name was misspelled … Anyway, `pce_edit.pl` was obsolete stuff and is now removed. Using an incremental build you have to remove the `pce_edit.pl` link in home before rebuilding. Either find the file or simply do `rm -r home/xpce` to remove all xpce files. It will rebuild them 🙂
