create-agit 0.2.10 → 0.2.12
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/bin.mjs +29 -4
- package/install-binary.mjs +29 -0
- package/package.json +2 -2
package/bin.mjs
CHANGED
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
import { createRequire } from 'node:module'
|
|
16
16
|
import { randomUUID } from 'node:crypto'
|
|
17
17
|
import { performance } from 'node:perf_hooks'
|
|
18
|
-
import {
|
|
18
|
+
import { existsSync, realpathSync } from 'node:fs'
|
|
19
19
|
import { homedir, platform, arch } from 'node:os'
|
|
20
20
|
import { join, delimiter } from 'node:path'
|
|
21
21
|
import { spawnSync } from 'node:child_process'
|
|
22
|
+
import { installBinary } from './install-binary.mjs'
|
|
22
23
|
|
|
23
24
|
const require = createRequire(import.meta.url)
|
|
24
25
|
|
|
@@ -84,9 +85,7 @@ function main() {
|
|
|
84
85
|
const target = join(targetDir, binaryName())
|
|
85
86
|
const copying = performance.now()
|
|
86
87
|
try {
|
|
87
|
-
|
|
88
|
-
copyFileSync(bin, target)
|
|
89
|
-
chmodSync(target, 0o755)
|
|
88
|
+
installBinary(bin, target)
|
|
90
89
|
report('binary_copy', 'ok', copying)
|
|
91
90
|
} catch (error) {
|
|
92
91
|
report('binary_copy', 'error', copying, 'filesystem')
|
|
@@ -106,9 +105,35 @@ function main() {
|
|
|
106
105
|
report('verification', 'ok', verifying)
|
|
107
106
|
ok(`installed ${check.stdout.trim()} → ${target}`)
|
|
108
107
|
|
|
108
|
+
const reconciliation = spawnSync(target, ['rc', 'local', 'reconcile-installed', '--allow-other-installation'], {
|
|
109
|
+
encoding: 'utf8', timeout: 35000,
|
|
110
|
+
env: { ...installerEnv, AGIT_TELEMETRY_DEFER: '1' },
|
|
111
|
+
})
|
|
112
|
+
if (reconciliation.error || reconciliation.status !== 0) {
|
|
113
|
+
dim(`the CLI is installed, but the RC daemon could not be reconciled: ${(reconciliation.stderr || reconciliation.error?.message || `exit ${reconciliation.status}`).trim()}`)
|
|
114
|
+
} else {
|
|
115
|
+
try {
|
|
116
|
+
const outcome = JSON.parse(reconciliation.stdout)
|
|
117
|
+
if (outcome.status === 'restarted') ok('RC daemon restarted with the installed CLI')
|
|
118
|
+
if (outcome.status === 'deferred') dim(`RC daemon upgrade is pending: ${outcome.message}`)
|
|
119
|
+
} catch {
|
|
120
|
+
dim('the CLI is installed, but the RC daemon returned an unreadable reconciliation result')
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
109
124
|
if (!process.env.PATH?.split(delimiter).includes(targetDir)) {
|
|
110
125
|
dim(`note: ${targetDir} is not on your PATH — add it to your ${platform() === 'win32' ? 'user environment variables' : 'shell profile'}`)
|
|
111
126
|
}
|
|
127
|
+
const selected = process.env.PATH?.split(delimiter)
|
|
128
|
+
.map(directory => join(directory, binaryName()))
|
|
129
|
+
.find(candidate => existsSync(candidate))
|
|
130
|
+
let shadowed = selected && selected !== target
|
|
131
|
+
if (shadowed) {
|
|
132
|
+
try { shadowed = realpathSync(selected) !== realpathSync(target) } catch { /* PATH may contain an unreadable entry. */ }
|
|
133
|
+
}
|
|
134
|
+
if (shadowed) {
|
|
135
|
+
dim(`note: your shell selects another agit at ${selected}; put ${targetDir} first on PATH or invoke ${target} directly`)
|
|
136
|
+
}
|
|
112
137
|
|
|
113
138
|
// "installed by default at download time": hooks + skill + MCP + AGENTS.md in one pass. A
|
|
114
139
|
// failure does not block the install itself — the binary is already there, and setup can be
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, renameSync, rmSync, constants } from 'node:fs'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
export function installBinary(source, target, windows = process.platform === 'win32') {
|
|
6
|
+
const directory = dirname(target)
|
|
7
|
+
const extension = windows ? '.exe' : ''
|
|
8
|
+
const staging = join(directory, `.agit-install-${randomUUID()}${extension}`)
|
|
9
|
+
mkdirSync(directory, { recursive: true })
|
|
10
|
+
try {
|
|
11
|
+
copyFileSync(source, staging, constants.COPYFILE_EXCL)
|
|
12
|
+
chmodSync(staging, 0o755)
|
|
13
|
+
if (windows && existsSync(target)) {
|
|
14
|
+
const previous = join(directory, `.agit-previous-${randomUUID()}.exe`)
|
|
15
|
+
renameSync(target, previous)
|
|
16
|
+
try {
|
|
17
|
+
renameSync(staging, target)
|
|
18
|
+
} catch (error) {
|
|
19
|
+
renameSync(previous, target)
|
|
20
|
+
throw error
|
|
21
|
+
}
|
|
22
|
+
try { rmSync(previous) } catch { /* A running Windows image can retain its old path. */ }
|
|
23
|
+
} else {
|
|
24
|
+
renameSync(staging, target)
|
|
25
|
+
}
|
|
26
|
+
} finally {
|
|
27
|
+
try { rmSync(staging) } catch { /* The staged file may already have moved. */ }
|
|
28
|
+
}
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-agit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "One-line installer for agit (npx create-agit) — thin wrapper around @einsia/agent-git that lands the CLI at ~/.local/bin and wires skills/hooks/MCP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"create-agit": "./bin.mjs"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@einsia/agent-git": "0.2.
|
|
11
|
+
"@einsia/agent-git": "0.2.12"
|
|
12
12
|
},
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=20"
|