- Alias uses absolute path (path.resolve) for correct Vite import resolution
- [nexus] comment marks the change for rebase visibility
- Original OnboardingWizard.tsx and App.tsx remain unmodified
- Add bootstrapNexusAgents function with health-check poll (max 30s)
- Create workspace (company) then PM agent (role:ceo) and Engineer agent
- Idempotent: skips if workspace already exists
- Bootstrap runs concurrently before runCommand starts server
- Failures are warnings, not errors
- [nexus] comments on all new lines
- Single-step wizard: root directory input only (no company name, mission, or first task)
- Creates workspace named VOCAB.appName (Nexus)
- Creates PM agent (role: ceo, for elevated permissions) + Engineer agent
- Navigates to dashboard after completion, not issue detail
- Preserves resolveRouteOnboardingOptions wizard-show detection logic
- Exports OnboardingWizard to match named import in App.tsx
- Original OnboardingWizard.tsx untouched for upstream rebase compatibility
- Add AGENT_TEMPLATES const with Project Manager (role:pm) and Engineer options
- Add template selector section between Ask PM button and advanced config link
- handleTemplateSelect navigates to /agents/new pre-filled with template values
- No hire language present in dialog
- [nexus] marked all new/changed lines
- Add pm and engineer entries to DEFAULT_AGENT_BUNDLE_FILES
- Update resolveDefaultAgentInstructionsBundleRole to handle pm and engineer roles
- DefaultAgentBundleRole type auto-includes new keys via keyof typeof
- All changes marked with // [nexus] for rebase visibility
- Add server/src/onboarding-assets/pm/ with SOUL.md, AGENTS.md, HEARTBEAT.md, TOOLS.md
- Add server/src/onboarding-assets/engineer/ with SOUL.md, AGENTS.md, HEARTBEAT.md, TOOLS.md
- Rewrite server/src/onboarding-assets/ceo/ as PM-appropriate content with Nexus vocabulary
- All files use workspace/agent/Owner/Project Manager terminology
- Zero Paperclip, CEO, Hire, or Fire references in any template content
- company-export-readme.ts: ROLE_LABELS ceo changed from 'CEO' to 'Project Manager' [nexus]
- server/index.ts: LOCAL_BOARD_USER_NAME changed from 'Board' to 'Owner' [nexus]
- cli/__tests__/company.test.ts: assertions updated to Workspace vocabulary
- cli/__tests__/http.test.ts: assertion updated to 'Nexus API' from 'Paperclip API'
- ui/OnboardingWizard.tsx: added explicit string type annotation for useState<string>
- InviteLanding: skill bootstrap and invite heading use VOCAB.appName and VOCAB.company
- IssueDetail: Board actor identity uses VOCAB.board
- NewAgent: first agent name/title defaults to VOCAB.ceo
- NotFound: company not found message uses VOCAB.company
- PluginManager: breadcrumb fallback uses VOCAB.company
- PluginSettings: breadcrumb fallback uses VOCAB.company
- Routines: error messages and creation hint use VOCAB.appName
- App: startup log messages use VOCAB.appName; CLI command unchanged
- Add VOCAB import to cli/src/index.ts and cli/src/client/http.ts
- Replace all 'Paperclip' description/help strings with VOCAB.appName
- Update backup filename prefix default from 'paperclip' to 'nexus'
- Update data dir help text to reference ~/.nexus
- Keep .name('paperclipai') binary name unchanged (CODE-zone)
- Sidebar.tsx: section label uses VOCAB.company instead of hardcoded 'Company'
- CompanySwitcher.tsx: uses VOCAB.company for placeholder and settings link
- ActivityRow.tsx: uses VOCAB.board instead of hardcoded 'Board' for user actor
- ApprovalPayload.tsx: hire_agent and approve_ceo_strategy values use VOCAB constants
- NewAgentDialog.tsx: CEO references use VOCAB.ceo
- NewGoalDialog.tsx: company level label uses VOCAB.company
- CompanyRail: import Box from lucide-react instead of Paperclip
- CompanyRail: render <Box> icon instead of <Paperclip> in top rail
- Auth.tsx: import VOCAB from @paperclipai/branding
- Auth.tsx: use VOCAB.appName for logo text and sign-in/create-account headings
- Add @paperclipai/branding workspace dep to ui/package.json and cli/package.json
- Change <title> and apple-mobile-web-app-title to Nexus in ui/index.html
- Replace site.webmanifest name/short_name with Nexus
- Replace paperclip SVG favicon with N-letter Nexus favicon
- Replace PAPERCLIP art with NEXUS art in server/src/startup-banner.ts
- Replace full cli/src/utils/banner.ts with NEXUS art and updated tagline
- Rename printPaperclipCliBanner to printNexusCliBanner
- Update tagline to 'Open-source orchestration for your agents'
- Update all 5 CLI command callers: onboard, configure, db-backup, worktree, doctor
- Satisfies BRND-02
- Change signature from (agentId: string) to (agent: { id: string; name?: string | null })
- Use sanitizeFriendlyPathSegment(name) for human-readable workspace dirs
- Fall back to sanitized id when name is empty/null
- Update all 4 call sites in heartbeat.ts with { id, name } objects
- Add agentName field to resolveRuntimeSessionParamsForWorkspace input type
- Update both test call sites in heartbeat-workspace-session.test.ts
- Add resolveNexusPointerFile() helper to server/src/home-paths.ts
- Add resolveNexusPointerFile() helper to cli/src/config/home.ts
- Patch resolvePaperclipHomeDir() in both files: ~/.nexus > PAPERCLIP_HOME > ~/.paperclip
- Add import fs from node:fs to both files
The PII sanitizer's phone regex matches digit pairs like "4880-8614"
that span UUID segment boundaries. Random UUIDs occasionally produce
these patterns, causing flaky test failures where sourceRun.id gets
partially redacted as [REDACTED_PHONE].
Use a fixed hex-letter-heavy UUID for runId so no cross-boundary
digit sequence triggers the phone pattern.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - Agents sometimes need to capture UI screenshots for visual
verification of fixes
> - The Paperclip UI requires authentication, so headless browser
screenshots fail without auth
> - The CLI already stores a board token in `~/.paperclip/auth.json`
> - This pull request adds a Playwright-based screenshot script that
reads the board token and injects it as a Bearer header
> - The benefit is agents can now take authenticated screenshots of any
Paperclip UI page without storing email/password credentials
## What Changed
- Added `scripts/screenshot.cjs` — a Node.js script that:
- Reads the board token from `~/.paperclip/auth.json`
- Launches Chromium via Playwright with the token as an `Authorization`
header
- Navigates to the specified URL and saves a screenshot
- Supports `--width`, `--height`, and `--wait` flags
- Accepts both full URLs and path-only shortcuts (e.g.,
`/PAPA/agents/cto/instructions`)
## Verification
```bash
node scripts/screenshot.cjs /PAPA/agents/cto/instructions /tmp/test.png --width 1920
```
Should produce an authenticated screenshot of the agent instructions
page.
## Risks
- Low risk — standalone utility script with no impact on the main
application. Requires Playwright (already a dev dependency) and a valid
board token in `~/.paperclip/auth.json`.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [ ] I have run tests locally and they pass
- [ ] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [ ] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
Supersedes #2499.
## Thinking Path
1. **Project context**: Paperclip uses a markdown editor
(`MarkdownEditor`) for document editing. Users expect to paste
markdown-formatted text from external sources (like code editors, other
documents) and have it render correctly.
2. **Problem identification**: When users paste plain text containing
markdown syntax (e.g., `# Heading`, `- list item`), the editor was
treating it as plain text, resulting in raw markdown syntax being
displayed rather than formatted content.
3. **Root cause**: The default browser paste behavior doesn't recognize
markdown syntax in plain text. The editor needed to intercept paste
events and detect when the clipboard content looks like markdown.
4. **Solution design**:
- Create a utility (`markdownPaste.ts`) to detect markdown patterns in
plain text
- Add a paste capture handler in `MarkdownEditor` that intercepts paste
events
- When markdown is detected, prevent default paste and use
`insertMarkdown` instead
- Handle edge cases (code blocks, file pastes, HTML content)
## What
- Added `ui/src/lib/markdownPaste.ts`: Utility to detect markdown
patterns and normalize line endings
- Added `ui/src/lib/markdownPaste.test.ts`: Test coverage for markdown
detection
- Modified `ui/src/components/MarkdownEditor.tsx`: Added paste capture
handler to intercept and handle markdown paste
## Why
Users frequently copy markdown content from various sources (GitHub,
documentation, notes) and expect it to render correctly when pasted into
the editor. Without this fix, users see raw markdown syntax (e.g., `#
Title` instead of a formatted heading), which degrades the editing
experience.
## How to Verify
1. Open any document in Paperclip
2. Copy markdown text from an external source (e.g., `# Heading\n\n-
Item 1\n- Item 2`)
3. Paste into the editor
4. **Expected**: The content should render as formatted markdown
(heading + bullet list), not as plain text with markdown syntax
### Test Coverage
```bash
cd ui
npm test -- markdownPaste.test.ts
```
All tests should pass, including:
- Windows line ending normalization (`\r\n` → `\n`)
- Old-Mac line ending normalization (`\r` → `\n`)
- Markdown block detection (headings, lists, code fences, etc.)
- Plain text rejection (non-markdown content)
## Risks
1. **False positives**: Plain text containing markdown-like characters
(e.g., a paragraph starting with `#` as a hashtag) may be incorrectly
treated as markdown. The detection uses a heuristic that requires
block-level markdown patterns, which reduces but doesn't eliminate this
risk.
2. **Removed focus guard**: The previous implementation used
`isFocusedRef` to prevent `onChange` from firing during programmatic
`setMarkdown` calls. This guard was removed as part of refactoring. The
assumption is that MDXEditor does not fire `onChange` during
`setMarkdown`, but this should be monitored for unexpected parent update
loops.
3. **Clipboard compatibility**: The paste handler specifically looks for
`text/plain` content and ignores `text/html` (to preserve existing HTML
paste behavior). This means pasting from rich text editors that provide
both HTML and plain text will continue to use the HTML path, which may
or may not be the desired behavior.
---------
Co-authored-by: 馨冉 <xinxincui239@gmail.com>
When a comment has both helpful/needswork feedback buttons and a run link,
the run link now appears right-aligned in the same row instead of a separate
section below. Comments with only a run link (no feedback buttons) still
show the run link in its own bordered row.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The "Don't allow" button in the feedback sharing preference modal
should be visually distinct from "Always allow" by using an outline
variant instead of the default solid primary style.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - The web UI includes an agent detail page with an Instructions tab
for editing agent prompts
> - The Instructions tab used `max-w-6xl` (1152px) to constrain its
two-panel layout (file tree + editor)
> - The floating Cancel/Save buttons used `float-right` at the full page
width, disconnecting them from the constrained content
> - This also left a large empty margin on the right side at wider
viewports
> - This pull request removes `max-w-6xl` so the flex layout fills
available width
> - The benefit is buttons now align with the content edge, and the
right margin is eliminated
## What Changed
- Removed `max-w-6xl` from the `PromptsTab` container in
`ui/src/pages/AgentDetail.tsx:1920`
- The file panel + editor flex layout now fills the available page width
naturally
## Verification
- Navigate to any agent's Instructions tab at a wide viewport (1920px+)
- Before: content stops at 1152px with a gap to the right; Cancel/Save
buttons float to the far edge
- After: content fills available width; Cancel/Save buttons sit flush
with the editor panel
## Risks
- Low risk — only removes a max-width constraint on a single tab's
container. Other tabs (Configuration, Skills, etc.) are unaffected.
## CI Note
The test failure in `feedback-service.test.ts:714` is **pre-existing**
and unrelated to this change. A PII redaction filter is incorrectly
treating a UUID segment (`5618-4783`) as a phone number, producing
`[REDACTED_PHONE]` in the expected UUID value.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [ ] I have run tests locally and they pass
- [ ] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [ ] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - Contributors submit pull requests to improve the codebase
> - We have a PR template at `.github/PULL_REQUEST_TEMPLATE.md` that
standardizes PR descriptions
> - But PRs created via the API or other tooling sometimes bypass the
template
> - We also require Greptile automated review and passing tests, but
this wasn't clearly documented
> - This PR updates CONTRIBUTING.md to explicitly require use of the PR
template, a 5/5 Greptile score, and passing tests
> - The benefit is contributors have clear, upfront expectations for
what a mergeable PR looks like
## What Changed
- Added a new "PR Requirements (all PRs)" section to CONTRIBUTING.md
with three subsections:
- **Use the PR Template** — links to `.github/PULL_REQUEST_TEMPLATE.md`
and explains it must be used even when creating PRs outside the GitHub
UI
- **Tests Must Pass** — requires local test runs and green CI
- **Greptile Review** — requires 5/5 score with all comments addressed
- Updated Path 1 and Path 2 bullet points to reference the PR template,
Greptile 5/5, and CI requirements specifically
- Updated "Writing a Good PR message" section to link to the PR template
and clarify all sections are required
## Verification
- Read the updated CONTRIBUTING.md and verify it clearly references the
PR template, Greptile 5/5 requirement, and test requirements
- Verify all links to `.github/PULL_REQUEST_TEMPLATE.md` resolve
correctly
## Risks
- Low risk — documentation-only change, no code affected
## Model Used
- Provider: Anthropic Claude
- Model ID: claude-opus-4-6 (1M context)
- Capabilities: tool use, code editing
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - The UI includes an inline markdown editor (MDXEditor) for editing
agent instruction files like AGENTS.md
> - The editor should render in monospace to match how markdown/code
files look in a text editor
> - The `AgentDetail.tsx` component already passes `font-mono` via
Tailwind's `contentClassName`, but it wasn't taking effect
> - Two CSS rules in `index.css` set `font-family: inherit`, which
overrode the Tailwind utility due to specificity/source order
> - This PR removes those overrides so `font-mono` applies correctly
> - The benefit is the markdown editor now renders in monospace
(Menlo/SF Mono), matching user expectations for code/config files
## What Changed
- Removed `font-family: inherit` from `.paperclip-mdxeditor
[class*="_placeholder_"]` in `ui/src/index.css`
- Removed `font-family: inherit` from `.paperclip-mdxeditor-content` in
`ui/src/index.css`
## Verification
- Navigate to any agent's Instructions tab in the Paperclip UI
- Confirm the markdown editor content renders in a monospace font
(Menlo/SF Mono)
- Visually verified by user on a live dev server
## Risks
- Low risk. Only removes two CSS declarations. Non-monospace editors are
unaffected since `font-mono` is only applied to agent instruction files
via `contentClassName` in `AgentDetail.tsx`.
## Screenshots
Before:
<img width="934" height="1228" alt="Screenshot 2026-04-02 at 10 46
06 PM"
src="https://github.com/user-attachments/assets/5d84f913-cbea-4206-9d41-3f283209c009"
/>
After:
<img width="1068" height="1324" alt="PNG image"
src="https://github.com/user-attachments/assets/2040e812-d9ca-4b37-b73b-ce05cf52168c"
/>
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - Agents run shell commands during workspace provisioning (git
worktree creation, runtime services)
> - When `process.env.SHELL` is unset, the code falls back to `/bin/sh`
> - But on Windows with Git Bash, `/bin/sh` doesn't exist as an absolute
path — Git Bash provides `sh` on PATH instead
> - This causes `child_process.spawn` to throw `ENOENT`, crashing
workspace provisioning on Windows
> - This PR extracts a `resolveShell()` helper that uses `$SHELL` when
set, falls back to `sh` (bare) on Windows or `/bin/sh` on Unix
> - The benefit is that agents running on Windows via Git Bash can
provision workspaces without shell resolution errors
## Summary
- `workspace-runtime.ts` falls back to `/bin/sh` when
`process.env.SHELL` is unset
- On Windows, `/bin/sh` doesn't exist → `spawn /bin/sh ENOENT`
- Fix: extract `resolveShell()` helper that uses `$SHELL` when set,
falls back to `sh` on Windows (Git Bash PATH lookup) or `/bin/sh` on
Unix
Three call sites updated to use the new helper.
Fixes#892
## Root cause
When Paperclip spawns shell commands in workspace operations (e.g., git
worktree creation), it uses `process.env.SHELL` if set, otherwise
defaults to `/bin/sh`. On Windows with Git Bash, `$SHELL` is typically
unset and `/bin/sh` is not a valid path — Git Bash provides `sh` on PATH
but not at the absolute `/bin/sh` location. This causes
`child_process.spawn` to throw `ENOENT`.
## Approach
Rather than hard-coding a Windows-specific absolute path (e.g.,
`C:\Program Files\Git\bin\sh.exe`), we use the bare `"sh"` command which
relies on PATH resolution. This works because:
1. Git Bash adds its `usr/bin` directory to PATH, making `sh` resolvable
2. On Unix/macOS, `/bin/sh` remains the correct default (it's the POSIX
standard location)
3. `process.env.SHELL` takes priority when set, so this only affects the
fallback
## Test plan
- [x] 7 unit tests for `resolveShell()`: SHELL set, trimmed, empty,
whitespace-only, linux/darwin/win32 fallbacks
- [x] Run a workspace provision command on Windows with `git_worktree`
strategy
- [x] Verify Unix/macOS is unaffected
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Devin Foley <devin@devinfoley.com>
Add a required "Model Used" section to the PR template so contributors
document which AI model (with version, context window, reasoning mode,
and other capability details) was used for each change. Also adds a
corresponding checklist item.
Co-Authored-By: Paperclip <noreply@paperclip.ing>