Skip to content

refactor: full rebrand ppg → pogu#50

Merged
2witstudios merged 8 commits into
mainfrom
pogu/rebrand
Feb 26, 2026
Merged

refactor: full rebrand ppg → pogu#50
2witstudios merged 8 commits into
mainfrom
pogu/rebrand

Conversation

@2witstudios

@2witstudios 2witstudios commented Feb 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Complete rebrand from ppg (Pure Point Guard) to pogu (pointguard) across the entire codebase
  • npm package: pure-point-guardpointguard, CLI binary: ppgpogu
  • Config directory: .pg/.pogu/, branch prefix: ppg/pogu/
  • Error class: PgErrorPoguError, path helper: pgDir()poguDir()

Changes (643 lines across 76 files)

Core layer (src/lib, src/types, src/core)

  • PG_DIRPOGU_DIR, pgDir()poguDir(), PgErrorPoguError
  • All test fixtures, branch prefixes, session names updated
  • 19 files, 125 insertions/deletions

Commands layer (src/commands, src/cli.ts)

  • .name('pogu'), all user-facing strings, imports, branch prefixes
  • 21 files, 100 insertions/deletions

Docs, skills, config

  • package.json: name/bin/description/URLs updated
  • CLAUDE.md, README.md, vision.md, CONTRIBUTING.md, SECURITY.md, CHANGELOG.md
  • Skills directories moved: skills/ppgskills/pogu, skills/ppg-conductorskills/pogu-conductor
  • Plugin config and appcast updated
  • 15 files, 269 insertions/deletions

Swift macOS app

  • PPGServicePoguService, runPPGCommandrunPoguCommand
  • All UI strings, notification names, UserDefaults keys, bundle IDs
  • Directory names (PPG CLI/) intentionally preserved (requires Xcode refactoring)
  • 21 files, 149 insertions/deletions

Test plan

  • npm run typecheck passes
  • npm run build succeeds — CLI binary responds to pogu --version
  • All 176 tests pass (17 test files)
  • grep -rn 'PgError\|pgDir\|PG_DIR' src/ returns zero hits
  • Manual: npm link and verify pogu spawn/status/reset work end-to-end
  • Manual: Verify Swift app compiles in Xcode

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Rebranded project identity and CLI from ppg to pogu
    • Updated package name from pure-point-guard to pointguard on npm
    • Renamed runtime directories from .pg to .pogu for configuration, templates, and results
    • Updated default branch naming convention from ppg/... to pogu/...
    • Updated all CLI commands and references throughout the application

Rename PgError → PoguError, pgDir() → poguDir(), PG_DIR → POGU_DIR,
.pg/ → .pogu/, ppg/ branch prefix → pogu/, session name ppg → pogu
across src/lib/, src/core/, src/types/, and src/test-fixtures.ts
Rename all ppg → pogu in CLI entry point and command implementations:
imports (PoguError, poguDir), user-facing strings, branch prefixes,
session names, .pg/ → .pogu/ directory references
Rename package pure-point-guard → pointguard, bin ppg → pogu,
move skills/ppg → skills/pogu, skills/ppg-conductor → skills/pogu-conductor,
update all documentation, plugin config, and appcast
Rename PPGService → PoguService, runPPGCommand → runPoguCommand,
all UI strings, notification names, UserDefaults keys, bundle IDs,
path references .pg/ → .pogu/ across all Swift source and test files
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Feb 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This pull request performs a comprehensive project rename from "ppg" (Pure Point Guard) to "pogu" across the entire codebase. Changes include renaming the npm package, Swift bundle identifiers, public API classes (PPGServicePoguService, PgErrorPoguError), path helpers (pgDirpoguDir), CLI commands, directory structures (.pg.pogu), and all related documentation and test fixtures.

Changes

Cohort / File(s) Summary
Package & Plugin Metadata
package.json, .claude-plugin/marketplace.json, .claude-plugin/plugin.json
Updated package name from pure-point-guard to pointguard; npm bin entry ppg → pogu; marketplace and plugin identifiers updated from ppg to pogu.
Documentation
README.md, CHANGELOG.md, CONTRIBUTING.md, CLAUDE.md, SECURITY.md, vision.md
Renamed CLI references from ppg to pogu; updated directory paths from .pg to .pogu; updated command examples and project nomenclature throughout.
Swift iOS Codebase
PPG CLI/PPG CLI.xcodeproj/project.pbxproj, PPG CLI/PPG CLI/AppDelegate.swift, PPG CLI/PPG CLI/AppSettingsManager.swift, PPG CLI/PPG CLI/ContentTabViewController.swift, PPG CLI/PPG CLI/DashboardSession.swift, PPG CLI/PPG CLI/DashboardSplitViewController.swift, PPG CLI/PPG CLI/HomeDashboardView.swift, PPG CLI/PPG CLI/Info.plist, PPG CLI/PPG CLI/KeybindingManager.swift, PPG CLI/PPG CLI/Models.swift, PPG CLI/PPG CLI/PPGService.swift, PPG CLI/PPG CLI/ProjectPickerViewController.swift, PPG CLI/PPG CLI/PromptsView.swift, PPG CLI/PPG CLI/SetupViewController.swift, PPG CLI/PPG CLI/ShellUtils.swift, PPG CLI/PPG CLI/SidebarViewController.swift, PPG CLI/PPG CLI/SwarmsView.swift
Renamed PPGServicePoguService across all view controllers and service usage; updated bundle identifiers in Xcode project; changed manifest paths from .pg to .pogu; updated UserDefaults keys, notification names, and user-facing strings; updated appcast URL.
Swift Tests
PPG CLI/PPG CLITests/DashboardSessionTests.swift, PPG CLI/PPG CLITests/PPGServiceTests.swift, PPG CLI/PPG CLITests/PPG_CLITests.swift, PPG CLI/PPG CLITests/SidebarViewControllerTests.swift
Updated test fixtures and class names from PPGService to PoguService; changed test data from ppg namespace to pogu (sessions, branches, paths).
TypeScript/Node CLI Core
src/cli.ts, src/commands/attach.ts, src/commands/clean.ts, src/commands/init.ts, src/commands/install-dashboard.ts, src/commands/kill.ts, src/commands/list.ts, src/commands/logs.ts, src/commands/merge.ts, src/commands/pr.ts, src/commands/reset.ts, src/commands/restart.ts, src/commands/spawn.ts, src/commands/status.ts, src/commands/swarm.ts, src/commands/ui.ts, src/commands/wait.ts, src/commands/worktree.ts
Replaced PgErrorPoguError import and usage across all commands; updated generated branch naming from ppg/ to pogu/; updated directory references from .pg/ to .pogu/ in help text and messages; changed npm package reference from pure-point-guard to pointguard; updated user-facing CLI messages.
TypeScript Core Modules
src/core/agent.ts, src/core/cleanup.test.ts, src/core/config.test.ts, src/core/config.ts, src/core/manifest.test.ts, src/core/pr.test.ts, src/core/self.test.ts, src/core/swarm.test.ts, src/core/swarm.ts, src/core/template.test.ts, src/core/tmux.ts
Updated error handling from PgErrorPoguError; changed default session name from ppg to pogu; updated test fixtures for branch, window, and target identifiers from ppg prefix to pogu; updated temporary directory prefixes and swarm paths.
TypeScript Libraries
src/lib/errors.ts, src/lib/errors.test.ts, src/lib/name.ts, src/lib/paths.ts, src/lib/paths.test.ts, src/lib/vars.ts, src/lib/vars.test.ts, src/test-fixtures.ts
Renamed base error class from PgErrorPoguError with all subclasses updated to extend it; replaced path helper pgDir()poguDir() returning .pogu instead of .pg; updated test fixture defaults for agent and worktree identifiers.
Skills & Reference Documentation
skills/pogu-conductor/SKILL.md, skills/pogu-conductor/references/commands.md, skills/pogu-conductor/references/conductor.md, skills/pogu-conductor/references/modes.md, skills/pogu/SKILL.md
Updated command references from ppg-conductor/ppg to pogu-conductor/pogu; changed worktree branch prefixes from ppg/ to pogu/; updated directory paths from .pg/ to .pogu/; adjusted session and tmux target identifiers.
Other Configuration
appcast.xml
Updated Sparkle feed metadata from PPG CLI to Pogu CLI; updated repository link to pogu-cli GitHub repository.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

