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 +30 -7
- package/dist/cli.js +17 -0
- package/dist/lib/update-check.js +82 -0
- package/dist/templates/agents.js +50 -15
- package/package.json +6 -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
|
|
|
@@ -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
|
-
|
|
157
|
+
Optional local enforcement:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npm run install:hooks
|
|
161
|
+
```
|
|
135
162
|
|
|
136
|
-
-
|
|
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
|
+
}
|
package/dist/templates/agents.js
CHANGED
|
@@ -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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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
|
|
54
|
+
## Example: small feature build
|
|
25
55
|
|
|
26
56
|
\`\`\`bash
|
|
27
57
|
sidecar context --format markdown
|
|
28
|
-
|
|
29
|
-
sidecar
|
|
30
|
-
sidecar
|
|
31
|
-
sidecar task add "
|
|
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.
|
|
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
|
},
|