logwork-cli 1.2.0 → 1.3.0
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 +37 -25
- package/RELEASE.md +3 -2
- package/bin/logwork.mjs +2 -2
- package/commands/commits.mjs +78 -14
- package/commands/mcp.mjs +266 -0
- package/commands/setup.mjs +161 -40
- package/docs/advanced.md +7 -6
- package/docs/mcp-setup.md +80 -28
- package/docs/operations-guide.md +18 -3
- package/docs/recipes.md +18 -5
- package/docs/security.md +20 -1
- package/examples/mcp/antigravity.mcp_config.json +2 -2
- package/examples/mcp/codex.config.toml +2 -2
- package/examples/mcp/copilot.mcp.json +2 -2
- package/lib/commit-workflow.mjs +160 -5
- package/lib/diagnostics.mjs +72 -9
- package/lib/launcher.mjs +303 -0
- package/lib/manual-commands.mjs +2 -2
- package/lib/manual-ink-app.mjs +34 -1
- package/lib/manual-ink-interaction.mjs +12 -0
- package/lib/manual-ink-ui.mjs +38 -0
- package/lib/manual-mcp.mjs +68 -22
- package/lib/manual-repl.mjs +147 -34
- package/lib/mcp-install.mjs +930 -0
- package/lib/mcp-server.mjs +2 -2
- package/lib/node-runtime.mjs +52 -12
- package/lib/project-mapping-workflow.mjs +2 -20
- package/lib/query-workflow.mjs +19 -0
- package/lib/reminder-scheduler.mjs +34 -18
- package/lib/reminder-service.mjs +18 -4
- package/lib/repo-project-suggestions.mjs +285 -0
- package/lib/ui.mjs +44 -0
- package/package.json +1 -1
- package/skills/logwork/SKILL.md +6 -1
package/commands/setup.mjs
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import { constants as fsConstants, promises as fs } from 'node:fs';
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
|
-
import { delimiter, dirname, join, relative, resolve
|
|
3
|
+
import { delimiter, dirname, join, relative, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { redactText } from '../lib/auth-redaction.mjs';
|
|
6
6
|
import { credentialStoreLabel } from '../lib/credential-store.mjs';
|
|
7
7
|
import { npmInvocation } from '../lib/npm-command.mjs';
|
|
8
8
|
import { writeRuntimeInfo } from '../lib/node-runtime.mjs';
|
|
9
9
|
import { RUNTIME_INFO_FILE_NAME, helperHome } from '../lib/paths.mjs';
|
|
10
|
+
import { mcpArgs, resolveLaunchCommand, writeLauncher } from '../lib/launcher.mjs';
|
|
10
11
|
import {
|
|
12
|
+
MCP_LAUNCHER_NOTE,
|
|
11
13
|
MCP_NODE_PATH_NOTE,
|
|
12
14
|
MCP_SERVER_NAME,
|
|
15
|
+
formatClaudeMcpAddCommand,
|
|
13
16
|
formatCodexToml,
|
|
14
17
|
stdioMcpServersConfig,
|
|
15
18
|
vscodeMcpConfig
|
|
16
19
|
} from '../lib/manual-mcp.mjs';
|
|
20
|
+
import { createMcpInstallContext, describeMcpPlan, planMcpInstall } from '../lib/mcp-install.mjs';
|
|
17
21
|
import { loadReminderConfig } from '../lib/reminder-config.mjs';
|
|
18
22
|
import { installReminderScheduler } from '../lib/reminder-scheduler.mjs';
|
|
23
|
+
import { formatMcpInstallResults, isInteractiveTerminal, runMcpInstall } from './mcp.mjs';
|
|
19
24
|
|
|
20
25
|
// Package name before the rename. Its global install provides a `logwork` bin
|
|
21
26
|
// that would block `npm link` of logwork-cli, so setup removes it first.
|
|
@@ -28,8 +33,9 @@ const EXCLUDED_DIRS = new Set([
|
|
|
28
33
|
]);
|
|
29
34
|
|
|
30
35
|
// `logwork setup`: copy this package into ~/.logwork-cli, install its
|
|
31
|
-
// dependencies, link the `logwork` command,
|
|
32
|
-
//
|
|
36
|
+
// dependencies, link the `logwork` command, write the launcher, refresh a
|
|
37
|
+
// migrated reminder, and add or update the `logwork` entry in the MCP clients
|
|
38
|
+
// found on this machine.
|
|
33
39
|
export async function run(argv = []) {
|
|
34
40
|
if (argv.includes('--help') || argv.includes('-h')) {
|
|
35
41
|
console.log(formatSetupHelp());
|
|
@@ -44,16 +50,19 @@ export async function run(argv = []) {
|
|
|
44
50
|
|
|
45
51
|
export function formatSetupHelp() {
|
|
46
52
|
return `Usage:
|
|
47
|
-
logwork setup [--login|--no-login]
|
|
53
|
+
logwork setup [--yes] [--no-mcp-install] [--login|--no-login]
|
|
48
54
|
|
|
49
|
-
Installs the runtime to ~/.logwork-cli, links the \`logwork\` command, and
|
|
50
|
-
MCP
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
Installs the runtime to ~/.logwork-cli, links the \`logwork\` command, and adds
|
|
56
|
+
the "logwork" MCP server to the clients it finds (Claude Code, Cursor, Codex,
|
|
57
|
+
VS Code, Google Antigravity), asking once per client. Each edited config is
|
|
58
|
+
backed up first. Settings, mappings and the login session from an older
|
|
59
|
+
logwork-helper install are carried over automatically.
|
|
53
60
|
|
|
54
61
|
Options:
|
|
55
|
-
--
|
|
56
|
-
--no-
|
|
62
|
+
--yes, -y Update every detected MCP client without asking
|
|
63
|
+
--no-mcp-install Do not touch MCP client configs
|
|
64
|
+
--login Log in to Resource Optimiser after installing
|
|
65
|
+
--no-login Do not ask to log in`;
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
export async function installUserRuntime({
|
|
@@ -67,7 +76,9 @@ export async function installUserRuntime({
|
|
|
67
76
|
linkFn = linkGlobalBinaries,
|
|
68
77
|
authFn = maybeRunAuthLogin,
|
|
69
78
|
runtimeInfoFn = recordRuntimeInfo,
|
|
79
|
+
launcherFn = writeRuntimeLauncher,
|
|
70
80
|
reminderFn = refreshReminderSchedule,
|
|
81
|
+
mcpInstallFn = installMcpClients,
|
|
71
82
|
printFn = printMcpInstructions
|
|
72
83
|
}) {
|
|
73
84
|
await mkdirFn(targetDir, { recursive: true });
|
|
@@ -79,21 +90,61 @@ export async function installUserRuntime({
|
|
|
79
90
|
const linkResult = await linkFn(targetDir);
|
|
80
91
|
const authResult = await authFn(targetDir, options);
|
|
81
92
|
await runtimeInfoFn(targetDir);
|
|
93
|
+
await launcherFn(targetDir);
|
|
82
94
|
const reminderResult = await reminderFn(targetDir);
|
|
83
|
-
await
|
|
95
|
+
const mcpResult = await mcpInstallFn(targetDir, options);
|
|
96
|
+
await printFn(targetDir, authResult, linkResult, cleanupResult, reminderResult, mcpResult);
|
|
84
97
|
|
|
85
98
|
return {
|
|
86
99
|
targetDir,
|
|
87
100
|
authResult,
|
|
88
101
|
linkResult,
|
|
89
102
|
cleanupResult,
|
|
90
|
-
reminderResult
|
|
103
|
+
reminderResult,
|
|
104
|
+
mcpResult
|
|
91
105
|
};
|
|
92
106
|
}
|
|
93
107
|
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
|
|
108
|
+
// macOS/Linux: <home>/bin/logwork-launch, which MCP configs and the reminder
|
|
109
|
+
// run. It must exist before the reminder is re-registered.
|
|
110
|
+
export async function writeRuntimeLauncher(targetDir, {
|
|
111
|
+
nodePath = process.execPath,
|
|
112
|
+
platform = process.platform,
|
|
113
|
+
writeFn = writeLauncher
|
|
114
|
+
} = {}) {
|
|
115
|
+
return writeFn({ home: targetDir, nodePath, platform });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Adds or updates the `logwork` entry in the detected MCP clients:
|
|
119
|
+
// - --no-mcp-install: skipped;
|
|
120
|
+
// - --yes: every detected client, without asking;
|
|
121
|
+
// - a terminal: one yes/no per client that needs a change;
|
|
122
|
+
// - otherwise (npm exec from `logwork update`, CI): only the plan.
|
|
123
|
+
export async function installMcpClients(targetDir, options = {}, {
|
|
124
|
+
interactive = isInteractiveTerminal(),
|
|
125
|
+
ctx = createMcpInstallContext({ home: targetDir }),
|
|
126
|
+
install = runMcpInstall,
|
|
127
|
+
plan = planMcpInstall
|
|
128
|
+
} = {}) {
|
|
129
|
+
if (options.mcpInstall === false) {
|
|
130
|
+
return { mode: 'skipped', launch: ctx.launch };
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
if (options.yes || interactive) {
|
|
134
|
+
const result = await install({ ctx, yes: Boolean(options.yes), interactive });
|
|
135
|
+
return { mode: 'installed', launch: ctx.launch, results: result.results };
|
|
136
|
+
}
|
|
137
|
+
const plans = await plan(ctx);
|
|
138
|
+
return { mode: 'planned', launch: ctx.launch, plans, lines: plans.flatMap((item) => describeMcpPlan(item, ctx)) };
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return { mode: 'error', launch: ctx.launch, error: error.message };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Records the node that ran setup. The macOS/Linux launcher tries it first;
|
|
145
|
+
// on Windows the MCP configs and the reminder run it (or the nvm-windows
|
|
146
|
+
// symlink). doctor and reminder status compare it with the current Node.
|
|
147
|
+
// Best effort: a failed write must not fail the install.
|
|
97
148
|
export async function recordRuntimeInfo(targetDir, {
|
|
98
149
|
nodePath = process.execPath,
|
|
99
150
|
nodeVersion = process.version,
|
|
@@ -117,6 +168,7 @@ export async function recordRuntimeInfo(targetDir, {
|
|
|
117
168
|
// at a Node that nvm or Homebrew removed. Re-register it so the OS scheduler
|
|
118
169
|
// runs this runtime with the current node (and the legacy entry is removed by
|
|
119
170
|
// installReminderScheduler).
|
|
171
|
+
// The schedule runs the launcher (macOS) or a stable node.exe (Windows).
|
|
120
172
|
export async function refreshReminderSchedule(targetDir, {
|
|
121
173
|
nodePath = process.execPath,
|
|
122
174
|
loadConfig = loadReminderConfig,
|
|
@@ -437,6 +489,8 @@ export async function findCommandOnPath(commandName, {
|
|
|
437
489
|
|
|
438
490
|
export function parseSetupUserArgs(args = []) {
|
|
439
491
|
let loginMode = 'prompt';
|
|
492
|
+
let yes = false;
|
|
493
|
+
let mcpInstall = true;
|
|
440
494
|
|
|
441
495
|
for (const arg of args) {
|
|
442
496
|
if (arg === '--login') {
|
|
@@ -447,10 +501,18 @@ export function parseSetupUserArgs(args = []) {
|
|
|
447
501
|
loginMode = 'skip';
|
|
448
502
|
continue;
|
|
449
503
|
}
|
|
504
|
+
if (arg === '--yes' || arg === '-y') {
|
|
505
|
+
yes = true;
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (arg === '--no-mcp-install') {
|
|
509
|
+
mcpInstall = false;
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
450
512
|
throw new Error(`Unknown setup option: ${arg}`);
|
|
451
513
|
}
|
|
452
514
|
|
|
453
|
-
return { loginMode };
|
|
515
|
+
return { loginMode, yes, mcpInstall };
|
|
454
516
|
}
|
|
455
517
|
|
|
456
518
|
async function maybeRunAuthLogin(targetDir, { loginMode }) {
|
|
@@ -521,13 +583,14 @@ function runAuthLogin(targetDir) {
|
|
|
521
583
|
});
|
|
522
584
|
}
|
|
523
585
|
|
|
524
|
-
function printMcpInstructions(targetDir, authResult = null, linkResult = null, cleanupResult = null, reminderResult = null) {
|
|
586
|
+
function printMcpInstructions(targetDir, authResult = null, linkResult = null, cleanupResult = null, reminderResult = null, mcpResult = null) {
|
|
525
587
|
console.log(formatSetupUserInstructions({
|
|
526
588
|
targetDir,
|
|
527
589
|
authResult,
|
|
528
590
|
linkResult,
|
|
529
591
|
cleanupResult,
|
|
530
|
-
reminderResult
|
|
592
|
+
reminderResult,
|
|
593
|
+
mcpResult
|
|
531
594
|
}));
|
|
532
595
|
}
|
|
533
596
|
|
|
@@ -537,13 +600,14 @@ export function formatSetupUserInstructions({
|
|
|
537
600
|
linkResult = null,
|
|
538
601
|
cleanupResult = null,
|
|
539
602
|
reminderResult = null,
|
|
603
|
+
mcpResult = null,
|
|
540
604
|
platform = process.platform,
|
|
541
|
-
nodePath = process.execPath
|
|
605
|
+
nodePath = process.execPath,
|
|
606
|
+
env = process.env,
|
|
607
|
+
launch = mcpResult?.launch || resolveLaunchCommand({ platform, home: targetDir, execPath: nodePath, env })
|
|
542
608
|
} = {}) {
|
|
543
|
-
const entryPath = platform === 'win32'
|
|
544
|
-
? win32.resolve(targetDir, 'bin', 'logwork.mjs')
|
|
545
|
-
: resolve(targetDir, 'bin', 'logwork.mjs');
|
|
546
609
|
const storeLabel = credentialStoreLabel({ platform });
|
|
610
|
+
const mcp = formatMcpSection({ mcpResult, launch, platform });
|
|
547
611
|
const sections = [
|
|
548
612
|
`logwork-cli installed to ${targetDir}.`,
|
|
549
613
|
'',
|
|
@@ -559,28 +623,18 @@ export function formatSetupUserInstructions({
|
|
|
559
623
|
formatTerminalCommandInstructions(linkResult),
|
|
560
624
|
'',
|
|
561
625
|
'Next steps',
|
|
562
|
-
...formatNextSteps(authResult),
|
|
563
|
-
'',
|
|
564
|
-
`MCP config (server name "${MCP_SERVER_NAME}", runs: ${nodePath} ${entryPath} mcp)`,
|
|
565
|
-
MCP_NODE_PATH_NOTE,
|
|
626
|
+
...formatNextSteps(authResult, mcp.manual),
|
|
566
627
|
'',
|
|
567
|
-
|
|
568
|
-
JSON.stringify(stdioMcpServersConfig(entryPath, { nodePath }), null, 2),
|
|
569
|
-
'',
|
|
570
|
-
'Codex config.toml:',
|
|
571
|
-
formatCodexToml(entryPath, { nodePath }),
|
|
572
|
-
'',
|
|
573
|
-
'GitHub Copilot / VS Code mcp.json:',
|
|
574
|
-
JSON.stringify(vscodeMcpConfig(entryPath, { nodePath }), null, 2),
|
|
628
|
+
...mcp.lines,
|
|
575
629
|
'',
|
|
576
630
|
'AI agent skill (log work from your commits)',
|
|
577
631
|
'- Claude Code / Codex: run `logwork skill install`.',
|
|
578
632
|
'- Other MCP clients: use the MCP prompt "log_from_commits".',
|
|
579
633
|
'',
|
|
580
634
|
'Verify',
|
|
581
|
-
'- Restart or reload your IDE MCP tools after
|
|
635
|
+
'- Restart or reload your IDE MCP tools after a config change.',
|
|
582
636
|
'- In the IDE, ask: Check my logwork for this week.',
|
|
583
|
-
'-
|
|
637
|
+
'- `logwork mcp status` shows which clients have a current "logwork" entry.',
|
|
584
638
|
'',
|
|
585
639
|
'Safety',
|
|
586
640
|
'- Do not paste passwords, 2FA codes, Bearer tokens, cookies, or raw curl auth logs into AI chat.',
|
|
@@ -591,6 +645,70 @@ export function formatSetupUserInstructions({
|
|
|
591
645
|
return sections.join('\n');
|
|
592
646
|
}
|
|
593
647
|
|
|
648
|
+
// The MCP part of the setup summary. `manual` is true when the user still has
|
|
649
|
+
// to paste a config somewhere.
|
|
650
|
+
function formatMcpSection({ mcpResult, launch, platform }) {
|
|
651
|
+
const header = `MCP server "${MCP_SERVER_NAME}" runs: ${[launch.command, ...mcpArgs(launch)].join(' ')}`;
|
|
652
|
+
if (mcpResult?.mode === 'installed' && mcpResult.results?.length) {
|
|
653
|
+
const failed = mcpResult.results.some((result) => result.status === 'failed');
|
|
654
|
+
return {
|
|
655
|
+
manual: failed,
|
|
656
|
+
lines: [header, 'MCP clients', ...formatMcpInstallResults(mcpResult.results)]
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
if (mcpResult?.mode === 'planned') {
|
|
660
|
+
const pending = (mcpResult.plans || []).some((plan) => plan.action === 'add' || plan.action === 'update');
|
|
661
|
+
if (mcpResult.plans?.length) {
|
|
662
|
+
return {
|
|
663
|
+
manual: false,
|
|
664
|
+
lines: [
|
|
665
|
+
header,
|
|
666
|
+
'MCP clients (not changed: this is not an interactive terminal)',
|
|
667
|
+
...(mcpResult.lines || []),
|
|
668
|
+
...(pending ? ['To apply: run `logwork mcp install` (asks per client) or `logwork mcp install --yes`.'] : [])
|
|
669
|
+
]
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (mcpResult?.mode === 'skipped') {
|
|
674
|
+
return {
|
|
675
|
+
manual: false,
|
|
676
|
+
lines: [header, 'MCP clients: not changed (--no-mcp-install). Run `logwork mcp install` to add or update them, or `logwork mcp status` to check.']
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
// No client found, an error, or an older caller: print every snippet.
|
|
680
|
+
const lines = [header];
|
|
681
|
+
if (mcpResult?.mode === 'error') {
|
|
682
|
+
lines.push(`MCP clients: could not update automatically (${redactText(mcpResult.error || 'unknown error')}).`);
|
|
683
|
+
} else if (mcpResult) {
|
|
684
|
+
lines.push('MCP clients: none found (Claude Code, Cursor, Codex, VS Code, Google Antigravity).');
|
|
685
|
+
}
|
|
686
|
+
lines.push(...formatManualMcpSnippets(launch, { platform }));
|
|
687
|
+
return { manual: true, lines };
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export function formatManualMcpSnippets(launch, { platform = process.platform } = {}) {
|
|
691
|
+
const note = launch.stable ? (launch.kind === 'launcher' ? MCP_LAUNCHER_NOTE : '') : MCP_NODE_PATH_NOTE;
|
|
692
|
+
return [
|
|
693
|
+
'Manual MCP config (paste into your client):',
|
|
694
|
+
...(note ? [note] : []),
|
|
695
|
+
'',
|
|
696
|
+
'Cursor / Antigravity / Claude Code (.mcp.json):',
|
|
697
|
+
JSON.stringify(stdioMcpServersConfig(launch), null, 2),
|
|
698
|
+
'',
|
|
699
|
+
'Claude Code CLI:',
|
|
700
|
+
formatClaudeMcpAddCommand(launch, { platform }),
|
|
701
|
+
'',
|
|
702
|
+
'Codex config.toml:',
|
|
703
|
+
formatCodexToml(launch),
|
|
704
|
+
'',
|
|
705
|
+
'GitHub Copilot / VS Code mcp.json:',
|
|
706
|
+
JSON.stringify(vscodeMcpConfig(launch), null, 2),
|
|
707
|
+
'',
|
|
708
|
+
'An old "logwork-helper" MCP entry can be deleted; it points at the old runtime.'
|
|
709
|
+
];
|
|
710
|
+
}
|
|
711
|
+
|
|
594
712
|
function formatAuthStatus(authResult) {
|
|
595
713
|
if (authResult?.ok) {
|
|
596
714
|
return 'completed';
|
|
@@ -601,7 +719,7 @@ function formatAuthStatus(authResult) {
|
|
|
601
719
|
return 'not run';
|
|
602
720
|
}
|
|
603
721
|
|
|
604
|
-
function formatNextSteps(authResult) {
|
|
722
|
+
function formatNextSteps(authResult, manualMcp = true) {
|
|
605
723
|
const steps = [];
|
|
606
724
|
let index = 1;
|
|
607
725
|
if (!authResult?.ok) {
|
|
@@ -609,9 +727,12 @@ function formatNextSteps(authResult) {
|
|
|
609
727
|
steps.push(' logwork login');
|
|
610
728
|
index += 1;
|
|
611
729
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
730
|
+
if (manualMcp) {
|
|
731
|
+
steps.push(`${index}. Paste the MCP config below into your IDE (or run \`logwork mcp install\`).`);
|
|
732
|
+
index += 1;
|
|
733
|
+
}
|
|
734
|
+
steps.push(`${index}. Restart or reload your IDE MCP tools.`);
|
|
735
|
+
steps.push(`${index + 1}. Verify with: Check my logwork for this week.`);
|
|
615
736
|
return steps;
|
|
616
737
|
}
|
|
617
738
|
|
package/docs/advanced.md
CHANGED
|
@@ -78,9 +78,9 @@ To install and start auth immediately:
|
|
|
78
78
|
logwork setup --login
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
Use `--no-login` when installing in scripts or CI.
|
|
81
|
+
Use `--no-login` when installing in scripts or CI. Add `--no-mcp-install` to leave MCP client configs alone, or `--yes` to update every detected client without asking. Without a terminal and without `--yes`, setup only prints what `logwork mcp install` would change.
|
|
82
82
|
|
|
83
|
-
`logwork setup` copies the package into `~/.logwork-cli`, runs `npm ci --omit=dev` there, removes a globally installed `logwork-helper` package (its `logwork` bin would block linking), runs `npm link`, re-registers an enabled reminder, and
|
|
83
|
+
`logwork setup` copies the package into `~/.logwork-cli`, runs `npm ci --omit=dev` there, removes a globally installed `logwork-helper` package (its `logwork` bin would block linking), runs `npm link`, writes `runtime.json` and the launcher (`bin/logwork-launch`, macOS), re-registers an enabled reminder, and adds or updates the `logwork` entry in the detected MCP clients ([details](mcp-setup.md#automatic-setup)). It prints the manual snippets only for clients it could not update, or when it found none.
|
|
84
84
|
|
|
85
85
|
## Update
|
|
86
86
|
|
|
@@ -91,7 +91,7 @@ logwork update install # interactive confirmation
|
|
|
91
91
|
logwork update install --version 0.3.1 --yes
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
The installer accepts only the version currently published under npm's `latest` tag. It runs `npm exec --package=logwork-cli@<version> -- logwork setup --no-login` with a fixed argument list. Then it verifies the copied `package.json` version in `~/.logwork-cli`.
|
|
94
|
+
The installer accepts only the version currently published under npm's `latest` tag. It runs `npm exec --package=logwork-cli@<version> -- logwork setup --no-login` with a fixed argument list. Then it verifies the copied `package.json` version in `~/.logwork-cli`. That setup runs without a terminal, so it does not edit MCP configs; they keep working because they point at the launcher (macOS) or a stable `node.exe` (Windows). `logwork mcp status` shows whether anything needs `logwork mcp install`.
|
|
95
95
|
|
|
96
96
|
Project mappings, drafts, apply history, update cache, and OS credential-store records are preserved.
|
|
97
97
|
|
|
@@ -222,7 +222,8 @@ Useful commands inside the session:
|
|
|
222
222
|
/projects
|
|
223
223
|
/projects 5234
|
|
224
224
|
/map SCB 5234
|
|
225
|
-
/map --repo
|
|
225
|
+
/map --repo
|
|
226
|
+
/map --repo ~/code/fcs GKE Fair Chem
|
|
226
227
|
/history
|
|
227
228
|
/diagnostics
|
|
228
229
|
```
|
|
@@ -272,8 +273,8 @@ Inside `logwork`, use `/history`, `/history ro`, `/history jira`, or `/history b
|
|
|
272
273
|
|
|
273
274
|
## Troubleshooting
|
|
274
275
|
|
|
275
|
-
- **IDE does not show tools:** restart or reload the MCP client.
|
|
276
|
-
- **Tools show old names such as `preview_logwork_batch`:** the IDE is still connected to the old `logwork-helper` entry.
|
|
276
|
+
- **IDE does not show tools:** run `logwork mcp status`. If the client's entry is missing or stale, run `logwork mcp install`, then restart or reload the MCP client. The entry should run `~/.logwork-cli/bin/logwork-launch mcp` (on Windows, `node.exe %USERPROFILE%\.logwork-cli\bin\logwork.mjs mcp`) under the server name `logwork`. `logwork doctor` also checks that the launcher finds a usable Node.
|
|
277
|
+
- **Tools show old names such as `preview_logwork_batch`:** the IDE is still connected to the old `logwork-helper` entry. `logwork mcp install` removes it; the [tool name table](mcp-setup.md#tool-name-changes-from-logwork-helper) lists the renames.
|
|
277
278
|
- **`logwork: command not found` after `logwork setup`:** open a new terminal first. If it still fails, run `npm install -g logwork-cli`, or make sure your npm global bin directory is on `PATH`.
|
|
278
279
|
- **`npm link` fails with `EEXIST` on `logwork`:** an old global `logwork-helper` package still owns the bin. Run `npm rm -g logwork-helper`, then `logwork setup` again.
|
|
279
280
|
- **Not authenticated to Resource Optimiser:** run `logwork login`, or ask the assistant to call `login`. Enter secrets only in the terminal.
|
package/docs/mcp-setup.md
CHANGED
|
@@ -1,81 +1,130 @@
|
|
|
1
1
|
# MCP Setup
|
|
2
2
|
|
|
3
|
-
`logwork setup`
|
|
3
|
+
Run `logwork setup` and answer yes for each client. That is the whole setup: you do not edit MCP JSON or TOML yourself, and you do not need to know where Node is installed.
|
|
4
4
|
|
|
5
5
|
For the full RO/Jira/Both processing model, mapping, reconciliation, history, reminders and updates, see the [operations guide](operations-guide.md).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Automatic Setup
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- The entry is `bin/logwork.mjs` instead of the `logwork` command, because GUI IDEs often start without the npm global bin directory on `PATH`.
|
|
11
|
-
- The `command` is the absolute path of your Node binary instead of a bare `node`. Cursor or VS Code started from the Dock, Finder or Start menu usually does not get the `PATH` that nvm (or another version manager) sets up in your shell, so `node` is not found and the server never starts.
|
|
9
|
+
`logwork setup` (and `logwork mcp install` at any time later) looks for these clients and adds or updates the `logwork` server in each one it finds. A client counts as found only when its config directory or CLI exists; setup never creates config for a client you do not have.
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
| Client | Detected by | What is changed |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Claude Code | `claude` on `PATH`, or `~/.claude.json` | `claude mcp remove --scope user logwork`, then `claude mcp add --scope user logwork -- <command> <args>`. Without the CLI: the top-level `mcpServers` in `~/.claude.json`. |
|
|
14
|
+
| Cursor | `~/.cursor` | `mcpServers.logwork` in `~/.cursor/mcp.json` |
|
|
15
|
+
| Codex | `~/.codex` | the `[mcp_servers.logwork]` table in `~/.codex/config.toml` |
|
|
16
|
+
| VS Code (user) | `~/Library/Application Support/Code/User` (macOS), `%APPDATA%\Code\User` (Windows) | `servers.logwork` (`"type": "stdio"`) in `mcp.json` there |
|
|
17
|
+
| Google Antigravity | `~/.gemini/antigravity` | `mcpServers.logwork` in `~/.gemini/antigravity/mcp_config.json` |
|
|
18
|
+
|
|
19
|
+
How files are edited:
|
|
20
|
+
- Each file is read, parsed and merged. Only the `logwork` entry changes; other servers and settings stay as they are. Extra fields you added to the `logwork` entry (such as `env`) are kept, except in Codex, where the whole `[mcp_servers.logwork]` table (with sub-tables such as `[mcp_servers.logwork.env]`) is replaced.
|
|
21
|
+
- An old `logwork-helper` entry is removed. In Claude Code, a stale project-scope (`--scope local`) `logwork` entry is removed too, because it would hide the user-scope one.
|
|
22
|
+
- Before the first change, the file is copied to `<file>.logwork-backup-<YYYYMMDDHHmmss>` next to it. Then the new file is written atomically. A symlinked config is written through the link.
|
|
23
|
+
- When the entry is already current, nothing is written and no backup is made.
|
|
24
|
+
- When a file does not parse cleanly (JSON with comments or trailing commas, TOML with an unusual layout such as an inline `mcp_servers` table), it is not touched. The result says "could not update automatically" and shows the snippet to paste.
|
|
25
|
+
|
|
26
|
+
Commands:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
logwork mcp status # per client: current, stale (and why), missing, leftover logwork-helper
|
|
30
|
+
logwork mcp install # asks once per client that needs a change (default: yes)
|
|
31
|
+
logwork mcp install --client cursor # only some clients (repeatable: claude, cursor, codex, vscode, antigravity)
|
|
32
|
+
logwork mcp install --dry-run # show the planned changes, write nothing
|
|
33
|
+
logwork mcp install --yes # no questions
|
|
34
|
+
logwork setup --yes # setup, updating every detected client without asking
|
|
35
|
+
logwork setup --no-mcp-install # setup without touching MCP configs
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
When setup does not run in a terminal (for example from `logwork update`), it only prints what `logwork mcp install` would change.
|
|
39
|
+
|
|
40
|
+
`logwork doctor` includes the same per-client check.
|
|
41
|
+
|
|
42
|
+
## What The Configs Run
|
|
43
|
+
|
|
44
|
+
Every client runs one command under the server name `logwork`. The command never names a Node version, so `nvm install`, `brew upgrade node` or a new Node installer do not break it:
|
|
45
|
+
|
|
46
|
+
- **macOS:** `~/.logwork-cli/bin/logwork-launch mcp`. `logwork setup` writes this small `sh` script. It starts `~/.logwork-cli/bin/logwork.mjs` with the first Node 22+ it finds, in this order:
|
|
47
|
+
1. the Node that ran `logwork setup`;
|
|
48
|
+
2. `node` on `PATH`;
|
|
49
|
+
3. the newest nvm Node (`$NVM_DIR` or `~/.nvm`);
|
|
50
|
+
4. Volta (`~/.volta/bin/node`) and the fnm default;
|
|
51
|
+
5. `/opt/homebrew/bin/node`, `/usr/local/bin/node`.
|
|
52
|
+
|
|
53
|
+
If none is found, it prints one line ("install Node.js 22 or newer, or run `logwork setup` again") and exits with code 127.
|
|
54
|
+
- **Windows:** `<node.exe> %USERPROFILE%\.logwork-cli\bin\logwork.mjs mcp`. GUI clients would need `cmd /c` to run a `.cmd` launcher, so the config uses a stable `node.exe` instead:
|
|
55
|
+
- when Node runs from an nvm-windows version folder and `NVM_SYMLINK` is set, `%NVM_SYMLINK%\node.exe`, which follows `nvm use`;
|
|
56
|
+
- otherwise the Node that ran setup, usually `C:\Program Files\nodejs\node.exe`, which an installer upgrade keeps.
|
|
57
|
+
|
|
58
|
+
With any other Node location (Scoop, a portable zip), re-run `logwork setup` after moving or upgrading Node.
|
|
59
|
+
|
|
60
|
+
The paths are absolute because GUI IDEs (started from the Dock, Finder or Start menu) often do not get your shell's `PATH`, so a bare `node` or `logwork` would not be found.
|
|
61
|
+
|
|
62
|
+
## Manual Setup (Fallback)
|
|
14
63
|
|
|
15
|
-
|
|
64
|
+
Use this only for a client that `logwork setup` does not support, or one whose file it could not update. `logwork setup` prints the snippet for each client it could not update. You can also open the terminal UI with `logwork` and type `/mcp`, or `/mcp <client>` for a single client; both print your real paths.
|
|
16
65
|
|
|
17
|
-
The examples use `/Users/<user>`
|
|
66
|
+
The examples use `/Users/<user>` as a placeholder. On Windows, use the paths printed by `logwork setup` or `/mcp`, for example `"command": "C:\\Program Files\\nodejs\\node.exe"` and `"args": ["C:\\Users\\<user>\\.logwork-cli\\bin\\logwork.mjs", "mcp"]` inside JSON or TOML strings.
|
|
18
67
|
|
|
19
|
-
|
|
68
|
+
### Cursor / Google Antigravity
|
|
20
69
|
|
|
21
|
-
|
|
70
|
+
`~/.cursor/mcp.json`, or `~/.gemini/antigravity/mcp_config.json`:
|
|
22
71
|
|
|
23
72
|
```json
|
|
24
73
|
{
|
|
25
74
|
"mcpServers": {
|
|
26
75
|
"logwork": {
|
|
27
|
-
"command": "
|
|
28
|
-
"args": ["
|
|
76
|
+
"command": "/Users/<user>/.logwork-cli/bin/logwork-launch",
|
|
77
|
+
"args": ["mcp"]
|
|
29
78
|
}
|
|
30
79
|
}
|
|
31
80
|
}
|
|
32
81
|
```
|
|
33
82
|
|
|
34
|
-
|
|
83
|
+
### Codex
|
|
35
84
|
|
|
36
85
|
`~/.codex/config.toml`, or project `.codex/config.toml`:
|
|
37
86
|
|
|
38
87
|
```toml
|
|
39
88
|
[mcp_servers.logwork]
|
|
40
|
-
command = "
|
|
41
|
-
args = ["
|
|
89
|
+
command = "/Users/<user>/.logwork-cli/bin/logwork-launch"
|
|
90
|
+
args = ["mcp"]
|
|
42
91
|
startup_timeout_sec = 20
|
|
43
92
|
tool_timeout_sec = 120
|
|
44
93
|
```
|
|
45
94
|
|
|
46
|
-
|
|
95
|
+
### GitHub Copilot / VS Code
|
|
47
96
|
|
|
48
|
-
Workspace `.vscode/mcp.json`, or your VS Code user
|
|
97
|
+
Workspace `.vscode/mcp.json`, or your VS Code user `mcp.json`:
|
|
49
98
|
|
|
50
99
|
```json
|
|
51
100
|
{
|
|
52
101
|
"servers": {
|
|
53
102
|
"logwork": {
|
|
54
103
|
"type": "stdio",
|
|
55
|
-
"command": "
|
|
56
|
-
"args": ["
|
|
104
|
+
"command": "/Users/<user>/.logwork-cli/bin/logwork-launch",
|
|
105
|
+
"args": ["mcp"]
|
|
57
106
|
}
|
|
58
107
|
}
|
|
59
108
|
}
|
|
60
109
|
```
|
|
61
110
|
|
|
62
|
-
|
|
111
|
+
### Claude Code
|
|
63
112
|
|
|
64
113
|
```bash
|
|
65
|
-
claude mcp add --transport stdio
|
|
114
|
+
claude mcp add --transport stdio --scope user logwork -- ~/.logwork-cli/bin/logwork-launch mcp
|
|
66
115
|
```
|
|
67
116
|
|
|
68
117
|
From Windows PowerShell:
|
|
69
118
|
|
|
70
119
|
```powershell
|
|
71
|
-
claude mcp add --transport stdio logwork -- 'C:\Program Files\nodejs\node.exe' 'C:\Users\<user>\.logwork-cli\bin\logwork.mjs' mcp
|
|
120
|
+
claude mcp add --transport stdio --scope user logwork -- 'C:\Program Files\nodejs\node.exe' 'C:\Users\<user>\.logwork-cli\bin\logwork.mjs' mcp
|
|
72
121
|
```
|
|
73
122
|
|
|
74
123
|
Or add the Cursor JSON above to the project `.mcp.json`.
|
|
75
124
|
|
|
76
|
-
Templates are also in [examples/mcp](../examples/mcp/)
|
|
125
|
+
Templates (macOS form) are also in [examples/mcp](../examples/mcp/); on Windows, use the paths printed by `/mcp`.
|
|
77
126
|
|
|
78
|
-
If you used `logwork-helper` before, delete its old MCP entry. It points at `~/.logwork-helper/mcp-server.mjs`, which is the old runtime.
|
|
127
|
+
If you used `logwork-helper` before and edit configs by hand, delete its old MCP entry. It points at `~/.logwork-helper/mcp-server.mjs`, which is the old runtime.
|
|
79
128
|
|
|
80
129
|
## Exposed Tools
|
|
81
130
|
|
|
@@ -95,7 +144,7 @@ Previews expire after 1 hour. They are also lost when the server restarts.
|
|
|
95
144
|
| Group | Tool | Kind | Purpose |
|
|
96
145
|
|---|---|---|---|
|
|
97
146
|
| Read | `get_logwork` | read-only | Booked vs logged RO hours by day and project, with entries (`logworkId`, worklog task, description, status). |
|
|
98
|
-
| Read | `draft_from_commits` | read-only | Your git commits (all branches, your author) for a period in the given `repos`, grouped per day into draft lines with a suggested worklog task, an RO project (repo mapping, else ticket/keyword mappings and bookings) and hours that fill each project's remaining booked time. Returns `draftText` and `projectOverrides` for `log_work`, and `
|
|
147
|
+
| Read | `draft_from_commits` | read-only | Your git commits (all branches, your author) for a period in the given `repos`, grouped per day into draft lines with a suggested worklog task, an RO project (repo mapping, else ticket/keyword mappings and bookings) and hours that fill each project's remaining booked time. Returns `draftText` and `projectOverrides` for `log_work`, `unmappedRepos`, and `repoSuggestions` (likely project per unmapped repo, with reasons) plus `projectCandidates`. |
|
|
99
148
|
| Read | `list_projects` | read-only | RO memberships (`projectMemberId`, `projectId`, `projectName`) and local mappings. |
|
|
100
149
|
| Read | `list_tasks` | read-only | RO worklog task catalog for one `projectId`: id, name, type of work, and when to use each task. |
|
|
101
150
|
| Read | `get_jira_issue` | read-only | Jira issue key, summary and status. |
|
|
@@ -198,7 +247,10 @@ Expected flow:
|
|
|
198
247
|
- Each line gets a project. A `map_project` mapping whose `repos` holds the repo comes first; then ticket/keyword mappings and that day's booked projects.
|
|
199
248
|
- Each project's remaining hours are split across its own lines and never exceeded. Lines without a project share the room of booked projects that no line claimed.
|
|
200
249
|
- It returns `draftText`, plus `projectOverrides` (preview entry id → `projectMemberId`) for each line with a project.
|
|
201
|
-
- It also returns `unmappedRepos
|
|
250
|
+
- It also returns `unmappedRepos` (repo paths whose lines got no project), `repoSuggestions` and `projectCandidates`:
|
|
251
|
+
- `repoSuggestions` maps each unmapped repo to up to 5 projects, best first: `{ projectName, projectMemberId, projectId, score, reasons }`. The evidence is a ticket from the repo's commits that you logged to the project in the last 30 days, the repo folder or git remote name matching the project name (its acronym in parentheses or its initials), and the only project booked on the repo's commit days. `reasons` are readable, for example `ticket FCS-12 was logged to this project on 2026-11-03` or `repo name matches FCS`.
|
|
252
|
+
- `projectCandidates` lists every member project (booked ones first).
|
|
253
|
+
- The assistant asks one short question per repo by project name ("Is fcs-web part of GKE Fair Chem System (FCS)?"). On a yes it calls `map_project` with `projectName` (or the suggestion's `projectMemberId`), `repos` and `confirm: true`, then runs `draft_from_commits` again.
|
|
202
254
|
3. `list_tasks` confirms the worklog task names for each project.
|
|
203
255
|
4. The assistant rewrites vague descriptions, shows you the block and waits for approval.
|
|
204
256
|
5. `log_work(text, projectOverrides)` previews the entries, then `log_work(batchId, confirm: true)` applies them.
|
|
@@ -353,11 +405,11 @@ The two applies are intentionally not atomic. `log_work` never writes Jira, and
|
|
|
353
405
|
You do not need to create the mapping file by hand. When a preview cannot resolve a ticket like `SCB-213`, the assistant calls `list_projects`. After you approve, it calls `map_project` with `tickets`, an optional `keywords`, and `confirm: true`.
|
|
354
406
|
|
|
355
407
|
For commit drafts, a mapping can also list git repos.
|
|
356
|
-
- When `draft_from_commits` reports `unmappedRepos`, the assistant
|
|
408
|
+
- When `draft_from_commits` reports `unmappedRepos`, the assistant confirms the top `repoSuggestions` entry with you by name, then calls `map_project` with `projectName`, `repos` (absolute paths) and `confirm: true`.
|
|
357
409
|
- At least one ticket prefix or repo is required.
|
|
358
410
|
- A subfolder is stored as the root of its repo.
|
|
359
411
|
- Paths are compared without trailing separators, and case-insensitively on Windows.
|
|
360
|
-
- In the terminal UI, `/map --repo [path] <
|
|
412
|
+
- In a terminal, `logwork commits` asks for each unmapped repo with a picker (likely project first). In the terminal UI, `/map --repo [path]` opens the same picker and `/map --repo [path] <project name>` maps by name. The path defaults to the current folder.
|
|
361
413
|
|
|
362
414
|
Mappings are stored in one of two places:
|
|
363
415
|
- **User scope (default):** `~/.logwork-cli/.logwork.json`.
|
package/docs/operations-guide.md
CHANGED
|
@@ -19,6 +19,8 @@ npm install -g logwork-cli
|
|
|
19
19
|
logwork setup
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
`logwork setup` also writes the launcher (`~/.logwork-cli/bin/logwork-launch` on macOS) and adds the `logwork` MCP server to the clients it finds (Claude Code, Cursor, Codex, VS Code, Google Antigravity), asking once per client. Each edited config is backed up first. Options: `--yes` (no questions), `--no-mcp-install` (do not touch MCP configs). Check or redo it later with `logwork mcp status` and `logwork mcp install`; see [MCP setup](mcp-setup.md#automatic-setup).
|
|
23
|
+
|
|
22
24
|
Upgrading from `logwork-helper`: run `npm uninstall -g logwork-helper` first. Both packages provide a `logwork` command, and npm refuses to overwrite it (`EEXIST`). If `~/.logwork-helper` was already deleted, the uninstall leaves broken links behind; remove them with `P="$(npm prefix -g)"; rm -f "$P/bin/logwork" "$P"/bin/logwork-helper* "$P/lib/node_modules/logwork-helper"`, or run `npx logwork-cli@latest setup`, which removes them.
|
|
23
25
|
|
|
24
26
|
Authenticate each target from Terminal:
|
|
@@ -348,6 +350,14 @@ RO project mapping can use:
|
|
|
348
350
|
- Task keywords, for example `maintenance mode`.
|
|
349
351
|
- Explicit project selection during preview.
|
|
350
352
|
- Jira project key/name metadata in the terminal Both flow to rank RO memberships.
|
|
353
|
+
- Git repo roots (`repos`), for commit drafts.
|
|
354
|
+
|
|
355
|
+
A repo with no mapping is mapped once, in place, without ids:
|
|
356
|
+
- `logwork commits` in an interactive terminal asks `Which RO project does <repo> belong to?` with the likely project preselected, saves the choice and redoes the draft (`--no-prompt` turns this off).
|
|
357
|
+
- In the terminal UI, `/map --repo [path]` opens the same picker; `/map --repo [path] <project name>` maps by name (case-insensitive, then a unique part of the name; an ambiguous name opens the picker).
|
|
358
|
+
- MCP: `draft_from_commits` returns `repoSuggestions` per unmapped repo; the assistant confirms the top one by name and calls `map_project` with `projectName` and `repos`.
|
|
359
|
+
|
|
360
|
+
The likely project comes from ticket keys in the repo's commits that you logged to a project in the last 30 days, then the repo folder or git remote name against the project name (acronym in parentheses, initials, shared words), then the only project booked on the repo's commit days.
|
|
351
361
|
|
|
352
362
|
Example MCP sequence:
|
|
353
363
|
|
|
@@ -453,8 +463,10 @@ Behavior:
|
|
|
453
463
|
- Missing auth produces an actionable notification without exposing API details.
|
|
454
464
|
- macOS uses a user `launchd` agent (`sg.vinova.logwork-cli.reminder`).
|
|
455
465
|
- Windows uses an interactive user Task Scheduler task (`Logwork Reminder`).
|
|
456
|
-
- The scheduler runs
|
|
457
|
-
-
|
|
466
|
+
- The scheduler runs the same command as the MCP configs with `reminder run --home ~/.logwork-cli`:
|
|
467
|
+
- macOS: `~/.logwork-cli/bin/logwork-launch`, which finds a Node 22+ itself, so a Node upgrade does not break the reminder;
|
|
468
|
+
- Windows: a stable `node.exe` (the nvm-windows symlink, or `C:\Program Files\nodejs\node.exe`) plus `~/.logwork-cli/bin/logwork.mjs`.
|
|
469
|
+
- `logwork reminder status` and `logwork doctor` warn when the scheduled command is missing, when the launcher finds no usable Node, and when a schedule from an older version still runs a raw Node path. Run `logwork setup` (or `logwork reminder enable`) to re-register it.
|
|
458
470
|
- Enabling or disabling the reminder also removes a leftover `logwork-helper` schedule.
|
|
459
471
|
|
|
460
472
|
Commit evidence:
|
|
@@ -567,6 +579,8 @@ The release doctor checks package version consistency, self-dependencies, clean/
|
|
|
567
579
|
| Update cache | `.logwork-cli/update-state.json` | No |
|
|
568
580
|
| Reminder config/state | `.logwork-cli/reminder.json`, `.logwork-cli/reminder-state.json` | No |
|
|
569
581
|
| Runtime Node record | `.logwork-cli/runtime.json` (Node path and version from `logwork setup`) | No |
|
|
582
|
+
| Launcher (macOS) | `.logwork-cli/bin/logwork-launch`, written by `logwork setup` | No |
|
|
583
|
+
| MCP config backups | `<client config>.logwork-backup-<timestamp>`, next to each edited client config | No |
|
|
570
584
|
| RO/Jira sessions | OS credential store, service `logwork-cli` | Yes |
|
|
571
585
|
|
|
572
586
|
The helper home is `~/.logwork-cli` on macOS and `%USERPROFILE%\.logwork-cli` on Windows. `LOGWORK_HOME` overrides it; the older `LOGWORK_HELPER_HOME` is still honored.
|
|
@@ -616,7 +630,8 @@ Recommended end-user checks after installation:
|
|
|
616
630
|
- Partial Both result: inspect `/history both`, then preview only the missing target.
|
|
617
631
|
- npm `E401`: refresh npm login with `npm login --registry=https://registry.npmjs.org/`.
|
|
618
632
|
- Reminder config/scheduler mismatch: rerun `reminder enable` or `reminder disable`.
|
|
619
|
-
-
|
|
633
|
+
- MCP client or reminder does not start after a Node change: run `logwork doctor` or `logwork mcp status`. `logwork setup` rewrites the launcher, re-registers the reminder and updates the MCP configs it can edit; paste the printed snippet only for a client it reports as "could not update automatically".
|
|
634
|
+
- `logwork mcp install` reports "could not update automatically": the file has comments, trailing commas or an unusual TOML layout. Paste the printed snippet by hand, or remove the comments and run it again.
|
|
620
635
|
- MCP after update: restart or reload the MCP connection.
|
|
621
636
|
|
|
622
637
|
For client configuration details, see [MCP setup](mcp-setup.md). For security boundaries and stored-data details, see [Security and auth](security.md). For copy-ready task recipes, see [Quick recipes](recipes.md).
|