This is a large-scope, homogeneous refactoring that renames the project consistently across ~90+ files. While individual changes follow a clear pattern (string substitutions and identifier renames), the volume and span across multiple ecosystems (Swift, TypeScript, configuration, documentation) requires verification that: (1) all rename targets are correct and complete, (2) public API changes are properly propagated, (3) test fixtures align with new naming, and (4) no unintended replacements occurred.

Possibly related PRs

Poem

🐰 From ppg to pogu, our bunny hops with glee,
The paths are .pogu now, directory by spree,
PgError bows to PoguError so fine,
With every service renamed, the stars align! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description deviates from the required template structure; it uses 'Summary' and 'Changes' sections instead of the specified 'What', 'Why', 'How', and 'Checklist' format. Restructure the description to follow the template: add 'What', 'Why', 'How' sections, and include the 'Checklist' with actual checkboxes for npm test, typecheck, and testing verification.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor: full rebrand ppg → pogu' clearly and concisely describes the primary change: a complete rebranding of the project from ppg to pogu across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pogu/rebrand

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@2witstudios
2witstudios merged commit 3d832c5 into main Feb 26, 2026
2 of 3 checks passed
@2witstudios
2witstudios deleted the pogu/rebrand branch February 26, 2026 01:57

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
src/commands/ui.ts (1)

40-41: ⚠️ Potential issue | 🟠 Major

Update bundle identifier in mdfind query from com.2wit.PPG-CLI to com.2wit.Pogu.

The mdfind query on line 41 uses an outdated bundle identifier. The Swift app's actual bundle identifier is com.2wit.Pogu (as defined in the Xcode project configuration), so the query will fail to locate the application. Update the query to match the current bundle ID.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/ui.ts` around lines 40 - 41, The mdfind call that builds the
Spotlight query uses the outdated bundle identifier string "com.2wit.PPG-CLI";
update the query argument passed to execa('mdfind', [...]) so the predicate uses
the current bundle identifier "com.2wit.Pogu" (i.e., replace "com.2wit.PPG-CLI"
with "com.2wit.Pogu" in the array passed to execa) so the result variable
receives the correct search output.
PPG CLI/PPG CLITests/DashboardSessionTests.swift (4)

180-199: ⚠️ Potential issue | 🔴 Critical

Same directory path mismatch as above.

Line 182 creates .pg but the DashboardSession now uses .pogu paths.

