@shaifulshabuj-waymarks/cli 0.1.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/dist/commands/init.js +274 -0
- package/dist/commands/logs.js +68 -0
- package/dist/commands/start.js +88 -0
- package/dist/commands/status.js +24 -0
- package/dist/index.js +25 -0
- package/package.json +40 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.run = run;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const readline = __importStar(require("readline"));
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
42
|
+
const DEFAULT_CONFIG = {
|
|
43
|
+
version: '1',
|
|
44
|
+
policies: {
|
|
45
|
+
allowedPaths: [
|
|
46
|
+
'./src/**',
|
|
47
|
+
'./data/**',
|
|
48
|
+
'./README.md',
|
|
49
|
+
'./CLAUDE.md'
|
|
50
|
+
],
|
|
51
|
+
blockedPaths: [
|
|
52
|
+
'./.env',
|
|
53
|
+
'./.env.*',
|
|
54
|
+
'./package-lock.json',
|
|
55
|
+
'/etc/**',
|
|
56
|
+
'/usr/**'
|
|
57
|
+
],
|
|
58
|
+
blockedCommands: [
|
|
59
|
+
'rm -rf',
|
|
60
|
+
'DROP TABLE',
|
|
61
|
+
'DROP DATABASE',
|
|
62
|
+
'chmod 777',
|
|
63
|
+
'regex:\\|\\s*bash',
|
|
64
|
+
'regex:\\|\\s*sh\\b',
|
|
65
|
+
'regex:\\$\\(curl',
|
|
66
|
+
'regex:\\$\\(wget',
|
|
67
|
+
'wget '
|
|
68
|
+
],
|
|
69
|
+
requireApproval: [
|
|
70
|
+
'./src/db/**',
|
|
71
|
+
'./waymark.config.json'
|
|
72
|
+
],
|
|
73
|
+
maxBashOutputBytes: 10000
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const CLAUDE_MD_CONTENT = `# Waymark — Active in this project
|
|
77
|
+
|
|
78
|
+
All file system actions in this project are monitored and controlled by Waymark.
|
|
79
|
+
|
|
80
|
+
## Rules (auto-loaded from waymark.config.json)
|
|
81
|
+
- Always use Waymark MCP tools for file operations
|
|
82
|
+
- Use waymark:write_file instead of write_file
|
|
83
|
+
- Use waymark:read_file instead of read_file
|
|
84
|
+
- Use waymark:bash instead of bash
|
|
85
|
+
- Never bypass Waymark tools for any file operation
|
|
86
|
+
|
|
87
|
+
## Why
|
|
88
|
+
Waymark logs all actions, enforces scope policies,
|
|
89
|
+
enables rollback, and routes sensitive paths for
|
|
90
|
+
human approval before execution.
|
|
91
|
+
|
|
92
|
+
## Dashboard
|
|
93
|
+
View all actions at: http://localhost:3001
|
|
94
|
+
`;
|
|
95
|
+
const WAYMARK_MARKER = '<!-- waymark -->';
|
|
96
|
+
function prompt(question) {
|
|
97
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
98
|
+
return new Promise(resolve => {
|
|
99
|
+
rl.question(question, answer => { rl.close(); resolve(answer.trim()); });
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function getClaudeDesktopConfigPath() {
|
|
103
|
+
const platform = process.platform;
|
|
104
|
+
if (platform === 'darwin') {
|
|
105
|
+
return path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
106
|
+
}
|
|
107
|
+
else if (platform === 'win32') {
|
|
108
|
+
return path.join(process.env.APPDATA || os.homedir(), 'Claude', 'claude_desktop_config.json');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return path.join(os.homedir(), '.config', 'Claude', 'claude_desktop_config.json');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function resolveServerBin() {
|
|
115
|
+
// Try installed @shaifulshabuj-waymarks/server package
|
|
116
|
+
try {
|
|
117
|
+
return require.resolve('@shaifulshabuj-waymarks/server/dist/mcp/server.js');
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Fallback: assume we're inside the waymark monorepo
|
|
121
|
+
return path.resolve(__dirname, '../../../server/dist/mcp/server.js');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function run() {
|
|
125
|
+
const projectRoot = process.cwd();
|
|
126
|
+
console.log(`Initializing Waymark in: ${projectRoot}`);
|
|
127
|
+
// Step 1 — Detect project
|
|
128
|
+
const hasPackageJson = fs.existsSync(path.join(projectRoot, 'package.json'));
|
|
129
|
+
const hasGit = fs.existsSync(path.join(projectRoot, '.git'));
|
|
130
|
+
if (!hasPackageJson && !hasGit) {
|
|
131
|
+
console.warn('Warning: No package.json or .git found. Continuing anyway.');
|
|
132
|
+
}
|
|
133
|
+
// Step 2 — Install @shaifulshabuj-waymarks/server (skip if already resolvable or in monorepo)
|
|
134
|
+
let serverBin;
|
|
135
|
+
try {
|
|
136
|
+
serverBin = require.resolve('@shaifulshabuj-waymarks/server/dist/mcp/server.js');
|
|
137
|
+
console.log('✓ @shaifulshabuj-waymarks/server already installed');
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
const monorepoFallback = path.resolve(__dirname, '../../../server/dist/mcp/server.js');
|
|
141
|
+
if (fs.existsSync(monorepoFallback)) {
|
|
142
|
+
serverBin = monorepoFallback;
|
|
143
|
+
console.log('✓ Using local @shaifulshabuj-waymarks/server (monorepo)');
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
console.log('Installing @shaifulshabuj-waymarks/server...');
|
|
147
|
+
const result = (0, child_process_1.spawnSync)('npm', ['install', '--save-dev', '@shaifulshabuj-waymarks/server'], {
|
|
148
|
+
stdio: 'inherit',
|
|
149
|
+
cwd: projectRoot
|
|
150
|
+
});
|
|
151
|
+
if (result.status !== 0) {
|
|
152
|
+
console.error('Failed to install @shaifulshabuj-waymarks/server');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
serverBin = resolveServerBin();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Step 3 — Create waymark.config.json
|
|
159
|
+
const configPath = path.join(projectRoot, 'waymark.config.json');
|
|
160
|
+
if (fs.existsSync(configPath)) {
|
|
161
|
+
const answer = await prompt('waymark.config.json exists. Overwrite? (y/N) ');
|
|
162
|
+
if (answer.toLowerCase() !== 'y') {
|
|
163
|
+
console.log('Keeping existing waymark.config.json');
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + '\n');
|
|
167
|
+
console.log('✓ Created waymark.config.json');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + '\n');
|
|
172
|
+
console.log('✓ Created waymark.config.json');
|
|
173
|
+
}
|
|
174
|
+
// Step 4 — Create/append CLAUDE.md
|
|
175
|
+
const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');
|
|
176
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
177
|
+
const existing = fs.readFileSync(claudeMdPath, 'utf8');
|
|
178
|
+
if (existing.includes(WAYMARK_MARKER)) {
|
|
179
|
+
console.log('✓ CLAUDE.md already has Waymark section');
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
fs.appendFileSync(claudeMdPath, `\n${WAYMARK_MARKER}\n${CLAUDE_MD_CONTENT}`);
|
|
183
|
+
console.log('✓ Appended Waymark section to CLAUDE.md');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
fs.writeFileSync(claudeMdPath, `${WAYMARK_MARKER}\n${CLAUDE_MD_CONTENT}`);
|
|
188
|
+
console.log('✓ Created CLAUDE.md — Claude Code will now use Waymark automatically');
|
|
189
|
+
}
|
|
190
|
+
// Step 5 — Update .gitignore
|
|
191
|
+
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
192
|
+
const gitignoreContent = fs.existsSync(gitignorePath)
|
|
193
|
+
? fs.readFileSync(gitignorePath, 'utf8')
|
|
194
|
+
: '';
|
|
195
|
+
const linesToAdd = ['.waymark/', 'waymark.db', 'data/waymark.db']
|
|
196
|
+
.filter(line => !gitignoreContent.includes(line));
|
|
197
|
+
if (linesToAdd.length > 0) {
|
|
198
|
+
const section = '\n# Waymark\n' + linesToAdd.join('\n') + '\n';
|
|
199
|
+
fs.appendFileSync(gitignorePath, section);
|
|
200
|
+
console.log('✓ Updated .gitignore');
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
console.log('✓ .gitignore already up to date');
|
|
204
|
+
}
|
|
205
|
+
// Step 6 — Register MCP in both Claude configs
|
|
206
|
+
const nodeBin = process.execPath;
|
|
207
|
+
const mcpEntry = {
|
|
208
|
+
command: nodeBin,
|
|
209
|
+
args: [serverBin, '--project-root', projectRoot]
|
|
210
|
+
};
|
|
211
|
+
// Claude Desktop config
|
|
212
|
+
const desktopConfigPath = getClaudeDesktopConfigPath();
|
|
213
|
+
try {
|
|
214
|
+
const desktopDir = path.dirname(desktopConfigPath);
|
|
215
|
+
if (!fs.existsSync(desktopDir))
|
|
216
|
+
fs.mkdirSync(desktopDir, { recursive: true });
|
|
217
|
+
const desktopConfig = fs.existsSync(desktopConfigPath)
|
|
218
|
+
? JSON.parse(fs.readFileSync(desktopConfigPath, 'utf8'))
|
|
219
|
+
: { mcpServers: {} };
|
|
220
|
+
if (!desktopConfig.mcpServers)
|
|
221
|
+
desktopConfig.mcpServers = {};
|
|
222
|
+
if (desktopConfig.mcpServers.waymark) {
|
|
223
|
+
console.log('✓ Claude Desktop MCP entry already exists — skipping');
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
desktopConfig.mcpServers.waymark = mcpEntry;
|
|
227
|
+
fs.writeFileSync(desktopConfigPath, JSON.stringify(desktopConfig, null, 2) + '\n');
|
|
228
|
+
console.log('✓ Registered Waymark MCP server in Claude Desktop config');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
console.warn(`Warning: Could not update Claude Desktop config: ${err.message}`);
|
|
233
|
+
}
|
|
234
|
+
// .mcp.json (Claude Code project-level)
|
|
235
|
+
const mcpJsonPath = path.join(projectRoot, '.mcp.json');
|
|
236
|
+
try {
|
|
237
|
+
const mcpJson = fs.existsSync(mcpJsonPath)
|
|
238
|
+
? JSON.parse(fs.readFileSync(mcpJsonPath, 'utf8'))
|
|
239
|
+
: { mcpServers: {} };
|
|
240
|
+
if (!mcpJson.mcpServers)
|
|
241
|
+
mcpJson.mcpServers = {};
|
|
242
|
+
if (mcpJson.mcpServers.waymark) {
|
|
243
|
+
console.log('✓ .mcp.json Waymark entry already exists — skipping');
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
mcpJson.mcpServers.waymark = { type: 'stdio', ...mcpEntry, cwd: projectRoot };
|
|
247
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpJson, null, 2) + '\n');
|
|
248
|
+
console.log('✓ Created .mcp.json for Claude Code');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
console.warn(`Warning: Could not update .mcp.json: ${err.message}`);
|
|
253
|
+
}
|
|
254
|
+
// Step 7 — Success summary
|
|
255
|
+
console.log('');
|
|
256
|
+
console.log('┌─────────────────────────────────────┐');
|
|
257
|
+
console.log('│ ✅ Waymark initialized │');
|
|
258
|
+
console.log('│ │');
|
|
259
|
+
console.log('│ Files created: │');
|
|
260
|
+
console.log('│ waymark.config.json │');
|
|
261
|
+
console.log('│ CLAUDE.md │');
|
|
262
|
+
console.log('│ │');
|
|
263
|
+
console.log('│ Next steps: │');
|
|
264
|
+
console.log('│ 1. Restart Claude Code │');
|
|
265
|
+
console.log('│ 2. Open this project in Claude │');
|
|
266
|
+
console.log('│ 3. View dashboard: │');
|
|
267
|
+
console.log('│npx @shaifulshabuj-waymarks/cli start│');
|
|
268
|
+
console.log('│ http://localhost:3001 │');
|
|
269
|
+
console.log('│ │');
|
|
270
|
+
console.log('│ Waymark is now always-on in │');
|
|
271
|
+
console.log('│ this project. No manual setup │');
|
|
272
|
+
console.log('│ required per session. │');
|
|
273
|
+
console.log('└─────────────────────────────────────┘');
|
|
274
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.run = run;
|
|
4
|
+
const BASE = 'http://localhost:3001';
|
|
5
|
+
function relativeTime(iso) {
|
|
6
|
+
const diffMs = Date.now() - new Date(iso.replace(' ', 'T') + 'Z').getTime();
|
|
7
|
+
const mins = Math.floor(diffMs / 60000);
|
|
8
|
+
if (mins < 1)
|
|
9
|
+
return 'just now';
|
|
10
|
+
if (mins < 60)
|
|
11
|
+
return `${mins}m ago`;
|
|
12
|
+
const hours = Math.floor(mins / 60);
|
|
13
|
+
if (hours < 24)
|
|
14
|
+
return `${hours}h ago`;
|
|
15
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
16
|
+
}
|
|
17
|
+
function truncate(str, len) {
|
|
18
|
+
if (!str)
|
|
19
|
+
return '—';
|
|
20
|
+
const s = str.split('/').pop() || str;
|
|
21
|
+
return s.length > len ? s.slice(0, len - 1) + '…' : s;
|
|
22
|
+
}
|
|
23
|
+
function pad(str, len) {
|
|
24
|
+
return str.padEnd(len).slice(0, len);
|
|
25
|
+
}
|
|
26
|
+
async function run() {
|
|
27
|
+
const args = process.argv.slice(3);
|
|
28
|
+
const limitIdx = args.indexOf('--limit');
|
|
29
|
+
const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) || 20 : 20;
|
|
30
|
+
const pendingOnly = args.includes('--pending');
|
|
31
|
+
const blockedOnly = args.includes('--blocked');
|
|
32
|
+
let rows;
|
|
33
|
+
try {
|
|
34
|
+
const res = await fetch(`${BASE}/api/actions`);
|
|
35
|
+
if (!res.ok)
|
|
36
|
+
throw new Error('Bad response');
|
|
37
|
+
rows = await res.json();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
console.log('Waymark is not running. Start with: waymark start');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (pendingOnly)
|
|
44
|
+
rows = rows.filter((r) => r.status === 'pending');
|
|
45
|
+
if (blockedOnly)
|
|
46
|
+
rows = rows.filter((r) => r.status === 'blocked');
|
|
47
|
+
rows = rows.slice(0, limit);
|
|
48
|
+
if (rows.length === 0) {
|
|
49
|
+
console.log('No actions found.');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
console.log(pad('Time', 10) + ' ' +
|
|
53
|
+
pad('Tool', 12) + ' ' +
|
|
54
|
+
pad('Path / Command', 40) + ' ' +
|
|
55
|
+
pad('Decision', 10) + ' ' +
|
|
56
|
+
'Status');
|
|
57
|
+
console.log('─'.repeat(86));
|
|
58
|
+
for (const r of rows) {
|
|
59
|
+
const target = r.target_path
|
|
60
|
+
? truncate(r.target_path, 40)
|
|
61
|
+
: truncate(JSON.parse(r.input_payload || '{}').command || '—', 40);
|
|
62
|
+
console.log(pad(relativeTime(r.created_at), 10) + ' ' +
|
|
63
|
+
pad(r.tool_name, 12) + ' ' +
|
|
64
|
+
pad(target, 40) + ' ' +
|
|
65
|
+
pad(r.decision || '—', 10) + ' ' +
|
|
66
|
+
r.status);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.run = run;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
function resolveServerBin(name) {
|
|
41
|
+
const file = name === 'mcp' ? 'mcp/server.js' : 'api/server.js';
|
|
42
|
+
try {
|
|
43
|
+
return require.resolve(`@shaifulshabuj-waymarks/server/dist/${file}`);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return path.resolve(__dirname, `../../../server/dist/${file}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function openBrowser(url) {
|
|
50
|
+
try {
|
|
51
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
52
|
+
: process.platform === 'win32' ? 'start'
|
|
53
|
+
: 'xdg-open';
|
|
54
|
+
(0, child_process_1.execSync)(`${cmd} ${url}`, { stdio: 'ignore' });
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// ignore — browser open is best-effort
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function run() {
|
|
61
|
+
const projectRoot = process.cwd();
|
|
62
|
+
const configPath = path.join(projectRoot, 'waymark.config.json');
|
|
63
|
+
if (!fs.existsSync(configPath)) {
|
|
64
|
+
console.error('waymark.config.json not found. Run waymark init first.');
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const nodeBin = process.execPath;
|
|
68
|
+
const mcpBin = resolveServerBin('mcp');
|
|
69
|
+
const apiBin = resolveServerBin('api');
|
|
70
|
+
const env = { ...process.env, WAYMARK_PROJECT_ROOT: projectRoot };
|
|
71
|
+
console.log('Starting Waymark...');
|
|
72
|
+
const apiProc = (0, child_process_1.spawn)(nodeBin, [apiBin], { env, stdio: 'inherit' });
|
|
73
|
+
const mcpProc = (0, child_process_1.spawn)(nodeBin, [mcpBin, '--project-root', projectRoot], { env, stdio: 'ignore' });
|
|
74
|
+
// Open browser after short delay for server startup
|
|
75
|
+
setTimeout(() => openBrowser('http://localhost:3001'), 1500);
|
|
76
|
+
console.log('');
|
|
77
|
+
console.log('Waymark running');
|
|
78
|
+
console.log('Dashboard: http://localhost:3001');
|
|
79
|
+
console.log('MCP server: active (stdio)');
|
|
80
|
+
console.log('Press Ctrl+C to stop');
|
|
81
|
+
const cleanup = () => {
|
|
82
|
+
apiProc.kill();
|
|
83
|
+
mcpProc.kill();
|
|
84
|
+
process.exit(0);
|
|
85
|
+
};
|
|
86
|
+
process.on('SIGINT', cleanup);
|
|
87
|
+
process.on('SIGTERM', cleanup);
|
|
88
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.run = run;
|
|
4
|
+
const BASE = 'http://localhost:3001';
|
|
5
|
+
async function run() {
|
|
6
|
+
try {
|
|
7
|
+
const [countRes, actionsRes] = await Promise.all([
|
|
8
|
+
fetch(`${BASE}/api/actions?count=true`),
|
|
9
|
+
fetch(`${BASE}/api/actions`)
|
|
10
|
+
]);
|
|
11
|
+
if (!countRes.ok || !actionsRes.ok)
|
|
12
|
+
throw new Error('Bad response');
|
|
13
|
+
const { count: pending } = await countRes.json();
|
|
14
|
+
const actions = await actionsRes.json();
|
|
15
|
+
const total = actions.length;
|
|
16
|
+
console.log('Waymark status');
|
|
17
|
+
console.log(`Dashboard: ${BASE} (running)`);
|
|
18
|
+
console.log(`Pending approvals: ${pending}`);
|
|
19
|
+
console.log(`Total actions logged: ${total}`);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
console.log('Waymark is not running. Start with: waymark start');
|
|
23
|
+
}
|
|
24
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const command = process.argv[2];
|
|
3
|
+
switch (command) {
|
|
4
|
+
case 'init':
|
|
5
|
+
require('./commands/init').run();
|
|
6
|
+
break;
|
|
7
|
+
case 'start':
|
|
8
|
+
require('./commands/start').run();
|
|
9
|
+
break;
|
|
10
|
+
case 'status':
|
|
11
|
+
require('./commands/status').run();
|
|
12
|
+
break;
|
|
13
|
+
case 'logs':
|
|
14
|
+
require('./commands/logs').run();
|
|
15
|
+
break;
|
|
16
|
+
default:
|
|
17
|
+
console.log('Usage: waymark <init|start|status|logs>');
|
|
18
|
+
console.log('');
|
|
19
|
+
console.log('Commands:');
|
|
20
|
+
console.log(' init Set up Waymark in the current project');
|
|
21
|
+
console.log(' start Start the Waymark dashboard and MCP server');
|
|
22
|
+
console.log(' status Show current Waymark status and pending count');
|
|
23
|
+
console.log(' logs Show recent action log');
|
|
24
|
+
process.exit(command ? 1 : 0);
|
|
25
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@shaifulshabuj-waymarks/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Control what AI agents can do in your codebase",
|
|
5
|
+
"author": "Waymark <hello@waymarks.dev>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/waymarks/waymark",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/waymarks/waymark.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/waymarks/waymark/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ai-agents",
|
|
17
|
+
"claude-code",
|
|
18
|
+
"mcp",
|
|
19
|
+
"security",
|
|
20
|
+
"developer-tools",
|
|
21
|
+
"llm",
|
|
22
|
+
"agent-control"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"waymark": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist/**"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@shaifulshabuj-waymarks/server": "0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.11.5",
|
|
38
|
+
"typescript": "^5.3.3"
|
|
39
|
+
}
|
|
40
|
+
}
|