vibe-coding-master 0.0.1 → 0.0.3
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 +25 -1
- package/dist/backend/adapters/git-adapter.js +34 -4
- package/dist/backend/services/project-service.js +15 -2
- package/dist/main.js +17 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Current V1 capabilities:
|
|
|
40
40
|
|
|
41
41
|
## Requirements
|
|
42
42
|
|
|
43
|
-
- Node.js 20+.
|
|
43
|
+
- Node.js 20 LTS or 22+.
|
|
44
44
|
- npm.
|
|
45
45
|
- Git.
|
|
46
46
|
- Claude Code installed and available as `claude` in the runtime environment.
|
|
@@ -52,6 +52,22 @@ python3 make g++ git bash
|
|
|
52
52
|
|
|
53
53
|
## Install
|
|
54
54
|
|
|
55
|
+
From npm:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g vibe-coding-master
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then start the packaged app:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
vcm
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The published package also installs `vcmctl`, which Claude Code role sessions use internally for VCM message bus commands.
|
|
68
|
+
|
|
69
|
+
From source:
|
|
70
|
+
|
|
55
71
|
```bash
|
|
56
72
|
npm install
|
|
57
73
|
```
|
|
@@ -91,6 +107,12 @@ Then open:
|
|
|
91
107
|
http://127.0.0.1:4173/
|
|
92
108
|
```
|
|
93
109
|
|
|
110
|
+
If installed globally from npm, `vcm` runs the production-style app and serves the GUI from the backend port:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
http://127.0.0.1:4173/
|
|
114
|
+
```
|
|
115
|
+
|
|
94
116
|
## Run In VS Code Dev Containers
|
|
95
117
|
|
|
96
118
|
VCM works well inside a VS Code `devContainer` as long as VCM, Claude Code, and the target repository are all inside the same container filesystem.
|
|
@@ -125,6 +147,8 @@ Important container notes:
|
|
|
125
147
|
- Install Claude Code inside the container, or make the `claude` command available in the container PATH.
|
|
126
148
|
- Make sure Claude Code authentication works inside the container.
|
|
127
149
|
- Make sure the container has network access to Claude services.
|
|
150
|
+
- Use the path as seen from inside the container, for example `/workspace`.
|
|
151
|
+
- If Git still reports dubious ownership for the mounted repository, run inside the container: `git config --global --add safe.directory /workspace`.
|
|
128
152
|
- Keep the user project, `.vcm`, and `.ai/handoffs` on the same mounted workspace so paths are consistent.
|
|
129
153
|
- Treat the container as the sandbox boundary, especially when using relaxed Claude Code permission modes.
|
|
130
154
|
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
1
2
|
import { VcmError } from "../errors.js";
|
|
2
3
|
export function createGitAdapter(runner) {
|
|
3
4
|
return {
|
|
5
|
+
async checkRepo(repoRoot) {
|
|
6
|
+
const result = await runGit(runner, repoRoot, ["rev-parse", "--is-inside-work-tree"]);
|
|
7
|
+
return {
|
|
8
|
+
isRepo: result.exitCode === 0 && result.stdout.trim() === "true",
|
|
9
|
+
hint: result.exitCode === 0 ? undefined : formatGitHint(result.stderr)
|
|
10
|
+
};
|
|
11
|
+
},
|
|
4
12
|
async isRepo(repoRoot) {
|
|
5
|
-
|
|
6
|
-
return result.exitCode === 0 && result.stdout.trim() === "true";
|
|
13
|
+
return (await this.checkRepo(repoRoot)).isRepo;
|
|
7
14
|
},
|
|
8
15
|
async getCurrentBranch(repoRoot) {
|
|
9
|
-
const result = await runner
|
|
16
|
+
const result = await runGit(runner, repoRoot, ["branch", "--show-current"]);
|
|
10
17
|
if (result.exitCode !== 0) {
|
|
11
18
|
throw new VcmError({
|
|
12
19
|
code: "GIT_ERROR",
|
|
@@ -18,7 +25,7 @@ export function createGitAdapter(runner) {
|
|
|
18
25
|
return result.stdout.trim() || "detached";
|
|
19
26
|
},
|
|
20
27
|
async isDirty(repoRoot) {
|
|
21
|
-
const result = await runner
|
|
28
|
+
const result = await runGit(runner, repoRoot, ["status", "--porcelain"]);
|
|
22
29
|
if (result.exitCode !== 0) {
|
|
23
30
|
throw new VcmError({
|
|
24
31
|
code: "GIT_ERROR",
|
|
@@ -31,3 +38,26 @@ export function createGitAdapter(runner) {
|
|
|
31
38
|
}
|
|
32
39
|
};
|
|
33
40
|
}
|
|
41
|
+
async function runGit(runner, repoRoot, args) {
|
|
42
|
+
return runner.run("git", [...await buildSafeDirectoryArgs(repoRoot), ...args], { cwd: repoRoot });
|
|
43
|
+
}
|
|
44
|
+
async function buildSafeDirectoryArgs(repoRoot) {
|
|
45
|
+
const safeDirs = new Set([repoRoot]);
|
|
46
|
+
try {
|
|
47
|
+
safeDirs.add(await fs.realpath(repoRoot));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// The main Git command will return the actionable path error.
|
|
51
|
+
}
|
|
52
|
+
return [...safeDirs].flatMap((safeDir) => ["-c", `safe.directory=${safeDir}`]);
|
|
53
|
+
}
|
|
54
|
+
function formatGitHint(stderr) {
|
|
55
|
+
const hint = stderr.trim();
|
|
56
|
+
if (!hint) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
if (hint.includes("detected dubious ownership")) {
|
|
60
|
+
return `${hint} If this is a devContainer mount, run inside the container: git config --global --add safe.directory <repo-path>`;
|
|
61
|
+
}
|
|
62
|
+
return hint;
|
|
63
|
+
}
|
|
@@ -5,11 +5,24 @@ export function createProjectService(deps) {
|
|
|
5
5
|
let currentProject = null;
|
|
6
6
|
return {
|
|
7
7
|
async connectProject(input) {
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const requestedPath = input.repoPath.trim();
|
|
9
|
+
const repoRoot = path.resolve(requestedPath);
|
|
10
|
+
if (!requestedPath || !(await deps.fs.pathExists(repoRoot))) {
|
|
10
11
|
throw new VcmError({
|
|
11
12
|
code: "INVALID_REPO",
|
|
12
13
|
message: "Selected path is not a Git repository.",
|
|
14
|
+
hint: requestedPath
|
|
15
|
+
? `Path does not exist inside the VCM runtime: ${repoRoot}`
|
|
16
|
+
: "Repository path cannot be empty.",
|
|
17
|
+
statusCode: 400
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const repoCheck = await deps.git.checkRepo(repoRoot);
|
|
21
|
+
if (!repoCheck.isRepo) {
|
|
22
|
+
throw new VcmError({
|
|
23
|
+
code: "INVALID_REPO",
|
|
24
|
+
message: "Selected path is not a Git repository.",
|
|
25
|
+
hint: repoCheck.hint,
|
|
13
26
|
statusCode: 400
|
|
14
27
|
});
|
|
15
28
|
}
|
package/dist/main.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { createServer as createViteDevServer } from "vite";
|
|
4
5
|
import { DEFAULT_BACKEND_PORT, DEFAULT_FRONTEND_PORT } from "./shared/constants.js";
|
|
5
6
|
import { getDefaultStaticDir, startServer } from "./backend/server.js";
|
|
6
7
|
export function parseMainArgs(argv) {
|
|
@@ -33,6 +34,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
33
34
|
});
|
|
34
35
|
let vite;
|
|
35
36
|
if (options.dev) {
|
|
37
|
+
const { createServer: createViteDevServer } = await import("vite");
|
|
36
38
|
vite = await createViteDevServer({
|
|
37
39
|
server: {
|
|
38
40
|
host,
|
|
@@ -58,6 +60,19 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
58
60
|
process.exit(0);
|
|
59
61
|
});
|
|
60
62
|
}
|
|
61
|
-
|
|
63
|
+
function isMainModule() {
|
|
64
|
+
const argvPath = process.argv[1];
|
|
65
|
+
if (!argvPath) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const modulePath = fileURLToPath(import.meta.url);
|
|
69
|
+
try {
|
|
70
|
+
return fs.realpathSync(argvPath) === fs.realpathSync(modulePath);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return path.resolve(argvPath) === modulePath;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (isMainModule()) {
|
|
62
77
|
void main();
|
|
63
78
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibe-coding-master",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Local GUI session cockpit for Claude Code role sessions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"vcmctl": "dist/cli/vcmctl.js"
|
|
16
16
|
},
|
|
17
17
|
"engines": {
|
|
18
|
-
"node": ">=
|
|
18
|
+
"node": "^20.0.0 || >=22.0.0"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"e2e": "playwright test"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@fastify/static": "^
|
|
36
|
+
"@fastify/static": "^9.1.3",
|
|
37
37
|
"@xterm/addon-fit": "^0.10.0",
|
|
38
38
|
"@xterm/addon-web-links": "^0.11.0",
|
|
39
39
|
"@xterm/xterm": "^5.5.0",
|