🐛 Proposed fix
     func testReloadFromDiskCancelsPendingWrite() {
         let dir = NSTemporaryDirectory() + "pogu-test-reload-\(UUID().uuidString)"
-        try? FileManager.default.createDirectory(atPath: dir + "/.pg", withIntermediateDirectories: true)
+        try? FileManager.default.createDirectory(atPath: dir + "/.pogu", withIntermediateDirectories: true)
         let s = DashboardSession(projectRoot: dir)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLITests/DashboardSessionTests.swift around lines 180 - 199, The
test creates and cleans up the wrong hidden directory name (uses ".pg") but
DashboardSession uses ".pogu"; update the test
(testReloadFromDiskCancelsPendingWrite) to create the directory at dir +
"/.pogu" (and remove that path at the end) so the session's
flushToDisk/reloadFromDisk operate on the same on-disk path used by
DashboardSession.

114-131: ⚠️ Potential issue | 🔴 Critical

Directory path mismatch will cause test failures.

The test creates the directory at .pg (line 115) but then expects the file to be written to .pogu (line 122). The flushToDisk() method will fail or write to a non-existent directory.

🐛 Proposed fix
     func testFlushWritesImmediately() {
         let dir = NSTemporaryDirectory() + "pogu-test-flush-\(UUID().uuidString)"
-        try? FileManager.default.createDirectory(atPath: dir + "/.pg", withIntermediateDirectories: true)
+        try? FileManager.default.createDirectory(atPath: dir + "/.pogu", withIntermediateDirectories: true)
         let s = DashboardSession(projectRoot: dir)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLITests/DashboardSessionTests.swift around lines 114 - 131, The
test creates a temporary repository metadata dir at ".pg" but later asserts the
file exists under ".pogu", causing a path mismatch; update the test to use the
same directory name that DashboardSession.flushToDisk writes to (or vice versa).
Locate the test in DashboardSessionTests.swift where dir is created and ensure
the created directory (created via FileManager.createDirectory and the
addTerminal call) and the expected filePath variable both reference the same
folder name (either ".pg" or ".pogu") so flushToDisk writes to the directory the
test checks; adjust the dir creation or filePath string accordingly around
DashboardSession and flushToDisk usage.

163-178: ⚠️ Potential issue | 🔴 Critical

Same directory path mismatch as above.

Line 165 creates .pg but line 172 expects .pogu.

🐛 Proposed fix
     func testFlushCancelsPendingDebouncedWrite() {
         let dir = NSTemporaryDirectory() + "pogu-test-cancel-\(UUID().uuidString)"
-        try? FileManager.default.createDirectory(atPath: dir + "/.pg", withIntermediateDirectories: true)
+        try? FileManager.default.createDirectory(atPath: dir + "/.pogu", withIntermediateDirectories: true)
         let s = DashboardSession(projectRoot: dir)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLITests/DashboardSessionTests.swift around lines 163 - 178, The
test creates a temp worktree directory at dir + "/.pg" but later reads dir +
"/.pogu/dashboard-sessions.json", causing a path mismatch; update the directory
creation to use the same folder name as the read path (or change the read path
to match) so both use the same dot-folder name (adjust the directory creation
line that calls FileManager.default.createDirectory and/or the filePath variable
used to load dashboard-sessions.json in testFlushCancelsPendingDebouncedWrite of
DashboardSessionTests.swift, leaving the rest of the flow using
s.addTerminal(...) and s.flushToDisk() unchanged).

133-161: ⚠️ Potential issue | 🔴 Critical

Same directory path mismatch as above.

Line 135 creates .pg but line 143 expects .pogu.

🐛 Proposed fix
     func testDebouncedWriteCoalesces() {
         let dir = NSTemporaryDirectory() + "pogu-test-debounce-\(UUID().uuidString)"
-        try? FileManager.default.createDirectory(atPath: dir + "/.pg", withIntermediateDirectories: true)
+        try? FileManager.default.createDirectory(atPath: dir + "/.pogu", withIntermediateDirectories: true)
         let s = DashboardSession(projectRoot: dir)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLITests/DashboardSessionTests.swift around lines 133 - 161, The
testDebouncedWriteCoalesces unit test creates a temporary directory at dir and
currently creates a subdirectory ".pg" but later checks for a file under ".pogu"
(filePath variable), causing a path mismatch; fix by making the directory
creation and expected file path consistent—either create ".pogu" instead of
".pg" in the call within testDebouncedWriteCoalesces (the
createDirectory(atPath: dir + "/.pg", ...) call) or change filePath to point at
".pg"; update the symbol references testDebouncedWriteCoalesces, filePath, and
the createDirectory invocation so the directory name is identical in both
places.
🧹 Nitpick comments (4)
PPG CLI/PPG CLI/SwarmsView.swift (1)

89-89: Extract the swarms subpath into a single constant.

The same literal appears at Line 89 and Line 733. Centralizing it avoids drift in future renames.

♻️ Proposed refactor
 class SwarmsView: NSView, NSTableViewDataSource, NSTableViewDelegate {
+    private static let swarmsRelativePath = ".pogu/swarms"
@@
-            let folder = (ctx.projectRoot as NSString).appendingPathComponent(".pogu/swarms")
+            let folder = (ctx.projectRoot as NSString).appendingPathComponent(Self.swarmsRelativePath)
@@
-        let folder = (ctx.projectRoot as NSString).appendingPathComponent(".pogu/swarms")
+        let folder = (ctx.projectRoot as NSString).appendingPathComponent(Self.swarmsRelativePath)

Also applies to: 733-733

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLI/SwarmsView.swift at line 89, Extract the literal
".pogu/swarms" into a single shared constant and use that constant wherever the
path is built (e.g., replace occurrences that form folder with (ctx.projectRoot
as NSString).appendingPathComponent(SWARMS_SUBPATH)). Create the constant near
the top of SwarmsView.swift (file-scope or inside the SwarmsView type) named
something like SWARMS_SUBPATH and update both the usage that assigns folder and
the other occurrence at the later location (the second appearance referenced in
the review) to reference this constant so future renames only require one edit.
src/commands/init.ts (1)

143-143: Move conductor-context path construction into lib/paths.ts.

path.join(poguDir(projectRoot), 'conductor-context.md') duplicates path composition logic inside a command module; add a helper (e.g., conductorContextPath(projectRoot)).

As per coding guidelines, **/*.ts: “Use path helper functions from lib/paths.ts for all path computation... Never duplicate path logic”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/init.ts` at line 143, Move the path construction out of the
command and into lib/paths.ts: add a helper function named
conductorContextPath(projectRoot) in lib/paths.ts that returns
path.join(poguDir(projectRoot), 'conductor-context.md'), export it, then update
src/commands/init.ts to import and use conductorContextPath(projectRoot) instead
of computing conductorPath inline; ensure you reuse the existing poguDir symbol
inside lib/paths.ts and update any imports/exports accordingly.
package.json (1)

7-8: Consider a temporary ppg bin alias for smoother migration.

Dropping the old executable name immediately can break existing automation. A one-release alias reduces upgrade friction.

Suggested diff
   "bin": {
+    "ppg": "./dist/cli.js",
     "pogu": "./dist/cli.js"
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 7 - 8, Add a temporary alias in package.json's
"bin" mapping so callers of the old executable keep working: keep the existing
"pogu": "./dist/cli.js" entry and add "ppg": "./dist/cli.js" (the old name)
pointing to the same CLI entry; ship a single release with both names and remove
the "ppg" alias in a subsequent major release after notifying users.
src/lib/errors.ts (1)

1-12: Export a PgError compatibility alias during the transition.

Keeping a PgError export (aliasing PoguError) preserves compatibility while allowing the new naming to roll out safely.

Suggested diff
 export class PoguError extends Error {
   constructor(
     message: string,
     public readonly code: string,
     public readonly exitCode: number = 1,
   ) {
     super(message);
     this.name = 'PoguError';
   }
 }
+
+// Backward-compatibility alias for migration period
+export { PoguError as PgError };
As per coding guidelines `src/lib/errors.ts`: “Use `PgError` hierarchy with typed error codes (`TMUX_NOT_FOUND`, `NOT_GIT_REPO`, `NOT_INITIALIZED`, `MANIFEST_LOCK`, `WORKTREE_NOT_FOUND`, `AGENT_NOT_FOUND`, `MERGE_FAILED`, `INVALID_ARGS`, `AGENTS_RUNNING`, `WAIT_TIMEOUT`, `AGENTS_FAILED`, `NO_SESSION_ID`)”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/errors.ts` around lines 1 - 12, Export a compatibility alias named
PgError that points to the new PoguError class so existing consumers keep
working; add an export (e.g. export { PoguError as PgError } or equivalent)
alongside the PoguError declaration in the same module (where PoguError and
TmuxNotFoundError are defined) so the PgError symbol is available and preserves
typings during the transition.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@PPG` CLI/PPG CLI/AppSettingsManager.swift:
- Around line 33-38: Add a one-time migration that copies legacy UserDefaults
keys named with the "PPG" prefix to the new "Pogu" keys before the app reads or
writes settings: implement a migrateLegacyKeys() method in AppSettingsManager
that checks for each legacy key (e.g. "PPGRefreshInterval", "PPGTerminalFont",
"PPGTerminalFontSize", "PPGShell", "PPGHistoryLimit", "PPGAppearanceMode"), and
if the corresponding new key (static lets refreshInterval, terminalFont,
terminalFontSize, shell, historyLimit, appearanceMode) is not already set, copy
the legacy value to the new key and remove the legacy key; call
migrateLegacyKeys() once during startup or in AppSettingsManager initialization
so existing user preferences are preserved on upgrade.

In `@PPG` CLI/PPG CLI/Info.plist:
- Line 7: The Sparkle feed URL in Info.plist currently points to
"https://2witstudios.github.io/pogu/appcast.xml" which returns 404; update the
value of that <string> entry in Info.plist to a valid, published appcast URL (or
remove/disable the NSSparkleFeedURL entry) before release so Sparkle can fetch
updates successfully; ensure the new URL is reachable and serves a valid
appcast.xml.

In `@PPG` CLI/PPG CLI/KeybindingManager.swift:
- Line 104: The new defaultsKey ("PoguCustomKeybindings") will drop existing
users’ bindings because there is no fallback read from the legacy key
"PPGCustomKeybindings"; update KeybindingManager to attempt a read from the
legacy key when loading (e.g., in the initializer or loadBindings method) and if
found migrate that data into the new defaultsKey and remove the old key so
future reads use defaultsKey; reference the private let defaultsKey and the
class KeybindingManager and ensure the migration uses UserDefaults.standard (or
your existing defaults instance) to read legacy data, write it under
defaultsKey, and delete the legacy key.

In `@PPG` CLI/PPG CLI/Models.swift:
- Around line 215-216: Add a one-time UserDefaults migration that runs when this
model is initialized: check for the old keys "PPGRecentProjects",
"PPGLastOpenedProject", and "PPGOpenProjects" and if any exist copy their values
into the new keys (key, lastOpenedKey, and the openProjectsKey used at the code
around line 284) using UserDefaults.standard.set(...), then remove the old keys
with removeObject(forKey:). Ensure the migration is guarded so it only runs once
(e.g., detect presence of any old key or set a migrated flag) and preserve the
original value types (arrays/strings) when copying.

In `@PPG` CLI/PPG CLI/SwarmsView.swift:
- Around line 89-90: Update SwarmsView.swift to add backward-compatible fallback
handling for the swarm folder: replace the hardcoded ".pogu/swarms" occurrences
with a single constant (e.g., swarmsDirectoryName or SwarmsView.swarmsDirectory)
and use that constant wherever the path is constructed; when reading contents
(the code using folder and fm.contentsOfDirectory) if the new path returns empty
or fails, attempt the legacy ".pg/swarms" path and read from it (or perform a
one-time migration by moving files from ".pg/swarms" to the new constant path),
ensuring the code uses the same constant for both reads and writes so future
path changes are centralized.

In `@PPG` CLI/PPG CLITests/PPG_CLITests.swift:
- Around line 9-19: The test fixture mixes sessionName "pogu-test" with tmux
values "ppg-test:1"; update the fixture so tmuxWindow and tmuxTarget use the
session name (e.g., "pogu-test:1") to match sessionName and avoid naming
regressions—specifically change the tmuxWindow in the worktree object
(wt-abc123) and the tmuxTarget in the agent object (ag-def456) to use
"pogu-test:1" and verify other fixture entries use the same sessionName
consistently.

In `@src/commands/init.ts`:
- Around line 88-89: The initCommand currently emits unconditional info(...)
logs and uses console.log which breaks --json mode; update initCommand to stop
emitting plain info/console output when options.json is true and instead call
output(data, options.json) for successful results and outputError(err,
options.json) for failures; replace each unconditional info(...) and console.log
in initCommand (and the other noted message sites inside the same file) with the
appropriate output(...) call, and wrap any human-readable info(...) calls behind
if (!options.json) so interactive output remains available when JSON mode is
off.
- Around line 17-21: Update the user-facing text in src/commands/init.ts that
currently hardcodes the string "master" (look for messages or help text
referencing "master branch") to say "default branch" instead and remove any
implication that the repo's default branch is named master; if the code
programmatically uses the literal "master" in prompts or logging, replace that
with a dynamic reference to the repository's default branch (or a neutral phrase
"default branch") and ensure any guidance still instructs users to use `pogu
spawn` to create worktrees rather than modifying the default branch directly.

---

Outside diff comments:
In `@PPG` CLI/PPG CLITests/DashboardSessionTests.swift:
- Around line 180-199: The test creates and cleans up the wrong hidden directory
name (uses ".pg") but DashboardSession uses ".pogu"; update the test
(testReloadFromDiskCancelsPendingWrite) to create the directory at dir +
"/.pogu" (and remove that path at the end) so the session's
flushToDisk/reloadFromDisk operate on the same on-disk path used by
DashboardSession.
- Around line 114-131: The test creates a temporary repository metadata dir at
".pg" but later asserts the file exists under ".pogu", causing a path mismatch;
update the test to use the same directory name that DashboardSession.flushToDisk
writes to (or vice versa). Locate the test in DashboardSessionTests.swift where
dir is created and ensure the created directory (created via
FileManager.createDirectory and the addTerminal call) and the expected filePath
variable both reference the same folder name (either ".pg" or ".pogu") so
flushToDisk writes to the directory the test checks; adjust the dir creation or
filePath string accordingly around DashboardSession and flushToDisk usage.
- Around line 163-178: The test creates a temp worktree directory at dir +
"/.pg" but later reads dir + "/.pogu/dashboard-sessions.json", causing a path
mismatch; update the directory creation to use the same folder name as the read
path (or change the read path to match) so both use the same dot-folder name
(adjust the directory creation line that calls
FileManager.default.createDirectory and/or the filePath variable used to load
dashboard-sessions.json in testFlushCancelsPendingDebouncedWrite of
DashboardSessionTests.swift, leaving the rest of the flow using
s.addTerminal(...) and s.flushToDisk() unchanged).
- Around line 133-161: The testDebouncedWriteCoalesces unit test creates a
temporary directory at dir and currently creates a subdirectory ".pg" but later
checks for a file under ".pogu" (filePath variable), causing a path mismatch;
fix by making the directory creation and expected file path consistent—either
create ".pogu" instead of ".pg" in the call within testDebouncedWriteCoalesces
(the createDirectory(atPath: dir + "/.pg", ...) call) or change filePath to
point at ".pg"; update the symbol references testDebouncedWriteCoalesces,
filePath, and the createDirectory invocation so the directory name is identical
in both places.

In `@src/commands/ui.ts`:
- Around line 40-41: The mdfind call that builds the Spotlight query uses the
outdated bundle identifier string "com.2wit.PPG-CLI"; update the query argument
passed to execa('mdfind', [...]) so the predicate uses the current bundle
identifier "com.2wit.Pogu" (i.e., replace "com.2wit.PPG-CLI" with
"com.2wit.Pogu" in the array passed to execa) so the result variable receives
the correct search output.

---

Nitpick comments:
In `@package.json`:
- Around line 7-8: Add a temporary alias in package.json's "bin" mapping so
callers of the old executable keep working: keep the existing "pogu":
"./dist/cli.js" entry and add "ppg": "./dist/cli.js" (the old name) pointing to
the same CLI entry; ship a single release with both names and remove the "ppg"
alias in a subsequent major release after notifying users.

In `@PPG` CLI/PPG CLI/SwarmsView.swift:
- Line 89: Extract the literal ".pogu/swarms" into a single shared constant and
use that constant wherever the path is built (e.g., replace occurrences that
form folder with (ctx.projectRoot as
NSString).appendingPathComponent(SWARMS_SUBPATH)). Create the constant near the
top of SwarmsView.swift (file-scope or inside the SwarmsView type) named
something like SWARMS_SUBPATH and update both the usage that assigns folder and
the other occurrence at the later location (the second appearance referenced in
the review) to reference this constant so future renames only require one edit.

In `@src/commands/init.ts`:
- Line 143: Move the path construction out of the command and into lib/paths.ts:
add a helper function named conductorContextPath(projectRoot) in lib/paths.ts
that returns path.join(poguDir(projectRoot), 'conductor-context.md'), export it,
then update src/commands/init.ts to import and use
conductorContextPath(projectRoot) instead of computing conductorPath inline;
ensure you reuse the existing poguDir symbol inside lib/paths.ts and update any
imports/exports accordingly.

In `@src/lib/errors.ts`:
- Around line 1-12: Export a compatibility alias named PgError that points to
the new PoguError class so existing consumers keep working; add an export (e.g.
export { PoguError as PgError } or equivalent) alongside the PoguError
declaration in the same module (where PoguError and TmuxNotFoundError are
defined) so the PgError symbol is available and preserves typings during the
transition.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac15c05 and a186533.

📒 Files selected for processing (76)
  • .claude-plugin/marketplace.json
  • .claude-plugin/plugin.json
  • CHANGELOG.md
  • CLAUDE.md
  • CONTRIBUTING.md
  • PPG CLI/PPG CLI.xcodeproj/project.pbxproj
  • PPG CLI/PPG CLI/AppDelegate.swift
  • PPG CLI/PPG CLI/AppSettingsManager.swift
  • PPG CLI/PPG CLI/ContentTabViewController.swift
  • PPG CLI/PPG CLI/DashboardSession.swift
  • PPG CLI/PPG CLI/DashboardSplitViewController.swift
  • PPG CLI/PPG CLI/HomeDashboardView.swift
  • PPG CLI/PPG CLI/Info.plist
  • PPG CLI/PPG CLI/KeybindingManager.swift
  • PPG CLI/PPG CLI/Models.swift
  • PPG CLI/PPG CLI/PPGService.swift
  • PPG CLI/PPG CLI/ProjectPickerViewController.swift
  • PPG CLI/PPG CLI/PromptsView.swift
  • PPG CLI/PPG CLI/SetupViewController.swift
  • PPG CLI/PPG CLI/ShellUtils.swift
  • PPG CLI/PPG CLI/SidebarViewController.swift
  • PPG CLI/PPG CLI/SwarmsView.swift
  • PPG CLI/PPG CLITests/DashboardSessionTests.swift
  • PPG CLI/PPG CLITests/PPGServiceTests.swift
  • PPG CLI/PPG CLITests/PPG_CLITests.swift
  • PPG CLI/PPG CLITests/SidebarViewControllerTests.swift
  • README.md
  • SECURITY.md
  • appcast.xml
  • package.json
  • skills/pogu-conductor/SKILL.md
  • skills/pogu-conductor/references/commands.md
  • skills/pogu-conductor/references/conductor.md
  • skills/pogu-conductor/references/modes.md
  • skills/pogu/SKILL.md
  • src/cli.ts
  • src/commands/attach.ts
  • src/commands/clean.ts
  • src/commands/init.ts
  • src/commands/install-dashboard.ts
  • src/commands/kill.ts
  • src/commands/list.ts
  • src/commands/logs.ts
  • src/commands/merge.ts
  • src/commands/pr.test.ts
  • src/commands/pr.ts
  • src/commands/reset.test.ts
  • src/commands/reset.ts
  • src/commands/restart.ts
  • src/commands/spawn.ts
  • src/commands/status.ts
  • src/commands/swarm.ts
  • src/commands/ui.test.ts
  • src/commands/ui.ts
  • src/commands/wait.ts
  • src/commands/worktree.ts
  • src/core/agent.ts
  • src/core/cleanup.test.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/manifest.test.ts
  • src/core/pr.test.ts
  • src/core/self.test.ts
  • src/core/swarm.test.ts
  • src/core/swarm.ts
  • src/core/template.test.ts
  • src/core/tmux.ts
  • src/lib/errors.test.ts
  • src/lib/errors.ts
  • src/lib/name.ts
  • src/lib/paths.test.ts
  • src/lib/paths.ts
  • src/lib/vars.test.ts
  • src/lib/vars.ts
  • src/test-fixtures.ts
  • vision.md

Comment on lines +33 to +38
static let refreshInterval = "PoguRefreshInterval"
static let terminalFont = "PoguTerminalFont"
static let terminalFontSize = "PoguTerminalFontSize"
static let shell = "PoguShell"
static let historyLimit = "PoguHistoryLimit"
static let appearanceMode = "PoguAppearanceMode"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

UserDefaults key rename will reset existing user settings without migration.

Switching persisted keys from PPG* to Pogu* drops previously saved preferences (font, shell, interval, history, appearance) on upgrade. Add a one-time migration path from legacy keys to new keys.

🛠️ Proposed migration pattern
 final class AppSettingsManager {
   static let shared = AppSettingsManager()
@@
   private enum Key {
     static let refreshInterval = "PoguRefreshInterval"
     static let terminalFont = "PoguTerminalFont"
     static let terminalFontSize = "PoguTerminalFontSize"
     static let shell = "PoguShell"
     static let historyLimit = "PoguHistoryLimit"
     static let appearanceMode = "PoguAppearanceMode"
   }
+
+  private enum LegacyKey {
+    static let refreshInterval = "PPGRefreshInterval"
+    static let terminalFont = "PPGTerminalFont"
+    static let terminalFontSize = "PPGTerminalFontSize"
+    static let shell = "PPGShell"
+    static let historyLimit = "PPGHistoryLimit"
+    static let appearanceMode = "PPGAppearanceMode"
+  }
@@
-  private init() {}
+  private init() {
+    migrateLegacyKeysIfNeeded()
+  }
+
+  private func migrateLegacyKeysIfNeeded() {
+    let pairs: [(old: String, new: String)] = [
+      (LegacyKey.refreshInterval, Key.refreshInterval),
+      (LegacyKey.terminalFont, Key.terminalFont),
+      (LegacyKey.terminalFontSize, Key.terminalFontSize),
+      (LegacyKey.shell, Key.shell),
+      (LegacyKey.historyLimit, Key.historyLimit),
+      (LegacyKey.appearanceMode, Key.appearanceMode)
+    ]
+    for pair in pairs where defaults.object(forKey: pair.new) == nil {
+      if let value = defaults.object(forKey: pair.old) {
+        defaults.set(value, forKey: pair.new)
+      }
+    }
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLI/AppSettingsManager.swift around lines 33 - 38, Add a
one-time migration that copies legacy UserDefaults keys named with the "PPG"
prefix to the new "Pogu" keys before the app reads or writes settings: implement
a migrateLegacyKeys() method in AppSettingsManager that checks for each legacy
key (e.g. "PPGRefreshInterval", "PPGTerminalFont", "PPGTerminalFontSize",
"PPGShell", "PPGHistoryLimit", "PPGAppearanceMode"), and if the corresponding
new key (static lets refreshInterval, terminalFont, terminalFontSize, shell,
historyLimit, appearanceMode) is not already set, copy the legacy value to the
new key and remove the legacy key; call migrateLegacyKeys() once during startup
or in AppSettingsManager initialization so existing user preferences are
preserved on upgrade.

<dict>
<key>SUFeedURL</key>
<string>https://2witstudios.github.io/ppg-cli/appcast.xml</string>
<string>https://2witstudios.github.io/pogu/appcast.xml</string>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

url="https://2witstudios.github.io/pogu/appcast.xml"

echo "Checking HTTP headers..."
curl -fsSLI "$url" 2>&1 | head -20

echo
echo "Checking appcast payload prefix..."
curl -fsSL "$url" 2>&1 | head -40

Repository: 2witstudios/ppg-cli

Length of output: 702


Publish the Sparkle feed URL before release. The appcast.xml endpoint currently returns a 404 error. Releasing with this URL will cause silent update failures for users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLI/Info.plist at line 7, The Sparkle feed URL in Info.plist
currently points to "https://2witstudios.github.io/pogu/appcast.xml" which
returns 404; update the value of that <string> entry in Info.plist to a valid,
published appcast URL (or remove/disable the NSSparkleFeedURL entry) before
release so Sparkle can fetch updates successfully; ensure the new URL is
reachable and serves a valid appcast.xml.

static let shared = KeybindingManager()

private let defaultsKey = "PPGCustomKeybindings"
private let defaultsKey = "PoguCustomKeybindings"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add migration fallback for legacy UserDefaults key.

Line 104 changes the persistence key, but there’s no read fallback for "PPGCustomKeybindings". Existing users will silently lose custom shortcuts after upgrade.

💡 Proposed migration-safe fix
 final class KeybindingManager {
     static let shared = KeybindingManager()

     private let defaultsKey = "PoguCustomKeybindings"
+    private let legacyDefaultsKey = "PPGCustomKeybindings"

     private var customBindings: [String: StoredBinding] = [:]

@@
     private func loadBindings() {
-        guard let data = UserDefaults.standard.data(forKey: defaultsKey),
-              let decoded = try? JSONDecoder().decode([String: StoredBinding].self, from: data) else {
-            return
+        let defaults = UserDefaults.standard
+
+        if let data = defaults.data(forKey: defaultsKey),
+           let decoded = try? JSONDecoder().decode([String: StoredBinding].self, from: data) {
+            customBindings = decoded
+            return
+        }
+
+        // One-time migration from old branding key.
+        if let legacyData = defaults.data(forKey: legacyDefaultsKey),
+           let decoded = try? JSONDecoder().decode([String: StoredBinding].self, from: legacyData) {
+            customBindings = decoded
+            saveBindings()
+            defaults.removeObject(forKey: legacyDefaultsKey)
         }
-        customBindings = decoded
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLI/KeybindingManager.swift at line 104, The new defaultsKey
("PoguCustomKeybindings") will drop existing users’ bindings because there is no
fallback read from the legacy key "PPGCustomKeybindings"; update
KeybindingManager to attempt a read from the legacy key when loading (e.g., in
the initializer or loadBindings method) and if found migrate that data into the
new defaultsKey and remove the old key so future reads use defaultsKey;
reference the private let defaultsKey and the class KeybindingManager and ensure
the migration uses UserDefaults.standard (or your existing defaults instance) to
read legacy data, write it under defaultsKey, and delete the legacy key.

Comment on lines +215 to +216
private let key = "PoguRecentProjects"
private let lastOpenedKey = "PoguLastOpenedProject"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if there's any migration logic for UserDefaults keys in the codebase
rg -n "PPGRecentProjects|PPGLastOpenedProject|PPGOpenProjects" --type swift

Repository: 2witstudios/ppg-cli

Length of output: 45


🏁 Script executed:

# Search for migration-related code
rg -n "migrat|UserDefaults" --type swift | head -50

Repository: 2witstudios/ppg-cli

Length of output: 1322


🏁 Script executed:

# Search for any init methods or app startup code that might handle data migration
rg -n "func.*init|applicationDidFinishLaunching|application.*didFinishLaunchingWithOptions" --type swift -A 5

Repository: 2witstudios/ppg-cli

Length of output: 1686


🏁 Script executed:

# Examine AppDelegate's applicationDidFinishLaunching method more thoroughly
sed -n '6,50p' 'PPG CLI/PPG CLI/AppDelegate.swift'

Repository: 2witstudios/ppg-cli

Length of output: 1771


🏁 Script executed:

# Find the RecentProjects class and check its initialization
rg -n "class RecentProjects|struct RecentProjects" --type swift -A 20

Repository: 2witstudios/ppg-cli

Length of output: 1390


🏁 Script executed:

# Check if RecentProjects has an init method
rg -n "class RecentProjects" --type swift -A 50 | grep -E "init|private|func"

Repository: 2witstudios/ppg-cli

Length of output: 596


Add UserDefaults migration logic for existing users.

The UserDefaults keys have been renamed from PPGRecentProjects and PPGLastOpenedProject to PoguRecentProjects and PoguLastOpenedProject (also affects PPGOpenProjectsPoguOpenProjects at line 284). Existing users upgrading will lose their recent projects history since the app reads from the new keys which are empty.

Add a one-time migration on first launch that copies data from old keys to new keys, then removes the old keys to prevent stale data.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLI/Models.swift around lines 215 - 216, Add a one-time
UserDefaults migration that runs when this model is initialized: check for the
old keys "PPGRecentProjects", "PPGLastOpenedProject", and "PPGOpenProjects" and
if any exist copy their values into the new keys (key, lastOpenedKey, and the
openProjectsKey used at the code around line 284) using
UserDefaults.standard.set(...), then remove the old keys with
removeObject(forKey:). Ensure the migration is guarded so it only runs once
(e.g., detect presence of any old key or set a migrated flag) and preserve the
original value types (arrays/strings) when copying.

Comment on lines +89 to 90
let folder = (ctx.projectRoot as NSString).appendingPathComponent(".pogu/swarms")
guard let files = try? fm.contentsOfDirectory(atPath: folder) else { continue }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, locate the SwarmsView.swift file
find . -name "SwarmsView.swift" -type f

Repository: 2witstudios/ppg-cli

Length of output: 97


🏁 Script executed:

# Get file size to determine reading strategy
wc -l "PPG CLI/PPG CLI/SwarmsView.swift" 2>/dev/null || wc -l $(find . -name "SwarmsView.swift" -type f)

Repository: 2witstudios/ppg-cli

Length of output: 99


🏁 Script executed:

# Run the provided verification script to search for legacy/migration handling
rg -n --type=swift '\.pg/swarms|\.pogu/swarms' -C2

Repository: 2witstudios/ppg-cli

Length of output: 946


🏁 Script executed:

# Search for migration, legacy, or copy/move operations across the codebase
rg -n --type=swift 'migrat|legacy|moveItem|copyItem' -C2

Repository: 2witstudios/ppg-cli

Length of output: 4728


🏁 Script executed:

# Also check for any constants or string literals that define paths
rg -n --type=swift '(let|var|static).*swarms|\.pogu|\.pg' -B1 -A1

Repository: 2witstudios/ppg-cli

Length of output: 11898


🏁 Script executed:

# Get context around line 89 to see if there's fallback logic
sed -n '85,95p' "PPG CLI/PPG CLI/SwarmsView.swift"

Repository: 2witstudios/ppg-cli

Length of output: 682


🏁 Script executed:

# Get context around line 733 to see the write operation
sed -n '730,745p' "PPG CLI/PPG CLI/SwarmsView.swift"

Repository: 2witstudios/ppg-cli

Length of output: 788


🏁 Script executed:

# Search for any reference to old .pg directory or migration
rg -n '\.pg' --type=swift

Repository: 2witstudios/ppg-cli

Length of output: 698


Add backward-compatibility fallback for .pg/swarms location.

Line 89 reads only from .pogu/swarms. Users upgrading with existing swarm files in .pg/swarms will see no swarms. Add fallback scanning for the legacy path when the new path is empty, or implement a one-time migration to avoid data loss.

Additionally, the path .pogu/swarms is hardcoded identically at lines 89 and 733. Extract this to a constant to simplify future path changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLI/SwarmsView.swift around lines 89 - 90, Update
SwarmsView.swift to add backward-compatible fallback handling for the swarm
folder: replace the hardcoded ".pogu/swarms" occurrences with a single constant
(e.g., swarmsDirectoryName or SwarmsView.swarmsDirectory) and use that constant
wherever the path is constructed; when reading contents (the code using folder
and fm.contentsOfDirectory) if the new path returns empty or fails, attempt the
legacy ".pg/swarms" path and read from it (or perform a one-time migration by
moving files from ".pg/swarms" to the new constant path), ensuring the code uses
the same constant for both reads and writes so future path changes are
centralized.

Comment on lines +9 to +19
"sessionName": "pogu-test",
"worktrees": {
"wt-abc123": {
"id": "wt-abc123", "name": "feature-x", "path": "/tmp/test/.worktrees/wt-abc123",
"branch": "ppg/feature-x", "baseBranch": "main", "status": "active",
"branch": "pogu/feature-x", "baseBranch": "main", "status": "active",
"tmuxWindow": "ppg-test:1",
"agents": {
"ag-def456": {
"id": "ag-def456", "name": "claude", "agentType": "claude",
"status": "running", "tmuxTarget": "ppg-test:1",
"prompt": "Do something", "resultFile": "/tmp/test/.pg/results/ag-def456.md",
"prompt": "Do something", "resultFile": "/tmp/test/.pogu/results/ag-def456.md",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Complete the fixture rebrand for tmux targets.

The fixture now mixes pogu-test (session name) with ppg-test:1 (tmuxWindow/tmuxTarget). This can hide naming regressions in tests.

Suggested fix
-          "tmuxWindow": "ppg-test:1",
+          "tmuxWindow": "pogu-test:1",
...
-              "status": "running", "tmuxTarget": "ppg-test:1",
+              "status": "running", "tmuxTarget": "pogu-test:1",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"sessionName": "pogu-test",
"worktrees": {
"wt-abc123": {
"id": "wt-abc123", "name": "feature-x", "path": "/tmp/test/.worktrees/wt-abc123",
"branch": "ppg/feature-x", "baseBranch": "main", "status": "active",
"branch": "pogu/feature-x", "baseBranch": "main", "status": "active",
"tmuxWindow": "ppg-test:1",
"agents": {
"ag-def456": {
"id": "ag-def456", "name": "claude", "agentType": "claude",
"status": "running", "tmuxTarget": "ppg-test:1",
"prompt": "Do something", "resultFile": "/tmp/test/.pg/results/ag-def456.md",
"prompt": "Do something", "resultFile": "/tmp/test/.pogu/results/ag-def456.md",
"sessionName": "pogu-test",
"worktrees": {
"wt-abc123": {
"id": "wt-abc123", "name": "feature-x", "path": "/tmp/test/.worktrees/wt-abc123",
"branch": "pogu/feature-x", "baseBranch": "main", "status": "active",
"tmuxWindow": "pogu-test:1",
"agents": {
"ag-def456": {
"id": "ag-def456", "name": "claude", "agentType": "claude",
"status": "running", "tmuxTarget": "pogu-test:1",
"prompt": "Do something", "resultFile": "/tmp/test/.pogu/results/ag-def456.md",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PPG` CLI/PPG CLITests/PPG_CLITests.swift around lines 9 - 19, The test
fixture mixes sessionName "pogu-test" with tmux values "ppg-test:1"; update the
fixture so tmuxWindow and tmuxTarget use the session name (e.g., "pogu-test:1")
to match sessionName and avoid naming regressions—specifically change the
tmuxWindow in the worktree object (wt-abc123) and the tmuxTarget in the agent
object (ag-def456) to use "pogu-test:1" and verify other fixture entries use the
same sessionName consistently.

Comment thread src/commands/init.ts
Comment on lines +17 to 21
You are operating on the master branch of a pogu-managed project.

## Critical Rule
**NEVER make code changes directly on the master branch.** Use \`ppg spawn\` to create worktrees.
**NEVER make code changes directly on the master branch.** Use \`pogu spawn\` to create worktrees.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Generated conductor context hardcodes master branch.

This can mislead users/automation in repositories using main (or another default branch). Prefer “default branch” wording.

✏️ Suggested wording update
-You are operating on the master branch of a pogu-managed project.
+You are operating on the default branch of a pogu-managed project (usually `main`).
@@
-**NEVER make code changes directly on the master branch.** Use `pogu spawn` to create worktrees.
+**NEVER make code changes directly on the default branch.** Use `pogu spawn` to create worktrees.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
You are operating on the master branch of a pogu-managed project.
## Critical Rule
**NEVER make code changes directly on the master branch.** Use \`ppg spawn\` to create worktrees.
**NEVER make code changes directly on the master branch.** Use \`pogu spawn\` to create worktrees.
You are operating on the default branch of a pogu-managed project (usually `main`).
## Critical Rule
**NEVER make code changes directly on the default branch.** Use `pogu spawn` to create worktrees.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/init.ts` around lines 17 - 21, Update the user-facing text in
src/commands/init.ts that currently hardcodes the string "master" (look for
messages or help text referencing "master branch") to say "default branch"
instead and remove any implication that the repo's default branch is named
master; if the code programmatically uses the literal "master" in prompts or
logging, replace that with a dynamic reference to the repository's default
branch (or a neutral phrase "default branch") and ensure any guidance still
instructs users to use `pogu spawn` to create worktrees rather than modifying
the default branch directly.

Comment thread src/commands/init.ts
Comment on lines +88 to 89
info('Created .pogu/ directory structure');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

--json mode is not machine-readable due to unconditional logs and direct console.log.

initCommand emits info(...) messages regardless of options.json, then prints JSON manually. This breaks parsable JSON output for automation.

✅ Proposed fix
-import { success, info } from '../lib/output.js';
+import { success, info, output } from '../lib/output.js';
@@
 export async function initCommand(options: { json?: boolean }): Promise<void> {
+  const json = options.json ?? false;
+  const logInfo = (message: string): void => {
+    if (!json) info(message);
+  };
   const cwd = process.cwd();
@@
-  info('Created .pogu/ directory structure');
+  logInfo('Created .pogu/ directory structure');
@@
-    info('config.yaml already exists, skipping');
+    logInfo('config.yaml already exists, skipping');
@@
-    info('Wrote default config.yaml');
+    logInfo('Wrote default config.yaml');
@@
-  info('Wrote empty manifest.json');
+  logInfo('Wrote empty manifest.json');
@@
-  info('Updated .gitignore');
+  logInfo('Updated .gitignore');
@@
-    info('Wrote sample template: default.md');
+    logInfo('Wrote sample template: default.md');
@@
-      info(`Wrote prompt: ${name}.md`);
+      logInfo(`Wrote prompt: ${name}.md`);
@@
-      info(`Wrote swarm template: ${name}.yaml`);
+      logInfo(`Wrote swarm template: ${name}.yaml`);
@@
-  info('Wrote conductor-context.md');
+  logInfo('Wrote conductor-context.md');
@@
-    info('Registered pogu Claude Code plugin');
+    logInfo('Registered pogu Claude Code plugin');
@@
-  if (options.json) {
-    console.log(JSON.stringify({
+  if (json) {
+    output({
       success: true,
       projectRoot,
       sessionName,
       poguDir: poguDir(projectRoot),
       pluginRegistered,
-    }));
+    }, true);
   } else {
     success(`pogu initialized in ${projectRoot}`);
   }
 }
As per coding guidelines, `src/commands/**/*.ts`: “Every command must support `--json` flag for machine-readable output. Use `output(data, json)` and `outputError(error, json)` from `lib/output.ts`”.

Also applies to: 94-98, 105-109, 117-118, 127-128, 138-139, 145-145, 150-150, 153-163

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/init.ts` around lines 88 - 89, The initCommand currently emits
unconditional info(...) logs and uses console.log which breaks --json mode;
update initCommand to stop emitting plain info/console output when options.json
is true and instead call output(data, options.json) for successful results and
outputError(err, options.json) for failures; replace each unconditional
info(...) and console.log in initCommand (and the other noted message sites
inside the same file) with the appropriate output(...) call, and wrap any
human-readable info(...) calls behind if (!options.json) so interactive output
remains available when JSON mode is off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant