Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/e4d8c882d/stdl
<6> What Pkl evaluated to discover the error.

When Pkl prints source locations, it also prints clickable links for easy access.
For local files, it generates a link for your development environment (https://pkl-lang.org/main/current/pkl-cli/index.html#settings-file[configurable in `+~/.pkl/settings.pkl+`]).
For local files, it generates a link for your development environment (https://pkl-lang.org/main/current/pkl-cli/index.html#settings-file[configurable in `+~/.config/pkl/settings.pkl+`]).
For packages imported from elsewhere, if available, Pkl produces `https://` links to their repository.

Pkl complains about a _type constraint_.
Expand Down
8 changes: 4 additions & 4 deletions docs/modules/pkl-cli/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1385,14 +1385,14 @@ it works as follows:
The Pkl settings file allows to customize the CLI experience.

A settings file is a Pkl module amending the `pkl.settings` standard library module.
Its default location is `~/.pkl/settings.pkl`.
Its default location is `~/.config/pkl/settings.pkl` on Unix or `%APPDATA%/pkl/settings.pkl` on Windows, falling back to the legacy `~/.pkl/settings.pkl` if that exists.
To use a different settings file, set the `--settings` command line option, for example `--settings mysettings.pkl`.
To enforce default settings, use `--settings pkl:settings`.
The settings file is also honored by (and configurable through) the Gradle plugin and `CliEvaluator` API.

Here is a typical settings file:

.~/.pkl/settings.pkl
.~/.config/pkl/settings.pkl
[source%parsed,{pkl}]
----
amends "pkl:settings" // <1>
Expand All @@ -1414,10 +1414,10 @@ When making TLS requests, Pkl comes with its own set of {uri-certificates}[CA ce
These certificates can be overridden via either of the two options:

- Set them directly via the CLI option `--ca-certificates <path>`.
- Add them to a directory at path `~/.pkl/cacerts/`.
- Add them to a directory at path `~/.config/pkl/cacerts/` on Unix or `%APPDATA%/pkl/cacerts/` on Windows (or the legacy `~/.pkl/cacerts/`).

Both these options will *replace* the default CA certificates bundled with Pkl. +
The CLI option takes precedence over the certificates in `~/.pkl/cacerts/`. +
The CLI option takes precedence over the certificates in the cacerts directory. +
Certificates need to be X.509 certificates in PEM format.

[[http-proxy]]
Expand Down
4 changes: 2 additions & 2 deletions docs/modules/pkl-cli/partials/cli-common-options.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Possible values:
.--cache-dir
[%collapsible]
====
Default: `~/.pkl/cache` +
Default: `~/.cache/pkl` on Unix, `%LOCALAPPDATA%/pkl/cache` on Windows (or the legacy `~/.pkl/cache` if it already exists) +
Example: `/path/to/module/cache/` +
The cache directory for storing packages.
====
Expand Down Expand Up @@ -97,7 +97,7 @@ Any symlinks are resolved before this check is performed.
Default: (none) +
Example: `mySettings.pkl` +
File path of the Pkl settings file to use.
If not set, `~/.pkl/settings.pkl` or defaults specified in the `pkl.settings` standard library module are used.
If not set, `~/.config/pkl/settings.pkl` on Unix or `%APPDATA%/pkl/settings.pkl` on Windows (or the legacy `~/.pkl/settings.pkl`), or defaults specified in the `pkl.settings` standard library module are used.
====

.-t, --timeout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Default: `null` +
Example 1: `moduleCacheDir = layout.buildDirectory.dir("pkl-module-cache")` +
Example 2: `moduleCacheDir.fileValue file("/absolute/path/to/cache")` +
The cache directory for storing packages.
If `null`, defaults to `~/.pkl/cache`.
If `null`, defaults to `~/.cache/pkl` on Unix or `%LOCALAPPDATA%/pkl/cache` on Windows (or the legacy `~/.pkl/cache` if it already exists).
====

.color: Property<Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Example: `settingsModule = layout.projectDirectory.file("mySettings.pkl")` +
The Pkl settings module to use.
This property accepts the same input types as the `sourceModules` property.

If `null`, `~/.pkl/settings.pkl` or defaults specified in the `pkl.settings` standard library module are used.
If `null`, `~/.config/pkl/settings.pkl` on Unix or `%APPDATA%/pkl/settings.pkl` on Windows (or the legacy `~/.pkl/settings.pkl`), or defaults specified in the `pkl.settings` standard library module are used.
====

include::../partials/gradle-common-properties.adoc[]
36 changes: 36 additions & 0 deletions docs/modules/release-notes/pages/0.32.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,41 @@ Ready when you need them.

* New property: link:{uri-stdlib-projectModule}#resolvedEvaluatorSettings[`Project.resolvedEvaluatorSettings`]

=== CLI Changes

==== Default file locations

For new setups, the CLI no longer stores anything under `~/.pkl` (https://github.com/apple/pkl/pull/1674[#1674]). It uses XDG-style locations on Unix and Known Folder locations on Windows:

[cols="1,2,2,2",options="header"]
|===
| Concern | Unix (Linux/macOS) | Windows | Legacy fallback

| Package cache
| `~/.cache/pkl`
| `%LOCALAPPDATA%/pkl/cache`
| `~/.pkl/cache`

| Settings file
| `~/.config/pkl/settings.pkl`
| `%APPDATA%/pkl/settings.pkl`
| `~/.pkl/settings.pkl`

| CA certificates
| `~/.config/pkl/cacerts`
| `%APPDATA%/pkl/cacerts`
| `~/.pkl/cacerts`

| REPL history
| `~/.local/state/pkl/repl-history`
| `%LOCALAPPDATA%/pkl/repl-history`
| `~/.pkl/repl-history`
|===

No Pkl-specific environment variables (such as `XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, `XDG_STATE_HOME`, or `PKL_HOME`) are read. On Windows, the standard `APPDATA` and `LOCALAPPDATA` paths are honoured because that is how Windows itself exposes the Known Folders – they are not Pkl-specific knobs. If `APPDATA` or `LOCALAPPDATA` is unset, the Unix layout is used as a fallback so a misconfigured environment doesn't crash.

Existing setups keep working without migration: each legacy `~/.pkl` location is still used when it already exists. In particular, a pre-existing `~/.pkl/cache` keeps being used as long as the new location does not exist, so packages aren't re-downloaded. If you have manually created an empty `~/.cache/pkl` (or the Windows equivalent), remove it before upgrading, or move your `~/.pkl/cache` contents over.

== Breaking Changes [small]#💔#

Things to watch out for when upgrading.
Expand All @@ -54,6 +89,7 @@ The following APIs have been removed without replacement.
The following APIs have been deprecated for removal.

* `org.pkl.config.java.mapper.NonNull` (https://github.com/apple/pkl/pull/1607[#1607]).
* `org.pkl.core.settings.PklSettings.loadFromPklHomeDir()` – renamed to `PklSettings.loadFromDefaultLocation()`, which now prefers `~/.config/pkl/settings.pkl` over the legacy `~/.pkl/settings.pkl` (https://github.com/apple/pkl/pull/1674[#1674]).

==== Changes

Expand Down
5 changes: 5 additions & 0 deletions docs/modules/release-notes/pages/changelog.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ include::ROOT:partial$component-attributes.adoc[]
[[release-0.32.0]]
== 0.32.0 (UNRELEASED)

=== Changes

* Default the CLI's package cache, settings file, CA certificates directory, and REPL history to XDG-style locations instead of `~/.pkl`: `~/.cache/pkl`, `~/.config/pkl/settings.pkl`, `~/.config/pkl/cacerts`, and `~/.local/state/pkl/repl-history` (pr:https://github.com/apple/pkl/pull/1674[]).
The legacy `~/.pkl` locations are still used when they already exist, so existing setups keep working without migration.

[[release-0.31.1]]
== 0.31.1 (2026-03-26)

Expand Down
2 changes: 1 addition & 1 deletion pkl-cli/src/main/kotlin/org/pkl/cli/repl/Repl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ internal class Repl(workingDir: Path, private val server: ReplServer, private va
}
completer(AggregateCompleter(CommandCompleter, FileCompleter(workingDir)))
option(Option.DISABLE_EVENT_EXPANSION, true)
variable(LineReader.HISTORY_FILE, (IoUtils.getPklHomeDir().resolve("repl-history")))
variable(LineReader.HISTORY_FILE, IoUtils.getDefaultReplHistoryFile())
}
.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ data class CliBaseOptions(

/**
* The Pkl settings file to use. A settings file is a Pkl module amending the `pkl.settings`
* standard library module. If `null`, `~/.pkl/settings.pkl` (if present) or the defaults
* specified in the `pkl:settings` standard library module are used.
* standard library module. If `null`, `~/.config/pkl/settings.pkl` (falling back to the legacy
* `~/.pkl/settings.pkl`), or the defaults specified in the `pkl:settings` standard library
* module, are used.
*/
private val settings: URI? = null,

Expand Down Expand Up @@ -130,8 +131,9 @@ data class CliBaseOptions(
* The given files must contain [X.509](https://en.wikipedia.org/wiki/X.509) certificates in PEM
* format.
*
* If [caCertificates] is the empty list, the certificate files in `~/.pkl/cacerts/` are used. If
* `~/.pkl/cacerts/` does not exist or is empty, Pkl's built-in CA certificates are used.
* If [caCertificates] is the empty list, the certificate files in `~/.config/pkl/cacerts/` (or
* the legacy `~/.pkl/cacerts/`) are used. If that directory does not exist or is empty, Pkl's
* built-in CA certificates are used.
*/
val caCertificates: List<Path> = listOf(),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
if (cliOptions.normalizedSettingsModule != null) {
PklSettings.load(ModuleSource.uri(cliOptions.normalizedSettingsModule))
} else {
PklSettings.loadFromPklHomeDir()
PklSettings.loadFromDefaultLocation()
}
} catch (e: PklException) {
// do not use `errorRenderer` because it depends on `settings`
Expand Down Expand Up @@ -215,7 +215,7 @@ abstract class CliCommand(protected val cliOptions: CliBaseOptions) {
}

private fun HttpClient.Builder.addDefaultCliCertificates() {
val caCertsDir = IoUtils.getPklHomeDir().resolve("cacerts")
val caCertsDir = IoUtils.getDefaultCaCertsDir()
var certsAdded = false
if (Files.isDirectory(caCertsDir)) {
Files.list(caCertsDir)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public synchronized VmTyped getOrLoad(
case "semver":
return SemVerModule.getModule();
case "settings":
// always needed if ~/.pkl/settings.pkl is present
// always needed if ~/.config/pkl/settings.pkl is present
return SettingsModule.getModule();
case "test":
return TestModule.getModule();
Expand Down
25 changes: 20 additions & 5 deletions pkl-core/src/main/java/org/pkl/core/settings/PklSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,31 @@ public record PklSettings(Editor editor, PklEvaluatorSettings.@Nullable Http htt
List.of(Pattern.compile("env:"), Pattern.compile("file:"));

/**
* Loads the user settings file ({@literal ~/.pkl/settings.pkl}). If this file does not exist,
* returns default settings defined by module {@literal pkl.settings}.
* Loads the user settings file. Prefers {@literal ~/.config/pkl/settings.pkl}, falling back to
* the legacy {@literal ~/.pkl/settings.pkl}. If neither file exists, returns default settings
* defined by module {@literal pkl.settings}.
*/
public static PklSettings loadFromDefaultLocation() throws VmEvalException {
return loadFromSettingsFile(IoUtils.getDefaultSettingsFile());
}

/**
* Loads the user settings file.
*
* @deprecated As of 0.32.0, renamed to {@link #loadFromDefaultLocation()}, which now prefers
* {@literal ~/.config/pkl/settings.pkl} over the legacy {@literal ~/.pkl/settings.pkl}.
*/
@Deprecated(since = "0.32.0", forRemoval = true)
public static PklSettings loadFromPklHomeDir() throws VmEvalException {
return loadFromPklHomeDir(IoUtils.getPklHomeDir());
return loadFromDefaultLocation();
}

/** For testing only. */
static PklSettings loadFromPklHomeDir(Path pklHomeDir) throws VmEvalException {
var path = pklHomeDir.resolve("settings.pkl");
static PklSettings loadFromSettingsDir(Path settingsDir) throws VmEvalException {
return loadFromSettingsFile(settingsDir.resolve("settings.pkl"));
}

private static PklSettings loadFromSettingsFile(Path path) throws VmEvalException {
return Files.exists(path)
? load(ModuleSource.path(path))
: new PklSettings(Editor.SYSTEM, null);
Expand Down
Loading