@lindengjian/codex-beacon 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Codex Beacon npm installer
2
+
3
+ This package installs the native Codex Beacon app into `~/Applications` on an
4
+ Apple Silicon Mac running macOS 15 or later.
5
+
6
+ ```sh
7
+ npx @lindengjian/codex-beacon install
8
+ ```
9
+
10
+ Or install the small command-line launcher globally:
11
+
12
+ ```sh
13
+ npm install -g @lindengjian/codex-beacon
14
+ codex-beacon install
15
+ ```
16
+
17
+ Commands:
18
+
19
+ ```sh
20
+ codex-beacon open
21
+ codex-beacon doctor
22
+ codex-beacon uninstall
23
+ ```
24
+
25
+ `uninstall` removes only `~/Applications/CodexBeacon.app`. Before removal it
26
+ asks Beacon to unregister its login item and roll back the shared App Server
27
+ compatibility adapter that Beacon itself created.
28
+
29
+ The app remains ad-hoc signed and is not notarized. npm does not bypass macOS
30
+ security checks; follow the macOS prompt only when you trust the release.
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>en</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>CodexBeacon</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>com.lindengjian.CodexBeacon</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleIconFile</key>
14
+ <string>CodexBeacon.icns</string>
15
+ <key>CFBundleName</key>
16
+ <string>Codex Beacon</string>
17
+ <key>CFBundlePackageType</key>
18
+ <string>APPL</string>
19
+ <key>CFBundleShortVersionString</key>
20
+ <string>1.0.5</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>1.0.5</string>
23
+ <key>LSArchitecturePriority</key>
24
+ <array>
25
+ <string>arm64</string>
26
+ </array>
27
+ <key>LSMinimumSystemVersion</key>
28
+ <string>15.0</string>
29
+ <key>LSUIElement</key>
30
+ <true/>
31
+ <key>NSHighResolutionCapable</key>
32
+ <true/>
33
+ <key>NSPrincipalClass</key>
34
+ <string>NSApplication</string>
35
+ </dict>
36
+ </plist>
@@ -0,0 +1,128 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>files</key>
6
+ <dict>
7
+ <key>Resources/CodexBeacon.icns</key>
8
+ <data>
9
+ ARb+dgpuDExYp5sFia3uxkcaQd0=
10
+ </data>
11
+ </dict>
12
+ <key>files2</key>
13
+ <dict>
14
+ <key>Resources/CodexBeacon.icns</key>
15
+ <dict>
16
+ <key>hash2</key>
17
+ <data>
18
+ /rRUPUqqL36bgR9YaCgNtPZoEW5epmPMQHPsP/iHbUk=
19
+ </data>
20
+ </dict>
21
+ </dict>
22
+ <key>rules</key>
23
+ <dict>
24
+ <key>^Resources/</key>
25
+ <true/>
26
+ <key>^Resources/.*\.lproj/</key>
27
+ <dict>
28
+ <key>optional</key>
29
+ <true/>
30
+ <key>weight</key>
31
+ <real>1000</real>
32
+ </dict>
33
+ <key>^Resources/.*\.lproj/locversion.plist$</key>
34
+ <dict>
35
+ <key>omit</key>
36
+ <true/>
37
+ <key>weight</key>
38
+ <real>1100</real>
39
+ </dict>
40
+ <key>^Resources/Base\.lproj/</key>
41
+ <dict>
42
+ <key>weight</key>
43
+ <real>1010</real>
44
+ </dict>
45
+ <key>^version.plist$</key>
46
+ <true/>
47
+ </dict>
48
+ <key>rules2</key>
49
+ <dict>
50
+ <key>.*\.dSYM($|/)</key>
51
+ <dict>
52
+ <key>weight</key>
53
+ <real>11</real>
54
+ </dict>
55
+ <key>^(.*/)?\.DS_Store$</key>
56
+ <dict>
57
+ <key>omit</key>
58
+ <true/>
59
+ <key>weight</key>
60
+ <real>2000</real>
61
+ </dict>
62
+ <key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
63
+ <dict>
64
+ <key>nested</key>
65
+ <true/>
66
+ <key>weight</key>
67
+ <real>10</real>
68
+ </dict>
69
+ <key>^.*</key>
70
+ <true/>
71
+ <key>^Info\.plist$</key>
72
+ <dict>
73
+ <key>omit</key>
74
+ <true/>
75
+ <key>weight</key>
76
+ <real>20</real>
77
+ </dict>
78
+ <key>^PkgInfo$</key>
79
+ <dict>
80
+ <key>omit</key>
81
+ <true/>
82
+ <key>weight</key>
83
+ <real>20</real>
84
+ </dict>
85
+ <key>^Resources/</key>
86
+ <dict>
87
+ <key>weight</key>
88
+ <real>20</real>
89
+ </dict>
90
+ <key>^Resources/.*\.lproj/</key>
91
+ <dict>
92
+ <key>optional</key>
93
+ <true/>
94
+ <key>weight</key>
95
+ <real>1000</real>
96
+ </dict>
97
+ <key>^Resources/.*\.lproj/locversion.plist$</key>
98
+ <dict>
99
+ <key>omit</key>
100
+ <true/>
101
+ <key>weight</key>
102
+ <real>1100</real>
103
+ </dict>
104
+ <key>^Resources/Base\.lproj/</key>
105
+ <dict>
106
+ <key>weight</key>
107
+ <real>1010</real>
108
+ </dict>
109
+ <key>^[^/]+$</key>
110
+ <dict>
111
+ <key>nested</key>
112
+ <true/>
113
+ <key>weight</key>
114
+ <real>10</real>
115
+ </dict>
116
+ <key>^embedded\.provisionprofile$</key>
117
+ <dict>
118
+ <key>weight</key>
119
+ <real>20</real>
120
+ </dict>
121
+ <key>^version\.plist$</key>
122
+ <dict>
123
+ <key>weight</key>
124
+ <real>20</real>
125
+ </dict>
126
+ </dict>
127
+ </dict>
128
+ </plist>
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ import {
7
+ defaultInstalledApp,
8
+ doctor,
9
+ installApp,
10
+ openApp,
11
+ uninstallApp,
12
+ } from "../lib/installer.mjs";
13
+
14
+ const packageDirectory = dirname(dirname(fileURLToPath(import.meta.url)));
15
+ const bundledApp = join(packageDirectory, "app", "CodexBeacon.app");
16
+
17
+ function printUsage() {
18
+ console.log(`Codex Beacon npm installer
19
+
20
+ Usage:
21
+ codex-beacon install [--no-launch] Install to ~/Applications and open it
22
+ codex-beacon open Open the installed app
23
+ codex-beacon doctor Check platform, installation, and signature
24
+ codex-beacon uninstall Clean up Beacon-owned services and remove the app
25
+ `);
26
+ }
27
+
28
+ function run() {
29
+ const [command = "help", ...arguments_] = process.argv.slice(2);
30
+
31
+ switch (command) {
32
+ case "install": {
33
+ const installedApp = installApp({ bundledApp });
34
+ console.log(`Installed Codex Beacon at ${installedApp}`);
35
+ if (!arguments_.includes("--no-launch")) {
36
+ openApp(installedApp);
37
+ }
38
+ return;
39
+ }
40
+ case "open": {
41
+ const installedApp = defaultInstalledApp();
42
+ doctor({ installedApp });
43
+ openApp(installedApp);
44
+ return;
45
+ }
46
+ case "doctor": {
47
+ const installedApp = doctor();
48
+ console.log(`Codex Beacon is installed and its signature is valid: ${installedApp}`);
49
+ console.log("Open Beacon and use its integration diagnostic to verify Codex Desktop compatibility.");
50
+ return;
51
+ }
52
+ case "uninstall": {
53
+ if (uninstallApp({})) {
54
+ console.log("Removed Codex Beacon from ~/Applications.");
55
+ } else {
56
+ console.log("Codex Beacon is not installed in ~/Applications.");
57
+ }
58
+ return;
59
+ }
60
+ case "help":
61
+ case "--help":
62
+ case "-h":
63
+ printUsage();
64
+ return;
65
+ default:
66
+ throw new Error(`Unknown command: ${command}`);
67
+ }
68
+ }
69
+
70
+ try {
71
+ run();
72
+ } catch (error) {
73
+ console.error(`codex-beacon: ${error.message}`);
74
+ process.exitCode = 1;
75
+ }
@@ -0,0 +1,120 @@
1
+ import {
2
+ cpSync,
3
+ existsSync,
4
+ mkdirSync,
5
+ renameSync,
6
+ rmSync,
7
+ statSync,
8
+ } from "node:fs";
9
+ import { homedir } from "node:os";
10
+ import { basename, dirname, join } from "node:path";
11
+ import { execFileSync } from "node:child_process";
12
+
13
+ export const applicationName = "CodexBeacon.app";
14
+ export const executableRelativePath = join("Contents", "MacOS", "CodexBeacon");
15
+
16
+ export function validatePlatform({ platform = process.platform, arch = process.arch } = {}) {
17
+ if (platform !== "darwin" || arch !== "arm64") {
18
+ throw new Error("Codex Beacon only supports macOS on Apple Silicon (darwin/arm64).");
19
+ }
20
+ }
21
+
22
+ export function defaultApplicationsDirectory(homeDirectory = homedir()) {
23
+ return join(homeDirectory, "Applications");
24
+ }
25
+
26
+ export function defaultInstalledApp(applicationsDirectory = defaultApplicationsDirectory()) {
27
+ return join(applicationsDirectory, applicationName);
28
+ }
29
+
30
+ export function verifyApp(appPath) {
31
+ execFileSync("/usr/bin/codesign", ["--verify", "--strict", "--verbose=2", appPath], {
32
+ stdio: "inherit",
33
+ });
34
+ }
35
+
36
+ export function openApp(appPath) {
37
+ execFileSync("/usr/bin/open", [appPath], { stdio: "inherit" });
38
+ }
39
+
40
+ function assertAppBundle(appPath, description) {
41
+ if (!existsSync(appPath) || !statSync(appPath).isDirectory()) {
42
+ throw new Error(`${description} is missing: ${appPath}`);
43
+ }
44
+ }
45
+
46
+ function replaceDirectory(source, destination) {
47
+ const parentDirectory = dirname(destination);
48
+ const stagingDirectory = join(parentDirectory, `.${basename(destination)}.install-${process.pid}`);
49
+ const backupDirectory = join(parentDirectory, `.${basename(destination)}.backup-${process.pid}`);
50
+
51
+ rmSync(stagingDirectory, { recursive: true, force: true });
52
+ rmSync(backupDirectory, { recursive: true, force: true });
53
+ cpSync(source, stagingDirectory, { recursive: true, preserveTimestamps: true });
54
+
55
+ const hadExistingInstallation = existsSync(destination);
56
+ if (hadExistingInstallation) {
57
+ renameSync(destination, backupDirectory);
58
+ }
59
+
60
+ try {
61
+ renameSync(stagingDirectory, destination);
62
+ } catch (error) {
63
+ if (hadExistingInstallation && !existsSync(destination)) {
64
+ renameSync(backupDirectory, destination);
65
+ }
66
+ throw error;
67
+ } finally {
68
+ rmSync(stagingDirectory, { recursive: true, force: true });
69
+ }
70
+
71
+ rmSync(backupDirectory, { recursive: true, force: true });
72
+ }
73
+
74
+ export function installApp({
75
+ bundledApp,
76
+ applicationsDirectory = defaultApplicationsDirectory(),
77
+ platform = process.platform,
78
+ arch = process.arch,
79
+ verifyApp: verify = verifyApp,
80
+ }) {
81
+ validatePlatform({ platform, arch });
82
+ assertAppBundle(bundledApp, "The bundled Codex Beacon app");
83
+ verify(bundledApp);
84
+ mkdirSync(applicationsDirectory, { recursive: true });
85
+
86
+ const installedApp = defaultInstalledApp(applicationsDirectory);
87
+ replaceDirectory(bundledApp, installedApp);
88
+ return installedApp;
89
+ }
90
+
91
+ export function uninstallApp({
92
+ installedApp = defaultInstalledApp(),
93
+ prepareForUninstall = (executable, commandArguments) =>
94
+ execFileSync(executable, commandArguments, { stdio: "inherit" }),
95
+ }) {
96
+ if (!existsSync(installedApp)) {
97
+ return false;
98
+ }
99
+
100
+ const executable = join(installedApp, executableRelativePath);
101
+ if (!existsSync(executable)) {
102
+ throw new Error(`The installed Codex Beacon app is incomplete: ${installedApp}`);
103
+ }
104
+
105
+ prepareForUninstall(executable, ["--prepare-for-uninstall"]);
106
+ rmSync(installedApp, { recursive: true, force: false });
107
+ return true;
108
+ }
109
+
110
+ export function doctor({
111
+ installedApp = defaultInstalledApp(),
112
+ platform = process.platform,
113
+ arch = process.arch,
114
+ verifyApp: verify = verifyApp,
115
+ }) {
116
+ validatePlatform({ platform, arch });
117
+ assertAppBundle(installedApp, "Codex Beacon is not installed; run `codex-beacon install`");
118
+ verify(installedApp);
119
+ return installedApp;
120
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@lindengjian/codex-beacon",
3
+ "version": "1.0.5",
4
+ "description": "Install Codex Beacon, a native macOS status companion for Codex Desktop.",
5
+ "license": "UNLICENSED",
6
+ "private": false,
7
+ "type": "module",
8
+ "bin": {
9
+ "codex-beacon": "bin/codex-beacon.mjs"
10
+ },
11
+ "files": [
12
+ "app",
13
+ "bin",
14
+ "lib",
15
+ "README.md"
16
+ ],
17
+ "os": [
18
+ "darwin"
19
+ ],
20
+ "cpu": [
21
+ "arm64"
22
+ ],
23
+ "engines": {
24
+ "node": ">=20"
25
+ },
26
+ "scripts": {
27
+ "test": "node --test test/*.test.mjs",
28
+ "prepack": "node scripts/prepare-package.mjs",
29
+ "pack:check": "npm pack --dry-run"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/lindengjian/CodexBeacon.git",
34
+ "directory": "npm"
35
+ },
36
+ "homepage": "https://github.com/lindengjian/CodexBeacon#readme",
37
+ "bugs": {
38
+ "url": "https://github.com/lindengjian/CodexBeacon/issues"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ }
43
+ }