codewalk 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.
Files changed (37) hide show
  1. package/bin/codewalk.js +2 -0
  2. package/dist/commands/init.d.ts +5 -0
  3. package/dist/commands/init.d.ts.map +1 -0
  4. package/dist/commands/init.js +163 -0
  5. package/dist/commands/visualize.d.ts +5 -0
  6. package/dist/commands/visualize.d.ts.map +1 -0
  7. package/dist/commands/visualize.js +79 -0
  8. package/dist/highlights-eq9cgrbb.scm +604 -0
  9. package/dist/highlights-ghv9g403.scm +205 -0
  10. package/dist/highlights-hk7bwhj4.scm +284 -0
  11. package/dist/highlights-r812a2qc.scm +150 -0
  12. package/dist/highlights-x6tmsnaa.scm +115 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +21435 -0
  16. package/dist/injections-73j83es3.scm +27 -0
  17. package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  18. package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
  19. package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  20. package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  21. package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
  22. package/dist/tui/app.d.ts +13 -0
  23. package/dist/tui/app.d.ts.map +1 -0
  24. package/dist/tui/app.js +11 -0
  25. package/dist/tui/tree-view.d.ts +24 -0
  26. package/dist/tui/tree-view.d.ts.map +1 -0
  27. package/dist/tui/tree-view.js +274 -0
  28. package/dist/types/codewalker.d.ts +15 -0
  29. package/dist/types/codewalker.d.ts.map +1 -0
  30. package/dist/types/codewalker.js +1 -0
  31. package/dist/utils/git.d.ts +24 -0
  32. package/dist/utils/git.d.ts.map +1 -0
  33. package/dist/utils/git.js +132 -0
  34. package/dist/utils/tracking.d.ts +23 -0
  35. package/dist/utils/tracking.d.ts.map +1 -0
  36. package/dist/utils/tracking.js +85 -0
  37. package/package.json +41 -0
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ import '../dist/index.js';
@@ -0,0 +1,5 @@
1
+ export interface InitOptions {
2
+ cwd: string;
3
+ }
4
+ export declare function initCommand(options: InitOptions): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAmHA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDrE"}
@@ -0,0 +1,163 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import pc from 'picocolors';
4
+ const SKILL_TEMPLATE = `# Code Walker
5
+
6
+ You are Code Walker, an AI programming assistant built on top of Claude Code.
7
+
8
+ Your purpose is to give the user more visibility into the changes you are making.
9
+
10
+ The current functionality you follow is to make changes, asking for permission if needed as you go, and then you provide a brief summary of the changes made after you're done.
11
+
12
+ In addition to your normal summary, you should also keep track of what you changed in a structured file.
13
+
14
+ The purpose of the file is to walk the user through the code changes step-by-step so that they can understand the code changes you made, why you made them, and how they relate to other changes you made during that task. If the user follows up with further instructions or changes, you should update the file to track that. A full walkthrough can be found below.
15
+
16
+ User prompts are surrounded by \`<USER>\` tags, your code changes are surrounded by \`<ASSISTANT>\` tags, example tracking files are surrounded by \`<TRACK>\` tags, and notes are surrounded in \`<NOTE>\` tags.
17
+
18
+ ## Tracking File Schema
19
+
20
+ \`\`\`typescript
21
+ type Changeset = {
22
+ // Schema version for forward compatibility
23
+ version: number;
24
+
25
+ // Git commit SHA this changeset describes
26
+ commit: string;
27
+
28
+ // Who made the changes (human name, "claude", etc.)
29
+ author: string;
30
+
31
+ // List of logical changes, each with its own reasoning
32
+ changes: Change[];
33
+ };
34
+
35
+ type Change = {
36
+ // Human-readable explanation of why this change was made.
37
+ // Should explain the intent, not just describe what changed.
38
+ reasoning: string;
39
+
40
+ // Files affected by this logical change
41
+ files: FileChange[];
42
+ };
43
+
44
+ type FileChange = {
45
+ // Path to the file, relative to repo root
46
+ path: string;
47
+
48
+ // Which hunks from \`git show <commit>\` belong to this change.
49
+ // 1-indexed, in order of appearance in the diff.
50
+ // Example: [1, 3] means the first and third hunks in this file's diff.
51
+ hunks: number[];
52
+ };
53
+ \`\`\`
54
+
55
+ ## Git Commands Reference
56
+
57
+ - Get current commit hash: \`git rev-parse --short HEAD\`
58
+ - Get commit author: \`git log -1 --format="%an"\`
59
+ - View commit diff with hunks: \`git show <commit> --format=""\`
60
+ - List files changed: \`git show <commit> --name-only --format=""\`
61
+
62
+ Hunks are numbered 1, 2, 3... in order of appearance. Each \`@@\` line in the diff starts a new hunk.
63
+
64
+ ## Handling Refinements
65
+
66
+ If the user requests changes to something you just did (e.g., "use different colors", "rename that function"):
67
+
68
+ 1. If it's part of the same logical task, amend the commit: \`git add -A && git commit --amend --no-edit\`
69
+ 2. Update the existing tracking file to reflect the final state
70
+ 3. The reasoning should describe the final result, not the iteration history
71
+
72
+ If it's a distinct new task, create a new commit and new tracking file.
73
+
74
+ ## Instructions
75
+
76
+ 1. Before committing, check if a git repo exists with \`git status\`. Only run \`git init\` if there isn't one.
77
+ 2. After completing a task, commit your changes and automatically create a tracking file at \`.codewalker/<commit-hash>.json\`
78
+ 3. Group hunks by their logical purpose—one reasoning per logical change, even if it spans multiple hunks or multiple files. If a single user request results in changes across several files, those should typically be one change with one reasoning, not separate changes per file.
79
+ 4. Write reasoning that explains *why*, not just *what* (the diff already shows what)
80
+ 5. If a follow-up request refines previous work, amend the commit and update the tracking file
81
+ 6. If a follow-up request is a new task, create a new commit and new tracking file
82
+ 7. After writing the tracking file, validate it with: \`python3 -c "import json; json.load(open('.codewalker/<commit-hash>.json'))"\`
83
+
84
+ Do not wait for the user to ask for the tracking file—create it automatically as part of finishing each task.
85
+
86
+ **Important:** Always complete the tracking step after every task, even in long conversations with multiple tasks. Do not skip this step regardless of conversation length or number of previous tasks.
87
+ `;
88
+ const CLAUDE_MD_CONTENT = `# Code Walker
89
+
90
+ **CRITICAL REQUIREMENT**: You MUST create git commits for your changes AND create tracking files after EVERY task. No exceptions.
91
+
92
+ ## Workflow (MANDATORY):
93
+ 1. Make your code changes using Write/Edit tools
94
+ 2. **COMMIT the changes**: \`git add -A && git commit -m "descriptive message"\`
95
+ 3. Get the commit hash: \`git rev-parse --short HEAD\`
96
+ 4. **IMMEDIATELY** create \`.codewalker/<commit-hash>.json\` with the tracking data
97
+ 5. Commit the tracking file: \`git add .codewalker/<hash>.json && git commit -m "Add tracking file for <hash>"\`
98
+ 6. Only THEN respond to the user
99
+
100
+ **DO NOT** skip commits. **DO NOT** respond to the user until both the code commit AND tracking file commit are done.
101
+
102
+ See \`.claude/skills/codewalker.md\` for the complete schema and examples.
103
+ `;
104
+ async function fileExists(filePath) {
105
+ try {
106
+ await fs.access(filePath);
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ export async function initCommand(options) {
114
+ const { cwd } = options;
115
+ console.log(pc.bold('Initializing CodeWalker...\n'));
116
+ // 1. Create .claude/skills directory
117
+ const skillsDir = path.join(cwd, '.claude', 'skills');
118
+ await fs.mkdir(skillsDir, { recursive: true });
119
+ // 2. Create skill file (idempotent)
120
+ const skillPath = path.join(skillsDir, 'codewalker.md');
121
+ const skillExists = await fileExists(skillPath);
122
+ if (!skillExists) {
123
+ await fs.writeFile(skillPath, SKILL_TEMPLATE);
124
+ console.log(pc.green('✓') + ' Created .claude/skills/codewalker.md');
125
+ }
126
+ else {
127
+ console.log(pc.yellow('○') + ' .claude/skills/codewalker.md already exists, skipping');
128
+ }
129
+ // 3. Update CLAUDE.md (idempotent)
130
+ const claudePath = path.join(cwd, 'CLAUDE.md');
131
+ let claudeContent = '';
132
+ try {
133
+ claudeContent = await fs.readFile(claudePath, 'utf-8');
134
+ }
135
+ catch {
136
+ // File doesn't exist, will create
137
+ }
138
+ if (!claudeContent.includes('.claude/skills/codewalker.md')) {
139
+ const newContent = claudeContent
140
+ ? claudeContent + '\n\n' + CLAUDE_MD_CONTENT
141
+ : CLAUDE_MD_CONTENT;
142
+ await fs.writeFile(claudePath, newContent);
143
+ console.log(pc.green('✓') + ' Updated CLAUDE.md with CodeWalker instructions');
144
+ }
145
+ else {
146
+ console.log(pc.yellow('○') + ' CLAUDE.md already references CodeWalker, skipping');
147
+ }
148
+ // 4. Create .codewalker directory
149
+ const codewalkerDir = path.join(cwd, '.codewalker');
150
+ const codewalkerExists = await fileExists(codewalkerDir);
151
+ await fs.mkdir(codewalkerDir, { recursive: true });
152
+ if (!codewalkerExists) {
153
+ console.log(pc.green('✓') + ' Created .codewalker/ directory');
154
+ }
155
+ else {
156
+ console.log(pc.yellow('○') + ' .codewalker/ directory already exists');
157
+ }
158
+ console.log(pc.bold('\nCodeWalker initialized successfully!'));
159
+ console.log('\nNext steps:');
160
+ console.log(' 1. Start Claude Code in this directory');
161
+ console.log(' 2. Make changes - Claude will automatically track them');
162
+ console.log(' 3. Run ' + pc.cyan('codewalker visualize') + ' to browse changes');
163
+ }
@@ -0,0 +1,5 @@
1
+ export interface VisualizeOptions {
2
+ cwd: string;
3
+ }
4
+ export declare function visualizeCommand(options: VisualizeOptions): Promise<void>;
5
+ //# sourceMappingURL=visualize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualize.d.ts","sourceRoot":"","sources":["../../src/commands/visualize.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2F/E"}
@@ -0,0 +1,79 @@
1
+ import pc from 'picocolors';
2
+ import { createCliRenderer } from '@opentui/core';
3
+ import { getCurrentBranch, getCommitList, isGitRepo } from '../utils/git.js';
4
+ import { loadTrackingFiles, getTrackedCommits, aggregateByReasoning } from '../utils/tracking.js';
5
+ import { createAppState } from '../tui/app.js';
6
+ import { TreeView } from '../tui/tree-view.js';
7
+ export async function visualizeCommand(options) {
8
+ const { cwd } = options;
9
+ // Check if in git repo
10
+ if (!isGitRepo(cwd)) {
11
+ console.error(pc.red('Error: Not a git repository'));
12
+ process.exit(1);
13
+ }
14
+ // Load data
15
+ console.log(pc.dim('Loading tracking data...'));
16
+ const branch = getCurrentBranch(cwd);
17
+ const commits = getCommitList(cwd);
18
+ const allTrackedCommits = await loadTrackingFiles(cwd, commits);
19
+ const trackedCommits = getTrackedCommits(allTrackedCommits);
20
+ if (trackedCommits.length === 0) {
21
+ console.log(pc.yellow('No tracked commits found in .codewalker/'));
22
+ console.log(pc.dim('Run some tasks with Claude Code to generate tracking data.'));
23
+ return;
24
+ }
25
+ console.log(pc.dim('Aggregating changes by reasoning...'));
26
+ // Aggregate changes by reasoning (like the PR "By Reasoning" view)
27
+ const reasoningGroups = aggregateByReasoning(cwd, trackedCommits);
28
+ if (reasoningGroups.length === 0) {
29
+ console.log(pc.yellow('No changes with diffs found.'));
30
+ return;
31
+ }
32
+ // Create OpenTUI renderer
33
+ console.log(pc.dim('Starting visualizer...'));
34
+ const renderer = await createCliRenderer({
35
+ exitOnCtrlC: true,
36
+ useAlternateScreen: true,
37
+ useMouse: true,
38
+ backgroundColor: '#0f0f1a',
39
+ });
40
+ // Create app state
41
+ const state = createAppState(branch, reasoningGroups);
42
+ // Create tree view
43
+ const treeView = new TreeView(renderer, state);
44
+ // Handle keyboard input
45
+ renderer.keyInput.on('keypress', (event) => {
46
+ const key = event.name;
47
+ switch (key) {
48
+ case 'q':
49
+ treeView.destroy();
50
+ renderer.destroy();
51
+ process.exit(0);
52
+ break;
53
+ case 'j':
54
+ case 'ArrowDown':
55
+ treeView.moveSelection(1);
56
+ break;
57
+ case 'k':
58
+ case 'ArrowUp':
59
+ treeView.moveSelection(-1);
60
+ break;
61
+ case 'Enter':
62
+ case ' ':
63
+ treeView.toggleExpand();
64
+ break;
65
+ case 'g':
66
+ // Go to top
67
+ state.selectedIndex = 0;
68
+ treeView.refresh();
69
+ break;
70
+ case 'G':
71
+ // Go to bottom
72
+ state.selectedIndex = Math.max(0, treeView.getItemCount() - 1);
73
+ treeView.refresh();
74
+ break;
75
+ }
76
+ });
77
+ // Start rendering
78
+ renderer.start();
79
+ }