create-urateam 0.1.2 → 0.1.4
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/__tests__/scaffold.test.js +165 -74
- package/dist/__tests__/scaffold.test.js.map +1 -1
- package/dist/index.d.ts +19 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/template/.urateam/README.md +40 -0
- package/template/CLAUDE.md +62 -0
- package/template/README.md +51 -11
- package/template/.github/workflows/ci.yml +0 -20
- /package/template/{.env.example → .urateam/.env.example} +0 -0
- /package/template/{Dockerfile → .urateam/Dockerfile} +0 -0
- /package/template/{docker-compose.yml → .urateam/docker-compose.yml} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { mkdtempSync, rmSync, existsSync, readFileSync } from "fs";
|
|
2
|
+
import { mkdtempSync, rmSync, existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { tmpdir } from "os";
|
|
5
5
|
import { scaffold } from "../index.js";
|
|
6
|
-
describe("scaffold", () => {
|
|
6
|
+
describe("scaffold — sidecar pattern", () => {
|
|
7
7
|
let tempDir;
|
|
8
8
|
beforeEach(() => {
|
|
9
9
|
tempDir = mkdtempSync(join(tmpdir(), "create-urateam-test-"));
|
|
@@ -11,80 +11,171 @@ describe("scaffold", () => {
|
|
|
11
11
|
afterEach(() => {
|
|
12
12
|
rmSync(tempDir, { recursive: true, force: true });
|
|
13
13
|
});
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
repoUrl: "https://github.com/user/repo",
|
|
22
|
-
defaultBranch: "main",
|
|
23
|
-
});
|
|
24
|
-
expect(existsSync(join(projectDir, "package.json"))).toBe(true);
|
|
25
|
-
expect(existsSync(join(projectDir, ".env"))).toBe(true);
|
|
26
|
-
expect(existsSync(join(projectDir, ".env.example"))).toBe(true);
|
|
27
|
-
expect(existsSync(join(projectDir, "docker-compose.yml"))).toBe(true);
|
|
28
|
-
expect(existsSync(join(projectDir, "Dockerfile"))).toBe(true);
|
|
29
|
-
expect(existsSync(join(projectDir, ".gitignore"))).toBe(true);
|
|
30
|
-
expect(existsSync(join(projectDir, "README.md"))).toBe(true);
|
|
14
|
+
const baseOptions = (projectDir, projectName) => ({
|
|
15
|
+
projectDir,
|
|
16
|
+
projectName,
|
|
17
|
+
linearApiKey: "lin_api_test",
|
|
18
|
+
linearTeamId: "team-123",
|
|
19
|
+
repoUrl: "https://github.com/user/repo",
|
|
20
|
+
defaultBranch: "main",
|
|
31
21
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
projectDir,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
projectDir,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
22
|
+
describe("new project (empty target directory)", () => {
|
|
23
|
+
it("creates .urateam/ with all sidecar template files", () => {
|
|
24
|
+
const projectDir = join(tempDir, "my-project");
|
|
25
|
+
scaffold(baseOptions(projectDir, "my-project"));
|
|
26
|
+
expect(existsSync(join(projectDir, ".urateam"))).toBe(true);
|
|
27
|
+
expect(existsSync(join(projectDir, ".urateam", "package.json"))).toBe(true);
|
|
28
|
+
expect(existsSync(join(projectDir, ".urateam", ".env"))).toBe(true);
|
|
29
|
+
expect(existsSync(join(projectDir, ".urateam", ".env.example"))).toBe(true);
|
|
30
|
+
expect(existsSync(join(projectDir, ".urateam", "docker-compose.yml"))).toBe(true);
|
|
31
|
+
expect(existsSync(join(projectDir, ".urateam", "Dockerfile"))).toBe(true);
|
|
32
|
+
expect(existsSync(join(projectDir, ".urateam", "README.md"))).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it("does NOT create a package.json at the project root", () => {
|
|
35
|
+
const projectDir = join(tempDir, "my-project");
|
|
36
|
+
scaffold(baseOptions(projectDir, "my-project"));
|
|
37
|
+
expect(existsSync(join(projectDir, "package.json"))).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it("creates CLAUDE.md at the project root with project name", () => {
|
|
40
|
+
const projectDir = join(tempDir, "cool-agent");
|
|
41
|
+
scaffold(baseOptions(projectDir, "cool-agent"));
|
|
42
|
+
const claudeMdPath = join(projectDir, "CLAUDE.md");
|
|
43
|
+
expect(existsSync(claudeMdPath)).toBe(true);
|
|
44
|
+
const content = readFileSync(claudeMdPath, "utf-8");
|
|
45
|
+
expect(content).toContain("# cool-agent");
|
|
46
|
+
expect(content).not.toContain("{{PROJECT_NAME}}");
|
|
47
|
+
expect(content).toContain("urateam sidecar");
|
|
48
|
+
});
|
|
49
|
+
it("creates .gitignore with .urateam/.env entry", () => {
|
|
50
|
+
const projectDir = join(tempDir, "my-project");
|
|
51
|
+
scaffold(baseOptions(projectDir, "my-project"));
|
|
52
|
+
const gitignorePath = join(projectDir, ".gitignore");
|
|
53
|
+
expect(existsSync(gitignorePath)).toBe(true);
|
|
54
|
+
const content = readFileSync(gitignorePath, "utf-8");
|
|
55
|
+
expect(content).toContain(".urateam/.env");
|
|
56
|
+
expect(content).toContain(".urateam/node_modules/");
|
|
57
|
+
});
|
|
58
|
+
it(".urateam/package.json has sidecar name and @urateam/cli dependency", () => {
|
|
59
|
+
const projectDir = join(tempDir, "cool-agent");
|
|
60
|
+
scaffold(baseOptions(projectDir, "cool-agent"));
|
|
61
|
+
const pkg = JSON.parse(readFileSync(join(projectDir, ".urateam", "package.json"), "utf-8"));
|
|
62
|
+
expect(pkg.name).toBe("cool-agent-urateam");
|
|
63
|
+
expect(pkg.dependencies["@urateam/cli"]).toBeDefined();
|
|
64
|
+
expect(pkg.scripts.dev).toBe("ura dev");
|
|
65
|
+
expect(pkg.scripts.start).toBe("ura start");
|
|
66
|
+
});
|
|
67
|
+
it(".urateam/.env has provided credentials", () => {
|
|
68
|
+
const projectDir = join(tempDir, "my-project");
|
|
69
|
+
scaffold({
|
|
70
|
+
projectDir,
|
|
71
|
+
projectName: "my-project",
|
|
72
|
+
linearApiKey: "lin_api_abc123",
|
|
73
|
+
linearTeamId: "team-xyz",
|
|
74
|
+
repoUrl: "https://github.com/org/mobile-app",
|
|
75
|
+
defaultBranch: "develop",
|
|
76
|
+
});
|
|
77
|
+
const env = readFileSync(join(projectDir, ".urateam", ".env"), "utf-8");
|
|
78
|
+
expect(env).toContain("LINEAR_API_KEY=lin_api_abc123");
|
|
79
|
+
expect(env).toContain("LINEAR_TEAM_ID=team-xyz");
|
|
80
|
+
expect(env).toContain("REPO_URL=https://github.com/org/mobile-app");
|
|
81
|
+
expect(env).toContain("REPO_DEFAULT_BRANCH=develop");
|
|
82
|
+
expect(env).toContain("REPO_TEAM_ID=team-xyz");
|
|
83
|
+
});
|
|
84
|
+
it(".urateam/.env has a random DASHBOARD_PASSWORD", () => {
|
|
85
|
+
const projectDir = join(tempDir, "my-project");
|
|
86
|
+
scaffold(baseOptions(projectDir, "my-project"));
|
|
87
|
+
const env = readFileSync(join(projectDir, ".urateam", ".env"), "utf-8");
|
|
88
|
+
const match = env.match(/DASHBOARD_PASSWORD=([a-f0-9]+)/);
|
|
89
|
+
expect(match).not.toBeNull();
|
|
90
|
+
expect(match[1].length).toBeGreaterThanOrEqual(32);
|
|
91
|
+
});
|
|
92
|
+
it("creates README.md at project root with project name", () => {
|
|
93
|
+
const projectDir = join(tempDir, "my-project");
|
|
94
|
+
scaffold(baseOptions(projectDir, "my-project"));
|
|
95
|
+
const readmePath = join(projectDir, "README.md");
|
|
96
|
+
expect(existsSync(readmePath)).toBe(true);
|
|
97
|
+
const content = readFileSync(readmePath, "utf-8");
|
|
98
|
+
expect(content).toContain("# my-project");
|
|
99
|
+
expect(content).not.toContain("{{PROJECT_NAME}}");
|
|
100
|
+
});
|
|
101
|
+
it(".gitignore template has .env.* wildcard with example exception", () => {
|
|
102
|
+
const projectDir = join(tempDir, "my-project");
|
|
103
|
+
scaffold(baseOptions(projectDir, "my-project"));
|
|
104
|
+
const content = readFileSync(join(projectDir, ".gitignore"), "utf-8");
|
|
105
|
+
expect(content).toContain(".urateam/.env.*");
|
|
106
|
+
expect(content).toContain("!.urateam/.env.example");
|
|
107
|
+
});
|
|
76
108
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
projectDir,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
});
|
|
87
|
-
|
|
109
|
+
describe("existing project (directory with files already)", () => {
|
|
110
|
+
it("preserves existing CLAUDE.md at project root", () => {
|
|
111
|
+
const projectDir = join(tempDir, "existing-project");
|
|
112
|
+
mkdirSync(projectDir, { recursive: true });
|
|
113
|
+
const existingContent = "# My Existing Project\n\nCustom content that should be preserved.\n";
|
|
114
|
+
writeFileSync(join(projectDir, "CLAUDE.md"), existingContent);
|
|
115
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
116
|
+
const finalContent = readFileSync(join(projectDir, "CLAUDE.md"), "utf-8");
|
|
117
|
+
expect(finalContent).toBe(existingContent);
|
|
118
|
+
});
|
|
119
|
+
it("preserves existing README.md at project root", () => {
|
|
120
|
+
const projectDir = join(tempDir, "existing-project");
|
|
121
|
+
mkdirSync(projectDir, { recursive: true });
|
|
122
|
+
const existingContent = "# My App\n\nProduction-ready.\n";
|
|
123
|
+
writeFileSync(join(projectDir, "README.md"), existingContent);
|
|
124
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
125
|
+
const finalContent = readFileSync(join(projectDir, "README.md"), "utf-8");
|
|
126
|
+
expect(finalContent).toBe(existingContent);
|
|
127
|
+
});
|
|
128
|
+
it("treats !.urateam/.env.example as not-yet-ignored (bare entry check)", () => {
|
|
129
|
+
// Regression test: loose substring matching of ".urateam/.env" would
|
|
130
|
+
// false-positive on "!.urateam/.env.example" and skip the append.
|
|
131
|
+
const projectDir = join(tempDir, "existing-project");
|
|
132
|
+
mkdirSync(projectDir, { recursive: true });
|
|
133
|
+
writeFileSync(join(projectDir, ".gitignore"), "node_modules/\n!.urateam/.env.example\n");
|
|
134
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
135
|
+
const content = readFileSync(join(projectDir, ".gitignore"), "utf-8");
|
|
136
|
+
// Should still append the bare .urateam/.env entry
|
|
137
|
+
const lines = content.split("\n").map((l) => l.trim());
|
|
138
|
+
expect(lines).toContain(".urateam/.env");
|
|
139
|
+
});
|
|
140
|
+
it("preserves existing package.json at project root", () => {
|
|
141
|
+
const projectDir = join(tempDir, "existing-project");
|
|
142
|
+
mkdirSync(projectDir, { recursive: true });
|
|
143
|
+
const existingPkg = { name: "my-app", version: "1.0.0", dependencies: { react: "^19.0.0" } };
|
|
144
|
+
writeFileSync(join(projectDir, "package.json"), JSON.stringify(existingPkg, null, 2));
|
|
145
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
146
|
+
const finalPkg = JSON.parse(readFileSync(join(projectDir, "package.json"), "utf-8"));
|
|
147
|
+
expect(finalPkg.name).toBe("my-app");
|
|
148
|
+
expect(finalPkg.dependencies.react).toBe("^19.0.0");
|
|
149
|
+
expect(finalPkg.dependencies["@urateam/cli"]).toBeUndefined();
|
|
150
|
+
});
|
|
151
|
+
it("appends .urateam/.env to existing .gitignore without duplication", () => {
|
|
152
|
+
const projectDir = join(tempDir, "existing-project");
|
|
153
|
+
mkdirSync(projectDir, { recursive: true });
|
|
154
|
+
writeFileSync(join(projectDir, ".gitignore"), "node_modules/\ndist/\n");
|
|
155
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
156
|
+
const content = readFileSync(join(projectDir, ".gitignore"), "utf-8");
|
|
157
|
+
expect(content).toContain("node_modules/");
|
|
158
|
+
expect(content).toContain("dist/");
|
|
159
|
+
expect(content).toContain(".urateam/.env");
|
|
160
|
+
});
|
|
161
|
+
it("does NOT duplicate .urateam/.env entry if already present", () => {
|
|
162
|
+
const projectDir = join(tempDir, "existing-project");
|
|
163
|
+
mkdirSync(projectDir, { recursive: true });
|
|
164
|
+
writeFileSync(join(projectDir, ".gitignore"), "node_modules/\n.urateam/.env\n");
|
|
165
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
166
|
+
const content = readFileSync(join(projectDir, ".gitignore"), "utf-8");
|
|
167
|
+
const matches = content.match(/\.urateam\/\.env/g);
|
|
168
|
+
expect(matches?.length).toBe(1);
|
|
169
|
+
});
|
|
170
|
+
it("still creates .urateam/ sidecar in existing project", () => {
|
|
171
|
+
const projectDir = join(tempDir, "existing-project");
|
|
172
|
+
mkdirSync(projectDir, { recursive: true });
|
|
173
|
+
writeFileSync(join(projectDir, "README.md"), "# My App");
|
|
174
|
+
writeFileSync(join(projectDir, "package.json"), '{"name":"my-app"}');
|
|
175
|
+
scaffold(baseOptions(projectDir, "existing-project"));
|
|
176
|
+
expect(existsSync(join(projectDir, ".urateam", "package.json"))).toBe(true);
|
|
177
|
+
expect(existsSync(join(projectDir, ".urateam", ".env"))).toBe(true);
|
|
178
|
+
});
|
|
88
179
|
});
|
|
89
180
|
});
|
|
90
181
|
//# sourceMappingURL=scaffold.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.test.js","sourceRoot":"","sources":["../../src/__tests__/scaffold.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.test.js","sourceRoot":"","sources":["../../src/__tests__/scaffold.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
export interface ScaffoldOptions {
|
|
3
|
+
/** The project root directory. `.urateam/` will be created inside it. */
|
|
3
4
|
projectDir: string;
|
|
5
|
+
/** Project name — used in CLAUDE.md header and .urateam/package.json. */
|
|
4
6
|
projectName: string;
|
|
5
7
|
linearApiKey: string;
|
|
6
8
|
linearTeamId: string;
|
|
@@ -8,8 +10,23 @@ export interface ScaffoldOptions {
|
|
|
8
10
|
defaultBranch: string;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
|
-
* Scaffold a
|
|
12
|
-
*
|
|
13
|
+
* Scaffold a urateam sidecar into a project directory.
|
|
14
|
+
*
|
|
15
|
+
* Creates:
|
|
16
|
+
* - <projectDir>/.urateam/ — isolated urateam config + deps
|
|
17
|
+
* - package.json — depends on @urateam/cli
|
|
18
|
+
* - .env — Linear keys, webhook secret, etc.
|
|
19
|
+
* - .env.example
|
|
20
|
+
* - Dockerfile
|
|
21
|
+
* - docker-compose.yml
|
|
22
|
+
* - README.md — how to run the sidecar
|
|
23
|
+
* - <projectDir>/CLAUDE.md — project conventions (only if absent)
|
|
24
|
+
* - <projectDir>/README.md — project readme (only if absent)
|
|
25
|
+
* - <projectDir>/.gitignore — ensures .urateam/.env is ignored
|
|
26
|
+
*
|
|
27
|
+
* The project root `package.json` is NOT touched — urateam is a sidecar tool,
|
|
28
|
+
* not a project dependency. Existing `CLAUDE.md` at the project root is
|
|
29
|
+
* preserved (not overwritten).
|
|
13
30
|
*/
|
|
14
31
|
export declare function scaffold(options: ScaffoldOptions): void;
|
|
15
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAiBA,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CA2EvD"}
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { writeFileSync, cpSync, readFileSync, statSync } from "fs";
|
|
3
|
-
import { join, dirname } from "path";
|
|
2
|
+
import { mkdirSync, writeFileSync, cpSync, readFileSync, statSync, existsSync, appendFileSync, } from "fs";
|
|
3
|
+
import { join, dirname, basename } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { randomBytes } from "crypto";
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = dirname(__filename);
|
|
8
8
|
/**
|
|
9
|
-
* Scaffold a
|
|
10
|
-
*
|
|
9
|
+
* Scaffold a urateam sidecar into a project directory.
|
|
10
|
+
*
|
|
11
|
+
* Creates:
|
|
12
|
+
* - <projectDir>/.urateam/ — isolated urateam config + deps
|
|
13
|
+
* - package.json — depends on @urateam/cli
|
|
14
|
+
* - .env — Linear keys, webhook secret, etc.
|
|
15
|
+
* - .env.example
|
|
16
|
+
* - Dockerfile
|
|
17
|
+
* - docker-compose.yml
|
|
18
|
+
* - README.md — how to run the sidecar
|
|
19
|
+
* - <projectDir>/CLAUDE.md — project conventions (only if absent)
|
|
20
|
+
* - <projectDir>/README.md — project readme (only if absent)
|
|
21
|
+
* - <projectDir>/.gitignore — ensures .urateam/.env is ignored
|
|
22
|
+
*
|
|
23
|
+
* The project root `package.json` is NOT touched — urateam is a sidecar tool,
|
|
24
|
+
* not a project dependency. Existing `CLAUDE.md` at the project root is
|
|
25
|
+
* preserved (not overwritten).
|
|
11
26
|
*/
|
|
12
27
|
export function scaffold(options) {
|
|
13
28
|
const { projectDir, projectName, linearApiKey, linearTeamId, repoUrl, defaultBranch } = options;
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
// When running from src/ (tests), template is at ../../template/
|
|
29
|
+
mkdirSync(projectDir, { recursive: true });
|
|
30
|
+
// Locate template directory (supports running from dist/ or src/ during tests)
|
|
17
31
|
let templateDir = join(__dirname, "..", "template");
|
|
18
32
|
if (!statSync(templateDir, { throwIfNoEntry: false })?.isDirectory()) {
|
|
19
33
|
templateDir = join(__dirname, "..", "..", "template");
|
|
20
34
|
}
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
// --- Sidecar files: copy template/.urateam/ → projectDir/.urateam/ (force overwrite) ---
|
|
36
|
+
const urateamDir = join(projectDir, ".urateam");
|
|
37
|
+
cpSync(join(templateDir, ".urateam"), urateamDir, { recursive: true, force: true });
|
|
38
|
+
// Write .urateam/package.json — the sidecar's own package.json
|
|
23
39
|
const pkg = {
|
|
24
|
-
name: projectName
|
|
40
|
+
name: `${projectName}-urateam`,
|
|
25
41
|
private: true,
|
|
26
42
|
type: "module",
|
|
27
43
|
scripts: {
|
|
@@ -29,11 +45,11 @@ export function scaffold(options) {
|
|
|
29
45
|
start: "ura start",
|
|
30
46
|
},
|
|
31
47
|
dependencies: {
|
|
32
|
-
"@urateam/cli": "^0.1.
|
|
48
|
+
"@urateam/cli": "^0.1.4",
|
|
33
49
|
},
|
|
34
50
|
};
|
|
35
|
-
writeFileSync(join(
|
|
36
|
-
// Write .env from provided values
|
|
51
|
+
writeFileSync(join(urateamDir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
52
|
+
// Write .urateam/.env from user-provided values
|
|
37
53
|
const envContent = [
|
|
38
54
|
`LINEAR_API_KEY=${linearApiKey}`,
|
|
39
55
|
`LINEAR_WEBHOOK_SECRET=`,
|
|
@@ -45,17 +61,47 @@ export function scaffold(options) {
|
|
|
45
61
|
`DASHBOARD_USER=admin`,
|
|
46
62
|
`DASHBOARD_PASSWORD=${randomBytes(16).toString("hex")}`,
|
|
47
63
|
].join("\n") + "\n";
|
|
48
|
-
writeFileSync(join(
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
64
|
+
writeFileSync(join(urateamDir, ".env"), envContent);
|
|
65
|
+
// --- Project root files: copy only if absent (don't clobber user files) ---
|
|
66
|
+
// Files with {{PROJECT_NAME}} placeholder get the substitution applied.
|
|
67
|
+
const rootFilesWithPlaceholder = ["CLAUDE.md", "README.md"];
|
|
68
|
+
for (const file of rootFilesWithPlaceholder) {
|
|
69
|
+
const dest = join(projectDir, file);
|
|
70
|
+
if (existsSync(dest))
|
|
71
|
+
continue;
|
|
72
|
+
const src = join(templateDir, file);
|
|
73
|
+
if (!existsSync(src))
|
|
74
|
+
continue;
|
|
75
|
+
const content = readFileSync(src, "utf-8");
|
|
76
|
+
writeFileSync(dest, content.replace(/\{\{PROJECT_NAME\}\}/g, projectName));
|
|
77
|
+
}
|
|
78
|
+
// Ensure .gitignore at project root has the urateam entries
|
|
79
|
+
const gitignorePath = join(projectDir, ".gitignore");
|
|
80
|
+
const gitignoreTemplateSrc = join(templateDir, ".gitignore");
|
|
81
|
+
const templateGitignore = readFileSync(gitignoreTemplateSrc, "utf-8");
|
|
82
|
+
if (!existsSync(gitignorePath)) {
|
|
83
|
+
writeFileSync(gitignorePath, templateGitignore);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const existing = readFileSync(gitignorePath, "utf-8");
|
|
87
|
+
// Check for the bare `.urateam/.env` entry as a standalone line.
|
|
88
|
+
// Loose substring match would false-positive on `!.urateam/.env.example`.
|
|
89
|
+
const hasBareEntry = existing
|
|
90
|
+
.split(/\r?\n/)
|
|
91
|
+
.some((line) => line.trim() === ".urateam/.env");
|
|
92
|
+
if (!hasBareEntry) {
|
|
93
|
+
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
94
|
+
appendFileSync(gitignorePath, separator + templateGitignore);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
53
97
|
}
|
|
54
98
|
// CLI entrypoint — only runs when executed directly (not when imported for testing)
|
|
55
99
|
async function main() {
|
|
56
|
-
const
|
|
57
|
-
if (!
|
|
58
|
-
console.error("Usage: create-urateam <project-name>");
|
|
100
|
+
const arg = process.argv[2];
|
|
101
|
+
if (!arg) {
|
|
102
|
+
console.error("Usage: create-urateam <project-name-or-dot>");
|
|
103
|
+
console.error(" create-urateam my-project # creates new directory");
|
|
104
|
+
console.error(" create-urateam . # adds .urateam/ to current directory");
|
|
59
105
|
process.exit(1);
|
|
60
106
|
}
|
|
61
107
|
const prompts = (await import("prompts")).default;
|
|
@@ -69,7 +115,8 @@ async function main() {
|
|
|
69
115
|
console.error("Cancelled.");
|
|
70
116
|
process.exit(1);
|
|
71
117
|
}
|
|
72
|
-
const projectDir = join(process.cwd(),
|
|
118
|
+
const projectDir = arg === "." ? process.cwd() : join(process.cwd(), arg);
|
|
119
|
+
const projectName = arg === "." ? basename(projectDir) || "my-project" : arg;
|
|
73
120
|
scaffold({
|
|
74
121
|
projectDir,
|
|
75
122
|
projectName,
|
|
@@ -78,11 +125,14 @@ async function main() {
|
|
|
78
125
|
repoUrl: response.repoUrl,
|
|
79
126
|
defaultBranch: response.defaultBranch || "main",
|
|
80
127
|
});
|
|
81
|
-
console.log(`\n
|
|
128
|
+
console.log(`\n urateam sidecar installed in ${projectDir}/.urateam\n`);
|
|
82
129
|
console.log(` Next steps:`);
|
|
83
|
-
|
|
130
|
+
if (arg !== ".")
|
|
131
|
+
console.log(` cd ${arg}`);
|
|
132
|
+
console.log(` cd .urateam`);
|
|
84
133
|
console.log(` pnpm install`);
|
|
85
|
-
console.log(` ura dev
|
|
134
|
+
console.log(` ura dev`);
|
|
135
|
+
console.log(`\n See CLAUDE.md in the project root for agent context.\n`);
|
|
86
136
|
}
|
|
87
137
|
const isEntrypoint = process.argv[1]?.endsWith("create-urateam") ||
|
|
88
138
|
process.argv[1]?.endsWith("index.js");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# urateam sidecar
|
|
2
|
+
|
|
3
|
+
This directory contains the [urateam](https://github.com/JonB32/urateam)
|
|
4
|
+
agent configuration for this project. urateam is a **sidecar** — it runs
|
|
5
|
+
alongside the project repo as an isolated utility and processes Linear issues
|
|
6
|
+
to implement features, fix bugs, and create PRs automatically.
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
1. Fill in `.env` with your Linear API key, webhook secret, team ID, and repo URL
|
|
11
|
+
2. Install dependencies: `pnpm install`
|
|
12
|
+
3. Start the agent: `pnpm dev` (SQLite, local dev) or `pnpm start` (production)
|
|
13
|
+
|
|
14
|
+
## Expose the webhook
|
|
15
|
+
|
|
16
|
+
The agent listens on `http://localhost:3000/webhooks/linear`. To receive
|
|
17
|
+
webhooks from Linear, expose this port via ngrok or a reverse proxy:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
ngrok http 3000
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Configure the ngrok URL as a webhook in Linear settings with the
|
|
24
|
+
`LINEAR_WEBHOOK_SECRET` from your `.env`.
|
|
25
|
+
|
|
26
|
+
## Dashboard
|
|
27
|
+
|
|
28
|
+
The ops dashboard runs on `http://localhost:3001`. Credentials from
|
|
29
|
+
`DASHBOARD_USER` / `DASHBOARD_PASSWORD` in `.env`.
|
|
30
|
+
|
|
31
|
+
## How it works
|
|
32
|
+
|
|
33
|
+
1. Move a Linear issue to the `Todo` state with an appropriate pipeline label
|
|
34
|
+
(e.g., `auto-implement`, `bug`, `quick-fix`, `needs-design`)
|
|
35
|
+
2. The urateam agent picks it up, clones the repo, executes the pipeline stages
|
|
36
|
+
(implement → test → review), and opens a PR
|
|
37
|
+
3. You review the PR in GitHub
|
|
38
|
+
|
|
39
|
+
See the project root `CLAUDE.md` for project-specific conventions that the
|
|
40
|
+
agent reads when implementing features.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
<!-- Describe your project here. This file is read by the urateam agent to understand
|
|
4
|
+
the project's architecture, conventions, and how to implement features. Keep it
|
|
5
|
+
current — a stale CLAUDE.md produces bad agent output. -->
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
<!-- What does this project do? Who is it for? -->
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
<!-- Monorepo layout, key packages, dependencies, deployment model. -->
|
|
14
|
+
|
|
15
|
+
## Tech Stack
|
|
16
|
+
|
|
17
|
+
<!-- Language, frameworks, database, infrastructure. -->
|
|
18
|
+
|
|
19
|
+
## Build Commands
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Install dependencies
|
|
23
|
+
pnpm install
|
|
24
|
+
|
|
25
|
+
# Build
|
|
26
|
+
pnpm build
|
|
27
|
+
|
|
28
|
+
# Test
|
|
29
|
+
pnpm test
|
|
30
|
+
|
|
31
|
+
# Run dev
|
|
32
|
+
pnpm dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Conventions
|
|
36
|
+
|
|
37
|
+
<!-- Coding style, naming, error handling, testing patterns, commit format. -->
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## urateam sidecar
|
|
42
|
+
|
|
43
|
+
This project uses [urateam](https://github.com/JonB32/urateam) — an autonomous
|
|
44
|
+
agentic software delivery framework — as a **sidecar** to process Linear issues
|
|
45
|
+
automatically.
|
|
46
|
+
|
|
47
|
+
Configuration lives in `.urateam/`. urateam is **not** a dependency of this
|
|
48
|
+
project. It runs alongside the project repo as an isolated utility.
|
|
49
|
+
|
|
50
|
+
### Run the agent locally
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd .urateam
|
|
54
|
+
pnpm install
|
|
55
|
+
ura dev # or: ura start (production)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The agent listens for Linear webhooks on port 3000 and serves a dashboard on
|
|
59
|
+
port 3001. Expose via ngrok or similar to receive webhooks from Linear.
|
|
60
|
+
|
|
61
|
+
Move an issue to `Todo` in Linear with the `auto-implement` label and the agent
|
|
62
|
+
will pick it up, create a PR, and notify you for review.
|
package/template/README.md
CHANGED
|
@@ -1,26 +1,66 @@
|
|
|
1
1
|
# {{PROJECT_NAME}}
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- Describe your project here. Replace this section with your project overview. -->
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Getting Started
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
<!-- Node version, pnpm, any system dependencies -->
|
|
10
|
+
|
|
11
|
+
### Installation
|
|
9
12
|
|
|
10
13
|
```bash
|
|
11
|
-
|
|
14
|
+
pnpm install
|
|
12
15
|
```
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
### Development
|
|
15
18
|
|
|
16
19
|
```bash
|
|
17
|
-
|
|
20
|
+
pnpm dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Build
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Test
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm test
|
|
18
33
|
```
|
|
19
34
|
|
|
20
|
-
##
|
|
35
|
+
## Project Structure
|
|
36
|
+
|
|
37
|
+
<!-- Describe your monorepo layout, key packages, or directory organization -->
|
|
21
38
|
|
|
22
|
-
|
|
39
|
+
## Contributing
|
|
23
40
|
|
|
24
|
-
|
|
41
|
+
Contributions are welcome. Please open an issue or pull request.
|
|
42
|
+
|
|
43
|
+
<!-- Link to CONTRIBUTING.md, code of conduct, etc. when you have them -->
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
<!-- e.g., MIT, Apache-2.0, proprietary — update to match your license -->
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## urateam sidecar
|
|
52
|
+
|
|
53
|
+
This project uses [urateam](https://github.com/JonB32/urateam) as a sidecar
|
|
54
|
+
agent for autonomous software delivery. The agent processes Linear issues and
|
|
55
|
+
creates PRs automatically.
|
|
56
|
+
|
|
57
|
+
To run the agent locally:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd .urateam
|
|
61
|
+
pnpm install
|
|
62
|
+
ura dev
|
|
63
|
+
```
|
|
25
64
|
|
|
26
|
-
|
|
65
|
+
See [`.urateam/README.md`](./.urateam/README.md) for setup details and
|
|
66
|
+
[`CLAUDE.md`](./CLAUDE.md) for project conventions read by the agent.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches: [main]
|
|
5
|
-
pull_request:
|
|
6
|
-
branches: [main]
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
test:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
steps:
|
|
12
|
-
- uses: actions/checkout@v4
|
|
13
|
-
- uses: pnpm/action-setup@v4
|
|
14
|
-
- uses: actions/setup-node@v4
|
|
15
|
-
with:
|
|
16
|
-
node-version: "22"
|
|
17
|
-
cache: pnpm
|
|
18
|
-
- run: pnpm install --frozen-lockfile
|
|
19
|
-
- run: pnpm build
|
|
20
|
-
- run: pnpm test
|
|
File without changes
|
|
File without changes
|
|
File without changes
|