@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.
@@ -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.
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ dist/
3
+ .build/
@@ -14,6 +14,7 @@ This is a claude-workspace. All conventions are defined in .claude/rules/.
14
14
  @local-only-template-freshness.md
15
15
 
16
16
  ## Team Knowledge
17
+ @CODEBASE.md
17
18
  @workspace-context/canonical.md
18
19
  @workspace-context/index.md
19
20
 
@@ -0,0 +1,13 @@
1
+ # {{project-name}} Codebase Map
2
+
3
+ ## Top-level layout
4
+ <!-- fill in -->
5
+
6
+ ## Key entry points
7
+ <!-- fill in -->
8
+
9
+ ## Conventions
10
+ <!-- fill in -->
11
+
12
+ ## External dependencies
13
+ <!-- fill in -->
@@ -0,0 +1,10 @@
1
+ # {{repo-name}}
2
+
3
+ ## Purpose
4
+ <!-- fill in -->
5
+
6
+ ## Conventions
7
+ <!-- fill in -->
8
+
9
+ ## Commands
10
+ <!-- fill in: test, lint, build commands for this repo -->
@@ -11,7 +11,8 @@
11
11
  "subagentContextMaxBytes": 10240,
12
12
  "greeting": "Welcome back to {{project-name}}.",
13
13
  "releaseMode": "per-repo",
14
- "tracker": null
14
+ "tracker": null,
15
+ "forge": { "type": "github" }
15
16
  },
16
17
  "repos": {}
17
18
  }
@@ -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
- }