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 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 { chmodSync, copyFileSync, mkdirSync } from 'node:fs'
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
- mkdirSync(targetDir, { recursive: true })
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.10",
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.10"
11
+ "@einsia/agent-git": "0.2.12"
12
12
  },
13
13
  "engines": {
14
14
  "node": ">=20"