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 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
+ }
@@ -5,34 +5,58 @@ Sidecar is the local project memory tool for this repository.
5
5
 
6
6
  ## Required workflow
7
7
 
8
- 1. Run \`sidecar context --format markdown\`.
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
- ## Commands to use
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 workflow
43
+ ## Example: small feature build
25
44
 
26
45
  \`\`\`bash
27
46
  sidecar context --format markdown
28
- sidecar session start --actor agent --name codex
29
- sidecar decision record --title "Choose SQLite" --summary "Local, deterministic storage" --by agent
30
- sidecar worklog record --goal "Refactor context output" --done "Improved markdown and json context payload" --files src/cli.ts,src/services/context-service.ts --by agent
31
- sidecar task add "Add integration test for context output" --priority medium --by agent
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.4",
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
  },