Skip to content
Draft
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
2 changes: 1 addition & 1 deletion UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ the context the patches were being applied in.

there are a few places to update next.

1. `appVersion` in default.nix and `hash` in `codexZip`.
1. `version` and `hash` in `nix/codex-zip/default.nix`.
2. `APP_VERSION` in ./scripts/prepare

then temporarily comment out the patch lines in ./scripts/prepare_asar and run
Expand Down
17 changes: 8 additions & 9 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,13 @@ flake-utils.lib.eachSystem systems (
system:
let
pkgs = import nixpkgs { inherit system; };
appVersion = "26.513.20950";
codexZip = pkgs.fetchurl {
url = "https://persistent.oaistatic.com/codex-app-prod/Codex-darwin-arm64-${appVersion}.zip";
hash = "sha256-zSlRaoUJc4eRFbe08qS/oyqaBbfW2Epjj3hlbEmA6Cw=";
};
codex = self.packages.${system}.codex;
in
{
devShells.default = pkgs.mkShell {
HOSTED_CODEX_APP_ZIP = codexZip;
HOSTED_CODEX_APP_ZIP = self.packages.${system}.codexZip;

packages = [
codex
self.packages.${system}.codex
pkgs.nodejs
pkgs.unzip
pkgs.patch
Expand Down Expand Up @@ -89,7 +83,7 @@ flake-utils.lib.eachSystem systems (
in
{
default = pkgs.buildNpmPackage {
HOSTED_CODEX_APP_ZIP = codexZip;
HOSTED_CODEX_APP_ZIP = self.packages.${system}.codexZip;

pname = "codex-web";
version = "1.0.0";
Expand All @@ -111,6 +105,11 @@ flake-utils.lib.eachSystem systems (
patchShebangs scripts
'';

postBuild = ''
substituteInPlace src/server/main.js \
--replace-fail '@resourcesPath@' '${self.packages.${system}.codex_resources}'
'';

preInstall = ''
# npm pack always runs the package prepare lifecycle. Nix already ran
# the explicit build script above, so remove prepare in the sandbox.
Expand Down
4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
inputs@{ flake-utils, ... }:
flake-utils.lib.meld inputs [
./nix/codex
./nix/codex-zip
./nix/codex-primary-runtime
./nix/codex-resources
./src/chrome-extension-host
./default.nix
./nix/fmt.nix
./scripts/fetch_updates
Expand Down
50 changes: 50 additions & 0 deletions nix/codex-primary-runtime/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
flake-utils,
nixpkgs,
...
}:
flake-utils.lib.eachSystem [ "x86_64-linux" ] (
system:
let
pkgs = import nixpkgs { inherit system; };
version = "26.426.12240";
in
{
packages.codex-primary-runtime = pkgs.stdenvNoCC.mkDerivation {
pname = "codex-primary-runtime";
inherit version;

# this one random version of codex-primary-runtime has a linux build with
# node_repl mcp. considered using the macOS binary and emulating with
# darling but ran into numerous issues with darling's isolation
# requirements
src = pkgs.fetchurl {
url = "https://persistent.oaistatic.com/codex-primary-runtime/${version}/codex-primary-runtime-linux-x64-${version}.tar.xz";
hash = "sha256-21Yk6276NrZuxvbdBIjO+5ZuSWNoYqq2IJpDNsHKkMQ=";
};

sourceRoot = "codex-primary-runtime";

nativeBuildInputs = [ pkgs.autoPatchelfHook ];

buildInputs = [
pkgs.glibc
pkgs.libxcrypt-legacy
pkgs.stdenv.cc.cc.lib
pkgs.zlib
];

dontConfigure = true;
dontBuild = true;

installPhase = ''
runHook preInstall

mkdir -p "$out"
cp -R . "$out"/

runHook postInstall
'';
};
}
)
183 changes: 183 additions & 0 deletions nix/codex-resources/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
{
self,
flake-utils,
nixpkgs,
...
}:
let
systems = [
"aarch64-darwin"
"x86_64-darwin"
"aarch64-linux"
"x86_64-linux"
];
in
flake-utils.lib.eachSystem systems (
system:
let
pkgs = import nixpkgs { inherit system; };
linuxOpenChromeWindow =
let
chromeExtensionId = "hehggadaopoacecdllhhajmbjkdcmajg";
chromeNativeHostName = "com.openai.codexextension";
chromeExtensionUpdateUrl = "https://clients2.google.com/service/update2/crx";
chromeNativeHostManifest = pkgs.writeText "codex-chrome-native-host-manifest.json" (
builtins.toJSON {
name = chromeNativeHostName;
description = "Codex chrome native messaging host";
type = "stdio";
path = "${self.packages.${system}.codex_chrome_extension_host}/bin/codex-chrome-extension-host";
allowed_origins = [ "chrome-extension://${chromeExtensionId}/" ];
}
);
linuxProfileRootTemplate = pkgs.linkFarm "codex-brave-profile-root-template" [
{
name = "xdg-config/BraveSoftware/Brave-Browser/NativeMessagingHosts/${chromeNativeHostName}.json";
path = chromeNativeHostManifest;
}
{
name = "user-data/External Extensions/${chromeExtensionId}.json";
path = pkgs.writeText "codex-chrome-extension.json" (
builtins.toJSON {
external_update_url = chromeExtensionUpdateUrl;
}
);
}
{
name = "user-data/policies/managed/codex.json";
path = pkgs.writeText "codex-chrome-policy.json" (
builtins.toJSON {
ExtensionInstallForcelist = [ "${chromeExtensionId};${chromeExtensionUpdateUrl}" ];
AudioCaptureAllowed = false;
VideoCaptureAllowed = false;
DefaultClipboardSetting = 2;
DefaultWebUsbGuardSetting = 2;
DefaultSerialGuardSetting = 2;
}
);
}
{
name = "user-data/Codex/Preferences";
path = pkgs.writeText "codex-chrome-preferences.json" (
builtins.toJSON {
profile = {
name = "Codex";
};
extensions = {
settings = {
"${chromeExtensionId}" = {
external_update_url = chromeExtensionUpdateUrl;
};
};
};
}
);
}
];
in
pkgs.writeShellScriptBin "codex-open-chrome-window" ''
set -euo pipefail

if [[ "$#" -gt 0 ]]; then
echo "Usage: scripts/open-chrome-window" >&2
exit 2
fi

profile_root="$(mktemp -d -t codex-brave-profile.XXXXXX)"

home_dir="$profile_root/home"
xdg_config_home="$profile_root/xdg-config"
xdg_cache_home="$profile_root/xdg-cache"
user_data_dir="$profile_root/user-data"
profile_name="Codex"

cp -RL --no-preserve=mode,ownership,timestamps ${linuxProfileRootTemplate}/. "$profile_root"

mkdir -p \
"$home_dir" \
"$xdg_cache_home" \
"$xdg_config_home" \
"$user_data_dir"

chmod -R u+w "$profile_root"

log_file="$profile_root/brave.log"
HOME="$home_dir" XDG_CONFIG_HOME="$xdg_config_home" XDG_CACHE_HOME="$xdg_cache_home" \
${pkgs.xvfb-run}/bin/xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" \
${pkgs.brave}/bin/brave \
--user-data-dir="$user_data_dir" \
--profile-directory="$profile_name" \
--no-first-run \
--no-default-browser-check \
--disable-dev-shm-usage \
--force-device-scale-factor=1 \
--start-maximized \
--window-position=0,0 \
--window-size=1920,1080 \
--new-window about:blank
'';
in
{
packages.codex_resources = pkgs.stdenvNoCC.mkDerivation {
pname = "codex-resources";
version = self.packages.${system}.codexZip.version;

src = self.packages.${system}.codexZip;

nativeBuildInputs = [
pkgs.patch
pkgs.unzip
];

dontConfigure = true;
dontBuild = true;

unpackPhase = ''
runHook preUnpack

unzip -q "$src"

runHook postUnpack
'';

installPhase = ''
runHook preInstall

mkdir -p "$out"
cp -R Codex.app/Contents/Resources/plugins "$out/plugins"

chromeManifestScript="$out/plugins/openai-bundled/plugins/chrome/scripts/installManifest.mjs"
chromeExtensionHost="${
self.packages.${system}.codex_chrome_extension_host
}/bin/codex-chrome-extension-host"
substituteInPlace "$chromeManifestScript" \
--replace-fail 'let t=a(o);' "let t=\"$chromeExtensionHost\";" \
--replace-fail 'path:a(o)' "path:\"$chromeExtensionHost\""
''
+ pkgs.lib.optionalString (system == "x86_64-linux") ''
chromePluginRoot="$out/plugins/openai-bundled/plugins/chrome"
patch --batch --forward --strip 1 --directory "$chromePluginRoot" < ${./patches/chrome-linux-brave-skill.patch}
substituteInPlace "$chromePluginRoot/skills/chrome/SKILL.md" \
--replace-fail '@openChromeWindow@' '${linuxOpenChromeWindow}/bin/codex-open-chrome-window'
rm "$chromePluginRoot/scripts/open-chrome-window.js"
''
+ pkgs.lib.optionalString (system == "aarch64-darwin") ''
install -m755 Codex.app/Contents/Resources/node "$out/node"
install -m755 Codex.app/Contents/Resources/node_repl "$out/node_repl"
''
+ pkgs.lib.optionalString (system == "x86_64-linux") ''
install -m755 ${pkgs.nodejs}/bin/node "$out/node"
install -m755 ${
self.packages.${system}.codex-primary-runtime
}/dependencies/bin/node_repl "$out/node_repl"
''
+ pkgs.lib.optionalString (system != "aarch64-darwin" && system != "x86_64-linux") ''
echo "codex resources are only packaged for aarch64-darwin and x86_64-linux" >&2
exit 1
''
+ ''
runHook postInstall
'';
};
}
)
Loading