sidecar-cli 0.1.0-beta.4 → 0.1.0-beta.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 +15 -1
- package/dist/cli.js +17 -0
- package/dist/lib/update-check.js +82 -0
- package/dist/templates/agents.js +39 -15
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -23,16 +23,29 @@ Sidecar is a local-first, CLI-first project memory and recording tool for human
|
|
|
23
23
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
26
|
-
Install globally:
|
|
26
|
+
Install globally (stable):
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
npm install -g sidecar-cli
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
Install beta:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g sidecar-cli@beta
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Install rc:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install -g sidecar-cli@rc
|
|
42
|
+
```
|
|
43
|
+
|
|
32
44
|
Or run without install:
|
|
33
45
|
|
|
34
46
|
```bash
|
|
35
47
|
npx sidecar-cli --help
|
|
48
|
+
npx sidecar-cli@beta --help
|
|
36
49
|
```
|
|
37
50
|
|
|
38
51
|
Requirements:
|
|
@@ -70,6 +83,7 @@ This creates:
|
|
|
70
83
|
|
|
71
84
|
- `.sidecar/sidecar.db`
|
|
72
85
|
- `.sidecar/config.json`
|
|
86
|
+
- `.sidecar/preferences.json`
|
|
73
87
|
- `.sidecar/AGENTS.md`
|
|
74
88
|
- `.sidecar/summary.md`
|
|
75
89
|
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,7 @@ import { nowIso, humanTime, stringifyJson } from './lib/format.js';
|
|
|
10
10
|
import { SidecarError } from './lib/errors.js';
|
|
11
11
|
import { jsonFailure, jsonSuccess, printJsonEnvelope } from './lib/output.js';
|
|
12
12
|
import { bannerDisabled, renderBanner } from './lib/banner.js';
|
|
13
|
+
import { getUpdateNotice } from './lib/update-check.js';
|
|
13
14
|
import { requireInitialized } from './db/client.js';
|
|
14
15
|
import { renderAgentsMarkdown } from './templates/agents.js';
|
|
15
16
|
import { refreshSummaryFile } from './services/summary-service.js';
|
|
@@ -149,6 +150,20 @@ function renderContextMarkdown(data) {
|
|
|
149
150
|
const program = new Command();
|
|
150
151
|
program.name('sidecar').description('Local-first project memory and recording CLI').version(pkg.version);
|
|
151
152
|
program.option('--no-banner', 'Disable Sidecar banner output');
|
|
153
|
+
function maybePrintUpdateNotice() {
|
|
154
|
+
const jsonRequested = process.argv.includes('--json');
|
|
155
|
+
const notice = getUpdateNotice({
|
|
156
|
+
packageName: 'sidecar-cli',
|
|
157
|
+
currentVersion: pkg.version,
|
|
158
|
+
skip: jsonRequested,
|
|
159
|
+
});
|
|
160
|
+
if (!notice)
|
|
161
|
+
return;
|
|
162
|
+
const installTag = notice.channel === 'latest' ? 'latest' : notice.channel;
|
|
163
|
+
console.log('');
|
|
164
|
+
console.log(`Update available: ${pkg.version} -> ${notice.latestVersion}`);
|
|
165
|
+
console.log(`Run: npm install -g sidecar-cli@${installTag}`);
|
|
166
|
+
}
|
|
152
167
|
program
|
|
153
168
|
.command('init')
|
|
154
169
|
.description('Initialize Sidecar in the current directory')
|
|
@@ -722,6 +737,8 @@ if (process.argv.length === 2) {
|
|
|
722
737
|
console.log('');
|
|
723
738
|
}
|
|
724
739
|
program.outputHelp();
|
|
740
|
+
maybePrintUpdateNotice();
|
|
725
741
|
process.exit(0);
|
|
726
742
|
}
|
|
727
743
|
program.parse(process.argv);
|
|
744
|
+
maybePrintUpdateNotice();
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import { gt as semverGt } from 'semver';
|
|
6
|
+
const CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
|
|
7
|
+
function getCacheFilePath() {
|
|
8
|
+
return path.join(os.homedir(), '.sidecar-cli', 'update-check.json');
|
|
9
|
+
}
|
|
10
|
+
function loadCache() {
|
|
11
|
+
const file = getCacheFilePath();
|
|
12
|
+
if (!fs.existsSync(file))
|
|
13
|
+
return null;
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function saveCache(cache) {
|
|
22
|
+
const file = getCacheFilePath();
|
|
23
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
24
|
+
fs.writeFileSync(file, JSON.stringify(cache));
|
|
25
|
+
}
|
|
26
|
+
export function detectReleaseChannel(version) {
|
|
27
|
+
if (version.includes('-beta.'))
|
|
28
|
+
return 'beta';
|
|
29
|
+
if (version.includes('-rc.'))
|
|
30
|
+
return 'rc';
|
|
31
|
+
return 'latest';
|
|
32
|
+
}
|
|
33
|
+
function shouldCheckNow(cache) {
|
|
34
|
+
if (!cache?.lastCheckedAt)
|
|
35
|
+
return true;
|
|
36
|
+
const last = Date.parse(cache.lastCheckedAt);
|
|
37
|
+
if (Number.isNaN(last))
|
|
38
|
+
return true;
|
|
39
|
+
return Date.now() - last >= CHECK_INTERVAL_MS;
|
|
40
|
+
}
|
|
41
|
+
function fetchDistTags(pkgName) {
|
|
42
|
+
try {
|
|
43
|
+
const raw = execFileSync('npm', ['view', pkgName, 'dist-tags', '--json'], {
|
|
44
|
+
encoding: 'utf8',
|
|
45
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
46
|
+
timeout: 2000,
|
|
47
|
+
}).trim();
|
|
48
|
+
if (!raw)
|
|
49
|
+
return null;
|
|
50
|
+
const parsed = JSON.parse(raw);
|
|
51
|
+
return typeof parsed === 'object' && parsed ? parsed : null;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function getUpdateNotice(options) {
|
|
58
|
+
if (options.skip || process.env.SIDECAR_NO_UPDATE_CHECK === '1')
|
|
59
|
+
return null;
|
|
60
|
+
const channel = detectReleaseChannel(options.currentVersion);
|
|
61
|
+
const cache = loadCache();
|
|
62
|
+
if (!shouldCheckNow(cache)) {
|
|
63
|
+
const cachedVersion = cache?.byChannel?.[channel];
|
|
64
|
+
if (!cachedVersion)
|
|
65
|
+
return null;
|
|
66
|
+
return semverGt(cachedVersion, options.currentVersion) ? { latestVersion: cachedVersion, channel } : null;
|
|
67
|
+
}
|
|
68
|
+
const tags = fetchDistTags(options.packageName);
|
|
69
|
+
if (!tags)
|
|
70
|
+
return null;
|
|
71
|
+
const latestVersion = tags[channel];
|
|
72
|
+
if (!latestVersion)
|
|
73
|
+
return null;
|
|
74
|
+
saveCache({
|
|
75
|
+
lastCheckedAt: new Date().toISOString(),
|
|
76
|
+
byChannel: {
|
|
77
|
+
...(cache?.byChannel ?? {}),
|
|
78
|
+
[channel]: latestVersion,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
return semverGt(latestVersion, options.currentVersion) ? { latestVersion, channel } : null;
|
|
82
|
+
}
|
package/dist/templates/agents.js
CHANGED
|
@@ -5,34 +5,58 @@ Sidecar is the local project memory tool for this repository.
|
|
|
5
5
|
|
|
6
6
|
## Required workflow
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
2. Do the work.
|
|
10
|
-
3. Record updates:
|
|
11
|
-
- decision: \`sidecar decision record ...\`
|
|
12
|
-
- worklog: \`sidecar worklog record ...\`
|
|
13
|
-
- follow-up task: \`sidecar task add ...\`
|
|
14
|
-
4. Run \`sidecar summary refresh\`.
|
|
8
|
+
For any code change, run these in order before final response:
|
|
15
9
|
|
|
16
|
-
|
|
10
|
+
1. \`sidecar context --format markdown\`
|
|
11
|
+
2. implement changes
|
|
12
|
+
3. \`sidecar worklog record ...\`
|
|
13
|
+
4. if behavior/design/architecture changed: \`sidecar decision record ...\`
|
|
14
|
+
5. \`sidecar summary refresh\`
|
|
15
|
+
|
|
16
|
+
## Scope rules
|
|
17
|
+
|
|
18
|
+
- If files changed: always record a worklog.
|
|
19
|
+
- If behavior/design choice changed: record a decision.
|
|
20
|
+
- If follow-up work exists: add a task.
|
|
21
|
+
|
|
22
|
+
## Definition of Done
|
|
23
|
+
|
|
24
|
+
- [ ] Context reviewed
|
|
25
|
+
- \`sidecar context --format markdown\`
|
|
26
|
+
- [ ] Work recorded
|
|
27
|
+
- \`sidecar worklog record --done "<what changed>" --files <paths> --by agent\`
|
|
28
|
+
- [ ] Decision recorded when needed
|
|
29
|
+
- \`sidecar decision record --title "<decision>" --summary "<why>" --by agent\`
|
|
30
|
+
- [ ] Follow-up task created when needed
|
|
31
|
+
- \`sidecar task add "<follow-up>" --priority medium --by agent\`
|
|
32
|
+
- [ ] Summary refreshed
|
|
33
|
+
- \`sidecar summary refresh\`
|
|
34
|
+
|
|
35
|
+
## Command patterns
|
|
17
36
|
|
|
18
37
|
- Context: \`sidecar context --format markdown\`
|
|
19
|
-
- Decision: \`sidecar decision record --title "<title>" --summary "<summary>" --by agent\`
|
|
20
38
|
- Worklog: \`sidecar worklog record --done "<what changed>" --files src/a.ts,src/b.ts --by agent\`
|
|
39
|
+
- Decision: \`sidecar decision record --title "<title>" --summary "<summary>" --by agent\`
|
|
21
40
|
- Task: \`sidecar task add "<follow-up>" --priority medium --by agent\`
|
|
22
41
|
- Summary: \`sidecar summary refresh\`
|
|
23
42
|
|
|
24
|
-
## Example
|
|
43
|
+
## Example: small feature build
|
|
25
44
|
|
|
26
45
|
\`\`\`bash
|
|
27
46
|
sidecar context --format markdown
|
|
28
|
-
|
|
29
|
-
sidecar
|
|
30
|
-
sidecar
|
|
31
|
-
sidecar task add "
|
|
47
|
+
# implement small todo app feature in src/app.ts and src/todo.ts
|
|
48
|
+
sidecar worklog record --goal "todo feature" --done "Added todo CRUD handlers and wired routes" --files src/app.ts,src/todo.ts --by agent
|
|
49
|
+
sidecar decision record --title "Use in-memory store for v1" --summary "Keeps implementation simple for initial feature" --by agent
|
|
50
|
+
sidecar task add "Persist todos to sqlite" --priority medium --by agent
|
|
32
51
|
sidecar summary refresh
|
|
33
|
-
sidecar session end --summary "Context and summary updates complete"
|
|
34
52
|
\`\`\`
|
|
35
53
|
|
|
54
|
+
## Optional hygiene reminder
|
|
55
|
+
|
|
56
|
+
Run this before final response to catch missed Sidecar logging:
|
|
57
|
+
|
|
58
|
+
- \`npm run sidecar:reminder\`
|
|
59
|
+
|
|
36
60
|
Project: ${projectName}.
|
|
37
61
|
`;
|
|
38
62
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sidecar-cli",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.5",
|
|
4
4
|
"description": "Local-first project memory and recording tool",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npm run clean && tsc -p tsconfig.json",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"release:cut": "node scripts/cut-release.mjs",
|
|
14
14
|
"release:stable": "node scripts/cut-release.mjs --channel stable",
|
|
15
15
|
"release:beta": "node scripts/cut-release.mjs --channel beta",
|
|
16
|
-
"release:rc": "node scripts/cut-release.mjs --channel rc"
|
|
16
|
+
"release:rc": "node scripts/cut-release.mjs --channel rc",
|
|
17
|
+
"sidecar:reminder": "node scripts/sidecar-reminder.mjs"
|
|
17
18
|
},
|
|
18
19
|
"keywords": [],
|
|
19
20
|
"author": "",
|
|
@@ -27,11 +28,13 @@
|
|
|
27
28
|
"better-sqlite3": "^12.8.0",
|
|
28
29
|
"chalk": "^5.6.2",
|
|
29
30
|
"commander": "^14.0.3",
|
|
31
|
+
"semver": "^7.7.4",
|
|
30
32
|
"zod": "^4.3.6"
|
|
31
33
|
},
|
|
32
34
|
"devDependencies": {
|
|
33
35
|
"@types/better-sqlite3": "^7.6.13",
|
|
34
36
|
"@types/node": "^25.5.0",
|
|
37
|
+
"@types/semver": "^7.7.1",
|
|
35
38
|
"tsx": "^4.21.0",
|
|
36
39
|
"typescript": "^5.9.3"
|
|
37
40
|
},
|