@ulysses-ai/create-workspace 0.16.0-beta.1 → 0.17.0-beta.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 +2 -2
- package/lib/init.mjs +19 -0
- package/package.json +1 -1
- package/template/.claude/hooks/session-end.mjs +68 -2
- package/template/.claude/rules/config-review.md.skip +29 -0
- package/template/.claude/rules/forge-operations.md +107 -0
- package/template/.claude/rules/goal-driven-work.md +13 -0
- package/template/.claude/rules/workspace-structure.md +38 -0
- package/template/.claude/scripts/cleanup-work-session.mjs +164 -26
- package/template/.claude/scripts/forges/github.mjs +210 -0
- package/template/.claude/scripts/forges/gitlab.mjs +19 -0
- package/template/.claude/scripts/forges/interface.mjs +113 -0
- package/template/.claude/settings.json +5 -13
- package/template/.claude/skills/complete-work/SKILL.md +67 -37
- package/template/.claude/skills/maintenance/SKILL.md +32 -6
- package/template/.claude/skills/pause-work/SKILL.md +24 -7
- package/template/.claude/skills/workspace-init/SKILL.md +32 -0
- package/template/.claudeignore +3 -0
- package/template/CLAUDE.md.tmpl +1 -0
- package/template/CODEBASE.md.tmpl +13 -0
- package/template/repo-claude.md.tmpl +10 -0
- package/template/workspace.json.tmpl +2 -1
- package/template/.claude/hooks/worktree-create.mjs +0 -53
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: workspace-init
|
|
3
3
|
description: First-time workspace initialization. Clones repos, installs template components, extracts team knowledge from documentation sources and Claude chat history, activates rules, configures user identity. Run once after scaffolding with --init.
|
|
4
|
+
|
|
5
|
+
# scope example (remove # to activate path-scoped loading):
|
|
6
|
+
# scope: repos/my-api/
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Workspace Init
|
|
@@ -117,6 +120,9 @@ Also install these top-level files from the payload:
|
|
|
117
120
|
- **`.claude/settings.json`** — Merge payload settings into existing file. Preserve user-added settings, add missing entries.
|
|
118
121
|
- **`.gitignore`** — Merge: add lines from payload not already present.
|
|
119
122
|
- **`CLAUDE.md`** — Generate from `.workspace-update/CLAUDE.md.tmpl`, substituting `{{project-name}}` with the workspace name. If the existing CLAUDE.md has user-added content beyond the bootstrap template, preserve it.
|
|
123
|
+
- **`CODEBASE.md` (optional)** — Ask: "Generate CODEBASE.md? This produces a lightweight file-tree map that helps Claude navigate the codebase without exhaustive exploration. [Y/n]". If yes: scaffold `CODEBASE.md` from `.workspace-update/CODEBASE.md.tmpl`, substitute `{{project-name}}`, then pre-populate `## Top-level layout` by listing the top-level entries of each `repos/{repo}/` directory using `fs.readdirSync` (Node.js, no network calls). If no: skip — `CODEBASE.md` can always be created manually later by copying and filling the template.
|
|
124
|
+
|
|
125
|
+
**Per-repo CLAUDE.md stubs:** For each repo in `workspace.json`, check if `repos/{repo}/CLAUDE.md` exists. If not, ask "Scaffold a CLAUDE.md for {repo}? [Y/n]". If yes, write a blank stub from `.workspace-update/repo-claude.md.tmpl`, substituting `{{repo-name}}` with the repo name. The stub body is comment text only — no workspace-specific content — and its `## Commands` section is where you will add repo-specific test, lint, and build commands.
|
|
120
126
|
|
|
121
127
|
**Commit:** `git commit -m "feat: install template components from payload"`
|
|
122
128
|
|
|
@@ -255,6 +261,29 @@ If you discovered candidate work items during earlier steps (bugs in braindumps,
|
|
|
255
261
|
|
|
256
262
|
Do NOT batch-create issues automatically — the user should review and prune the list.
|
|
257
263
|
|
|
264
|
+
### Step 12.5: Configure MCP servers
|
|
265
|
+
|
|
266
|
+
MCP (Model Context Protocol) servers extend what Claude can do inside the workspace. The template ships with a Playwright MCP server entry in `.mcp.json` for browser automation and visual testing. Additional servers open up two particularly useful capabilities:
|
|
267
|
+
|
|
268
|
+
- **LSP symbol navigation** — a Language Server Protocol server gives Claude go-to-definition, find-all-references, and call-graph queries without false positives from text search. The right server depends on your language stack:
|
|
269
|
+
- TypeScript / JavaScript: `typescript-language-server` (via `npx typescript-language-server --stdio`)
|
|
270
|
+
- Python: `pylsp` (via `pip install python-lsp-server`)
|
|
271
|
+
- Go, Rust, Java, and others: consult your language's LSP documentation.
|
|
272
|
+
- **Internal tool access** — if your team has internal APIs, databases, or services, an MCP server can expose them as tools Claude can call directly. The shape of an `mcpServers` entry in `.mcp.json`:
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"mcpServers": {
|
|
277
|
+
"my-lsp": {
|
|
278
|
+
"command": "npx",
|
|
279
|
+
"args": ["typescript-language-server", "--stdio"]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**This step is guidance only.** The right LSP server depends on your language; the right internal-tool server depends on what your team builds. Configure `.mcp.json` after init when you know what you need — there is no pressure to choose now. The Playwright entry already present in `.mcp.json` satisfies the template's audit assertion; additional servers are additive.
|
|
286
|
+
|
|
258
287
|
### Step 13: Configure user identity
|
|
259
288
|
|
|
260
289
|
Ask: "What name should be used for your user-scoped context? [{system-username}]"
|
|
@@ -418,3 +447,6 @@ This session is done. Start a fresh Claude Code session and run /start-work to b
|
|
|
418
447
|
- Documentation sources are first-class — always ask, always confirm access, always report failures
|
|
419
448
|
- Chat history scanning uses a manifest to survive auto-compaction
|
|
420
449
|
- Existing worktrees are formalized with session markers, trackers, and linked chat history
|
|
450
|
+
- **Subdirectory launch:** Once initialized, `claude` can be launched from `work-sessions/{name}/workspace/repos/{repo}/` instead of the workspace root. Claude walks up the filesystem loading every `CLAUDE.md` it finds, so starting from inside a project worktree loads both the per-repo conventions and the workspace conventions automatically. This is useful for repo-focused tasks — no configuration change needed, just a different launch point.
|
|
451
|
+
- **Skills are on-demand, not pre-loaded:** Skills are invoked explicitly by name (`/skill-name`) when needed; they are not loaded at session start. The `.skip` mechanism in `.claude/rules/` provides the analogous progressive-disclosure pattern for rules — a `.md.skip` file is present but inactive; rename it to `.md` to activate, rename it back to deactivate. Step 6 of this skill walks through the activation choices.
|
|
452
|
+
- **`scope:` for path-scoped skills:** The `scope:` frontmatter field (shown as a commented-out example at the top of this file) restricts a skill so it activates only when the working directory is inside the declared path. Removing the `#` prefix from the example line turns this skill into a path-scoped skill — useful when you want a repo-specific skill available only from inside that repo's worktree.
|
package/template/CLAUDE.md.tmpl
CHANGED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// WorktreeCreate hook — scan for stale worktrees across project repos and
|
|
3
|
-
// flag them. Project worktrees live inside work-sessions/{name}/workspace/repos/
|
|
4
|
-
// in the new layout. The scan walks each project repo's worktree admin list
|
|
5
|
-
// rather than a filesystem pattern, so it keeps working regardless of where
|
|
6
|
-
// worktrees are physically located.
|
|
7
|
-
import { readdirSync, existsSync } from 'fs';
|
|
8
|
-
import { join, basename } from 'path';
|
|
9
|
-
import { execSync } from 'child_process';
|
|
10
|
-
import { getWorkspaceRoot, respond } from './_utils.mjs';
|
|
11
|
-
|
|
12
|
-
const root = getWorkspaceRoot(import.meta.url);
|
|
13
|
-
const reposDir = join(root, 'repos');
|
|
14
|
-
const stale = [];
|
|
15
|
-
|
|
16
|
-
if (!existsSync(reposDir)) {
|
|
17
|
-
respond();
|
|
18
|
-
process.exit(0);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
for (const entry of readdirSync(reposDir)) {
|
|
22
|
-
const repoPath = join(reposDir, entry);
|
|
23
|
-
if (!existsSync(join(repoPath, '.git'))) continue;
|
|
24
|
-
|
|
25
|
-
let worktreeOutput;
|
|
26
|
-
try {
|
|
27
|
-
worktreeOutput = execSync('git worktree list', { cwd: repoPath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
28
|
-
} catch { continue; }
|
|
29
|
-
|
|
30
|
-
for (const line of worktreeOutput.trim().split('\n')) {
|
|
31
|
-
const parts = line.trim().split(/\s+/);
|
|
32
|
-
const wtPath = parts[0];
|
|
33
|
-
if (!wtPath || wtPath === repoPath) continue;
|
|
34
|
-
if (!existsSync(wtPath)) continue;
|
|
35
|
-
|
|
36
|
-
const branchMatch = line.match(/\[(.+?)\]/);
|
|
37
|
-
const branch = branchMatch ? branchMatch[1] : 'unknown';
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
const lastCommit = execSync('git log -1 --format=%ci', { cwd: wtPath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
41
|
-
const daysAgo = Math.floor((Date.now() - new Date(lastCommit).getTime()) / 86400000);
|
|
42
|
-
if (daysAgo > 3) {
|
|
43
|
-
stale.push(`- ${basename(wtPath)} (${branch}): no commits in ${daysAgo} days`);
|
|
44
|
-
}
|
|
45
|
-
} catch {}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (stale.length > 0) {
|
|
50
|
-
respond(`Stale worktrees found:\n${stale.join('\n')}\n\nConsider cleaning up with: git worktree remove {path}`);
|
|
51
|
-
} else {
|
|
52
|
-
respond();
|
|
53
|
-
}
|