sidecar-cli 0.1.0-beta.4 → 0.1.0-beta.6

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
 
@@ -130,14 +144,23 @@ sidecar session end --summary "Initialization and recording flow implemented"
130
144
  ## AI agent usage
131
145
 
132
146
  Sidecar generates `.sidecar/AGENTS.md` during `init`.
147
+ This repo also includes a root `AGENTS.md` so the policy is visible before any `.sidecar` lookup.
148
+
149
+ Required minimum for any code change:
150
+
151
+ 1. `sidecar context --format markdown`
152
+ 2. `sidecar worklog record --done "<what changed>" --files <paths> --by agent`
153
+ 3. if behavior/design changed: `sidecar decision record ...`
154
+ 4. if follow-up exists: `sidecar task add ...`
155
+ 5. `sidecar summary refresh`
133
156
 
134
- That file explains:
157
+ Optional local enforcement:
158
+
159
+ ```bash
160
+ npm run install:hooks
161
+ ```
135
162
 
136
- - this repo uses Sidecar
137
- - required workflow for agents
138
- - when to record notes, decisions, worklogs, and tasks
139
- - recommended commands
140
- - a practical session checklist and example
163
+ This installs a non-blocking pre-commit reminder that runs `npm run sidecar:reminder`.
141
164
 
142
165
  Agents can discover the CLI surface programmatically with:
143
166
 
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
+ }
@@ -3,36 +3,71 @@ export function renderAgentsMarkdown(projectName) {
3
3
 
4
4
  Sidecar is the local project memory tool for this repository.
5
5
 
6
+ ## MUST before final response
7
+
8
+ If you changed code, you MUST run these commands in order:
9
+
10
+ 1. \`sidecar context --format markdown\`
11
+ 2. \`sidecar worklog record --done "<what changed>" --files <paths> --by agent\`
12
+ 3. if behavior/design/architecture changed: \`sidecar decision record --title "<decision>" --summary "<why>" --by agent\`
13
+ 4. if follow-up exists: \`sidecar task add "<follow-up>" --priority medium --by agent\`
14
+ 5. \`sidecar summary refresh\`
15
+
6
16
  ## Required workflow
7
17
 
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\`.
18
+ For any code change, run these in order before final response:
19
+
20
+ 1. \`sidecar context --format markdown\`
21
+ 2. implement changes
22
+ 3. \`sidecar worklog record ...\`
23
+ 4. if behavior/design/architecture changed: \`sidecar decision record ...\`
24
+ 5. \`sidecar summary refresh\`
25
+
26
+ ## Scope rules
27
+
28
+ - If files changed: always record a worklog.
29
+ - If behavior/design choice changed: record a decision.
30
+ - If follow-up work exists: add a task.
31
+ - Never skip summary refresh after recording work.
32
+
33
+ ## Definition of Done
15
34
 
16
- ## Commands to use
35
+ - [ ] Context reviewed
36
+ - \`sidecar context --format markdown\`
37
+ - [ ] Work recorded
38
+ - \`sidecar worklog record --done "<what changed>" --files <paths> --by agent\`
39
+ - [ ] Decision recorded when needed
40
+ - \`sidecar decision record --title "<decision>" --summary "<why>" --by agent\`
41
+ - [ ] Follow-up task created when needed
42
+ - \`sidecar task add "<follow-up>" --priority medium --by agent\`
43
+ - [ ] Summary refreshed
44
+ - \`sidecar summary refresh\`
45
+
46
+ ## Command patterns
17
47
 
18
48
  - Context: \`sidecar context --format markdown\`
19
- - Decision: \`sidecar decision record --title "<title>" --summary "<summary>" --by agent\`
20
49
  - Worklog: \`sidecar worklog record --done "<what changed>" --files src/a.ts,src/b.ts --by agent\`
50
+ - Decision: \`sidecar decision record --title "<title>" --summary "<summary>" --by agent\`
21
51
  - Task: \`sidecar task add "<follow-up>" --priority medium --by agent\`
22
52
  - Summary: \`sidecar summary refresh\`
23
53
 
24
- ## Example workflow
54
+ ## Example: small feature build
25
55
 
26
56
  \`\`\`bash
27
57
  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
58
+ # implement small todo app feature in src/app.ts and src/todo.ts
59
+ sidecar worklog record --goal "todo feature" --done "Added todo CRUD handlers and wired routes" --files src/app.ts,src/todo.ts --by agent
60
+ sidecar decision record --title "Use in-memory store for v1" --summary "Keeps implementation simple for initial feature" --by agent
61
+ sidecar task add "Persist todos to sqlite" --priority medium --by agent
32
62
  sidecar summary refresh
33
- sidecar session end --summary "Context and summary updates complete"
34
63
  \`\`\`
35
64
 
65
+ ## Optional hygiene reminder
66
+
67
+ Run this before final response to catch missed Sidecar logging:
68
+
69
+ - \`npm run sidecar:reminder\`
70
+
36
71
  Project: ${projectName}.
37
72
  `;
38
73
  }
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.6",
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,9 @@
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",
18
+ "install:hooks": "node scripts/install-git-hooks.mjs"
17
19
  },
18
20
  "keywords": [],
19
21
  "author": "",
@@ -27,11 +29,13 @@
27
29
  "better-sqlite3": "^12.8.0",
28
30
  "chalk": "^5.6.2",
29
31
  "commander": "^14.0.3",
32
+ "semver": "^7.7.4",
30
33
  "zod": "^4.3.6"
31
34
  },
32
35
  "devDependencies": {
33
36
  "@types/better-sqlite3": "^7.6.13",
34
37
  "@types/node": "^25.5.0",
38
+ "@types/semver": "^7.7.1",
35
39
  "tsx": "^4.21.0",
36
40
  "typescript": "^5.9.3"
37
41
  },