Skip to content

Commit e04c0a9

Browse files
feat(wrapperModules.ghostty): init
Writes settings to a Nix store config file and loads it via --config-default-files=false --config-file=<path>, isolating the wrapper from the host config in both installed and ephemeral use. The host config path varies by platform: ~/.config/ghostty/config on Linux, and ~/Library/Application Support/com.mitchellh.ghostty/config on macOS. Ghostty +actions and --help use minimal option parsers that reject unknown flags and exit silently, so argv0type bypasses flag injection for these. +show-config and +validate-config are subject to the same parser limitation and will show the host config rather than the generated one. On macOS, ghostty-bin is used by default (the pre-built binary distribution recommended for nix-darwin by the Ghostty installation docs).
1 parent c2b76d3 commit e04c0a9

3 files changed

Lines changed: 146 additions & 0 deletions

File tree

maintainers/default.nix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,9 @@
111111
github = "allen-liaoo";
112112
githubId = 16383622;
113113
};
114+
trustworthyadult = {
115+
name = "Michael Ross";
116+
github = "TrustworthyAdult";
117+
githubId = 104172948;
118+
};
114119
}

wrapperModules/g/ghostty/check.nix

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
pkgs,
3+
self,
4+
tlib,
5+
...
6+
}:
7+
let
8+
inherit (tlib) isFile fileContains test;
9+
wrapper = self.wrappers.ghostty.wrap {
10+
inherit pkgs;
11+
settings = {
12+
font-size = 14;
13+
theme = "catppuccin-mocha";
14+
window-decoration = false;
15+
};
16+
};
17+
configFile = "${wrapper}/ghostty-config";
18+
in
19+
test { wrapper = "ghostty"; } {
20+
"ghostty wrapper binary should exist" = [ (isFile "${wrapper}/bin/ghostty") ];
21+
22+
"ghostty wrapper should disable default config and point to generated file" = [
23+
(fileContains "${wrapper}/bin/ghostty" "--config-default-files=false")
24+
(fileContains "${wrapper}/bin/ghostty" "--config-file=")
25+
];
26+
27+
"ghostty wrapper should bypass config flags for +actions and --help" = [
28+
(fileContains "${wrapper}/bin/ghostty" "_ghostty_arg")
29+
(fileContains "${wrapper}/bin/ghostty" "--help")
30+
];
31+
32+
"ghostty config file should exist" = [ (isFile configFile) ];
33+
34+
"ghostty settings should appear in generated config" = [
35+
(fileContains configFile "font-size = 14")
36+
(fileContains configFile "theme = catppuccin-mocha")
37+
(fileContains configFile "window-decoration = false")
38+
];
39+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
config,
3+
wlib,
4+
lib,
5+
pkgs,
6+
...
7+
}:
8+
let
9+
toGhosttyConf = lib.generators.toKeyValue {
10+
mkKeyValue = lib.generators.mkKeyValueDefault {
11+
mkValueString = v: if builtins.isBool v then lib.boolToString v else toString v;
12+
} " = ";
13+
};
14+
in
15+
{
16+
imports = [ wlib.modules.default ];
17+
18+
options.settings = lib.mkOption {
19+
type = lib.types.attrsOf (
20+
lib.types.oneOf [
21+
lib.types.bool
22+
lib.types.float
23+
lib.types.int
24+
lib.types.str
25+
]
26+
);
27+
default = { };
28+
example = lib.literalExpression ''
29+
{
30+
font-size = 14;
31+
theme = "catppuccin-mocha";
32+
window-decoration = false;
33+
}
34+
'';
35+
description = ''
36+
Ghostty configuration written to a generated config file. The wrapper
37+
passes {option}`--config-default-files=false` and
38+
{option}`--config-file=<generated>`, so the host config is never loaded
39+
-- including when the wrapper is used ephemerally on a machine that has
40+
its own Ghostty config. The host config path varies by platform:
41+
{file}`~/.config/ghostty/config` on Linux, and
42+
{file}`~/Library/Application Support/com.mitchellh.ghostty/config` on
43+
macOS.
44+
See <https://ghostty.org/docs/config/reference> for all available options.
45+
46+
Note: if you pass an additional {option}`--config-file` flag at runtime,
47+
Ghostty will merge it on top of the generated config (later files take
48+
precedence for conflicting keys).
49+
50+
Note: {command}`ghostty +show-config` and {command}`ghostty
51+
+validate-config` bypass the generated config entirely (their option
52+
parsers reject {option}`--config-file`), so they will show the host
53+
config if one exists -- this affects both installed and ephemeral use.
54+
55+
On macOS, `ghostty-bin` is used by default, which is the pre-built
56+
binary distribution [recommended for nix-darwin](https://ghostty.org/docs/install/binary)
57+
by the Ghostty installation docs.
58+
'';
59+
};
60+
61+
config = {
62+
package = lib.mkDefault (if pkgs.stdenv.isDarwin then pkgs.ghostty-bin else pkgs.ghostty);
63+
constructFiles.ghosttyConfig = {
64+
content = toGhosttyConf config.settings;
65+
relPath = "${config.binName}-config";
66+
};
67+
addFlag = [
68+
"--config-default-files=false"
69+
"--config-file=${config.constructFiles.ghosttyConfig.path}"
70+
];
71+
# Ghostty has no environment variable for specifying a config file, so CLI
72+
# flags are the only option: --config-default-files=false prevents loading
73+
# the host's ~/.config/ghostty/config (including on machines where one
74+
# exists), and --config-file points at the generated one.
75+
#
76+
# However, Ghostty +actions and --help have their own minimal Options
77+
# struct with no _diagnostics field. Any flag unrecognised by the action
78+
# parser causes error.InvalidField and a silent exit with no output.
79+
# argv0type detects these and execs Ghostty directly without injecting any
80+
# flags.
81+
#
82+
# Consequence: +show-config and +validate-config will show the host's
83+
# ~/.config/ghostty/config if present, not the generated config, because
84+
# their option parsers also reject --config-file. This applies equally to
85+
# installed and ephemeral use.
86+
argv0type =
87+
let
88+
binPath = lib.escapeShellArg config.wrapperPaths.input;
89+
in
90+
cmd: ''
91+
for _ghostty_arg in "$@"; do
92+
case "$_ghostty_arg" in
93+
+*|--help) exec -a "$0" ${binPath} "$@";;
94+
esac
95+
done
96+
exec -a "$0" ${cmd}
97+
'';
98+
meta.description = "Ghostty terminal emulator";
99+
meta.maintainers = [ wlib.maintainers.trustworthyadult ];
100+
meta.platforms = lib.platforms.linux ++ lib.platforms.darwin;
101+
};
102+
}

0 commit comments

Comments
 (0)