nightshift-mcp 1.0.0 → 1.0.3

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 CHANGED
@@ -12,12 +12,17 @@ An MCP (Model Context Protocol) server that enables multi-agent communication an
12
12
 
13
13
  - **Multi-agent chat**: Structured messages with agent name, timestamp, type, and content
14
14
  - **Failover handling**: Seamless handoffs when an agent hits limits
15
- - **Ralph-style PRD management**: Work through user stories in prd.json
15
+ - **Ralph-style PRD management**: Work through user stories in prd.json with Zod-validated schemas and helpful error messages
16
16
  - **Progress tracking**: Shared learnings via progress.txt
17
- - **Agent tracking**: See which agents are active and what they're working on
17
+ - **Agent spawning & orchestration**: Spawn Claude, Codex, Gemini, or Vibe as subprocesses with full lifecycle tracking
18
+ - **Autonomous orchestration**: Single `orchestrate` tool runs a claim→implement→complete loop until all stories pass
19
+ - **Agent status tracking**: Monitor spawned agents by PID, check exit codes, and tail output in real-time
20
+ - **Smart retry**: Automatically suggests or uses a different agent when one fails
21
+ - **Workflow management**: Phases, strategic decisions, and agent assignments
18
22
  - **Watch/polling**: Monitor for new messages with cursor-based polling
19
23
  - **Auto-archiving**: Archive old messages to keep the chat file manageable
20
- - **Universal compatibility**: Works with any MCP-supporting tool
24
+ - **Cross-platform**: Works on Windows, Linux, and macOS (uses cross-spawn and platform-safe process management)
25
+ - **Universal compatibility**: Works with any MCP-supporting tool (42 tools across 8 categories)
21
26
  - **Simple file-based storage**: No external services required
22
27
 
23
28
  ## Installation
@@ -27,6 +32,11 @@ An MCP (Model Context Protocol) server that enables multi-agent communication an
27
32
  npm install -g nightshift-mcp
28
33
  ```
29
34
 
35
+ **Updating:**
36
+ ```bash
37
+ npm update -g nightshift-mcp
38
+ ```
39
+
30
40
  **Or build from source:**
31
41
  ```bash
32
42
  git clone <repo-url>
@@ -44,11 +54,8 @@ npm link # makes 'nightshift-mcp' available globally
44
54
  {
45
55
  "mcpServers": {
46
56
  "nightshift": {
47
- "command": "node",
48
- "args": ["/path/to/nightshift-mcp/dist/index.js"],
49
- "env": {
50
- "ROBOT_CHAT_PROJECT_PATH": "${PWD}"
51
- }
57
+ "command": "nightshift-mcp",
58
+ "args": []
52
59
  }
53
60
  }
54
61
  }
@@ -58,11 +65,12 @@ npm link # makes 'nightshift-mcp' available globally
58
65
 
59
66
  ```toml
60
67
  [mcp_servers.nightshift]
61
- command = "node"
62
- args = ["/path/to/nightshift-mcp/dist/index.js"]
63
- env = { ROBOT_CHAT_PROJECT_PATH = "${PWD}" }
68
+ command = "nightshift-mcp"
69
+ args = []
64
70
  ```
65
71
 
72
+ The server automatically uses the current working directory for the `.robot-chat/` folder. You can override this with the `ROBOT_CHAT_PROJECT_PATH` environment variable if needed.
73
+
66
74
  ## Usage
67
75
 
68
76
  For agents to communicate, they must be running in the **same project directory**. The chat file is created at `<project>/.robot-chat/chat.txt` based on where each CLI is started.
@@ -261,7 +269,6 @@ NightShift includes Ralph-compatible PRD and progress management, enabling struc
261
269
  ```json
262
270
  {
263
271
  "project": "MyApp",
264
- "branchName": "feature/my-feature",
265
272
  "description": "Feature description",
266
273
  "userStories": [
267
274
  {
@@ -281,6 +288,37 @@ NightShift includes Ralph-compatible PRD and progress management, enabling struc
281
288
  }
282
289
  ```
283
290
 
291
+ ### PRD Schema
292
+
293
+ | Field | Type | Required | Default | Description |
294
+ |-------|------|----------|---------|-------------|
295
+ | `project` | string | no | — | Project name |
296
+ | `description` | string | no | "" | Project description |
297
+ | **`userStories`** | array | **yes** | — | Array of user story objects |
298
+
299
+ **User Story fields:**
300
+
301
+ | Field | Type | Required | Default | Description |
302
+ |-------|------|----------|---------|-------------|
303
+ | **`id`** | string | **yes** | — | Unique ID (e.g., "US-001") |
304
+ | **`title`** | string | **yes** | — | Short title |
305
+ | `description` | string | no | "" | Detailed description |
306
+ | `acceptanceCriteria` | string[] | no | [] | Criteria for completion |
307
+ | `priority` | number | no | 999 | Lower = higher priority |
308
+ | `passes` | boolean | no | false | Whether the story is complete |
309
+ | `notes` | string | no | "" | Implementation notes |
310
+
311
+ ### PRD Validation
312
+
313
+ NightShift validates your `prd.json` with Zod schemas and provides helpful error messages when common mistakes are detected:
314
+
315
+ - Using `stories` instead of `userStories` → suggests the correct field name
316
+ - Using `acceptance_criteria` instead of `acceptanceCriteria` → suggests the correct field name
317
+ - Missing required fields (`id`, `title`) → identifies which story has the issue
318
+ - Optional fields default gracefully (`passes` → false, `notes` → "", `acceptanceCriteria` → [])
319
+
320
+ Use `nightshift_setup(showExamples: true)` for the full schema reference and examples.
321
+
284
322
  2. Agents use these tools to work through stories:
285
323
 
286
324
  ### PRD Tools
@@ -472,6 +510,50 @@ rollback_savepoint("US-002")
472
510
  # → All changes after US-002 discarded
473
511
  ```
474
512
 
513
+ ## Workflow Management
514
+
515
+ NightShift includes workflow tools for tracking project phases, recording strategic decisions, and managing agent assignments.
516
+
517
+ ### Workflow Tools
518
+
519
+ #### `init_workflow`
520
+ Initialize a new workflow with a project goal and optional custom phases.
521
+
522
+ **Parameters:**
523
+ - `projectGoal` (required): High-level goal of the project
524
+ - `phases` (optional): Custom phases (default: research, decisions, planning, build, test, report)
525
+
526
+ #### `get_workflow_state`
527
+ Get the current workflow state including phase, assignments, and decisions.
528
+
529
+ #### `advance_phase`
530
+ Advance to the next workflow phase when the current phase's exit criteria are met.
531
+
532
+ #### `set_phase`
533
+ Manually set the workflow to a specific phase.
534
+
535
+ **Parameters:**
536
+ - `phase` (required): Target phase (research, decisions, planning, build, test, report, complete)
537
+
538
+ #### `record_decision`
539
+ Record a strategic decision with rationale for future reference.
540
+
541
+ **Parameters:**
542
+ - `topic` (required): What the decision is about
543
+ - `options` (required): Options that were considered
544
+ - `chosen` (required): The chosen option
545
+ - `rationale` (required): Why this option was chosen
546
+ - `decidedBy` (required): Agent or person who decided
547
+
548
+ #### `get_decisions`
549
+ Get all recorded decisions, optionally filtered by topic.
550
+
551
+ #### `get_active_assignments`
552
+ Get all stories currently being worked on by agents.
553
+
554
+ #### `clear_assignment`
555
+ Clear a story assignment (for abandonment/failover scenarios).
556
+
475
557
  ## Setup & Debugging
476
558
 
477
559
  NightShift includes self-service tools for setup and troubleshooting.
@@ -512,14 +594,14 @@ nightshift_debug
512
594
  # Returns detailed diagnostic report with suggested fixes
513
595
  ```
514
596
 
515
- ## Agent Spawning (Autonomous Orchestration)
597
+ ## Agent Spawning & Orchestration
516
598
 
517
599
  One agent can spawn others as subprocesses, enabling fully autonomous multi-agent workflows with minimal user intervention.
518
600
 
519
- ### Tools
601
+ ### Spawning Tools
520
602
 
521
603
  #### `list_available_agents`
522
- Check which agent CLIs (claude, codex, gemini, vibe) are installed.
604
+ Check which agent CLIs (claude, codex, gemini, vibe) are installed and ready to run.
523
605
 
524
606
  #### `spawn_agent`
525
607
  Spawn another agent as a subprocess and wait for completion.
@@ -535,16 +617,14 @@ spawn_agent(agent: "codex", prompt: "Fix the type errors in src/utils.ts")
535
617
  ```
536
618
 
537
619
  #### `spawn_agent_background`
538
- Spawn an agent in the background (non-blocking).
620
+ Spawn an agent in the background (non-blocking). Returns immediately with PID and output file path.
539
621
 
540
622
  **Parameters:**
541
623
  - `agent` (required): "claude", "codex", "gemini", or "vibe"
542
624
  - `prompt` (required): Task/prompt to send
543
625
 
544
- Returns immediately with PID and output file path.
545
-
546
626
  #### `delegate_story`
547
- Delegate a PRD user story to another agent with full context.
627
+ Delegate a PRD user story to another agent with full context. On failure, returns a `retryHint` suggesting alternative available agents.
548
628
 
549
629
  **Parameters:**
550
630
  - `agent` (required): "claude", "codex", "gemini", or "vibe"
@@ -562,8 +642,51 @@ The spawned agent receives:
562
642
  - Recent chat messages for context
563
643
  - Instructions to use nightshift tools for coordination
564
644
 
645
+ #### `delegate_research`
646
+ Delegate a research or planning task to Gemini. Ideal for read-only tasks like codebase analysis, architecture planning, code review, and documentation.
647
+
648
+ **Parameters:**
649
+ - `task` (required): The research/planning task description
650
+ - `context` (optional): Additional context to provide
651
+ - `background` (optional): Run in background (default: false)
652
+
653
+ ### Monitoring Tools
654
+
655
+ #### `get_agent_status`
656
+ Check the status of a spawned background agent by PID.
657
+
658
+ **Parameters:**
659
+ - `pid` (required): Process ID of the spawned agent
660
+
661
+ **Returns:**
662
+ - Whether the agent is still running or has exited
663
+ - Exit code (if finished)
664
+ - Last 30 lines of output
665
+ - Story assignment (if delegated via `delegate_story`)
666
+
667
+ #### `list_running_agents`
668
+ List all agents spawned in the current session with their status.
669
+
670
+ **Returns:** Array of agents with PID, agent type, running/exited status, elapsed time, and story assignment.
671
+
672
+ ### Orchestration
673
+
674
+ #### `orchestrate`
675
+ Run an autonomous orchestration loop that claims stories, implements them, and marks them complete until all work is done. This is the highest-level automation tool.
676
+
677
+ **Parameters:**
678
+ - `agent` (optional): Your agent name (default: "NightShift")
679
+ - `maxIterations` (optional): Maximum stories to process (default: 50)
680
+ - `mode` (optional): "stories", "bugs", or "all" (default: "all")
681
+
565
682
  ### Orchestration Patterns
566
683
 
684
+ **Fully autonomous (recommended):**
685
+ ```
686
+ orchestrate(agent: "Claude", mode: "all")
687
+ # Runs until all stories and bugs are complete
688
+ ```
689
+
567
690
  **Sequential delegation:**
568
691
  ```
569
692
  delegate_story(agent: "codex") # Wait for completion
@@ -575,11 +698,14 @@ delegate_story(agent: "gemini") # Then delegate next
575
698
  delegate_story(agent: "codex", storyId: "US-001", background: true)
576
699
  delegate_story(agent: "gemini", storyId: "US-002", background: true)
577
700
  # Work on US-003 yourself while they run in parallel
701
+ # Monitor with get_agent_status or list_running_agents
578
702
  ```
579
703
 
580
- **Ad-hoc task delegation:**
704
+ **Research then implement:**
581
705
  ```
582
- spawn_agent(agent: "claude", prompt: "Review the auth module and suggest improvements")
706
+ delegate_research(task: "Analyze auth patterns and recommend approach")
707
+ # Use findings to inform implementation
708
+ delegate_story(agent: "codex", storyId: "US-001")
583
709
  ```
584
710
 
585
711
  ## NightShift Daemon (Continuous Orchestration)
@@ -604,9 +730,10 @@ The daemon provides hands-off multi-agent orchestration:
604
730
  1. **Event-Driven**: Watches `prd.json` and `chat.txt` for changes
605
731
  2. **Auto-Spawning**: Spawns agents for orphaned stories (up to concurrency limit)
606
732
  3. **Failover Handling**: Automatically claims and reassigns failover requests
607
- 4. **Health Checks**: Periodic reconciliation as a fallback (default: every 2 min)
608
- 5. **Poison Pill Protection**: Quarantines stories that fail repeatedly
609
- 6. **Stuck Detection**: Kills agents that haven't reported activity
733
+ 4. **Smart Retry**: Tracks failed agents per story and tries a different agent on retry
734
+ 5. **Health Checks**: Periodic reconciliation as a fallback (default: every 2 min)
735
+ 6. **Poison Pill Protection**: Quarantines stories that fail repeatedly
736
+ 7. **Stuck Detection**: Kills agents that haven't reported activity
610
737
 
611
738
  ### Options
612
739
 
@@ -663,7 +790,9 @@ The daemon provides hands-off multi-agent orchestration:
663
790
  4. **Document learnings**: Progress.txt helps future iterations
664
791
  5. **Handle failovers**: Check for and claim failovers at the start of each session
665
792
  6. **Use delegation**: One orchestrating agent can spawn others for parallel work
666
- 7. **Add `.robot-chat/` to your project's `.gitignore`**: Chat logs are ephemeral and shouldn't be committed
793
+ 7. **Monitor background agents**: Use `get_agent_status` and `list_running_agents` to track spawned agents
794
+ 8. **Use `orchestrate` for full autonomy**: The `orchestrate` tool handles the entire claim→implement→complete loop
795
+ 9. **Add `.robot-chat/` to your project's `.gitignore`**: Chat logs are ephemeral and shouldn't be committed
667
796
 
668
797
  ## License
669
798
 
@@ -1,4 +1,43 @@
1
1
  export type AgentType = "claude" | "codex" | "gemini" | "vibe";
2
+ export interface TrackedAgent {
3
+ agent: AgentType;
4
+ pid: number | undefined;
5
+ outputFile: string;
6
+ startTime: number;
7
+ storyId?: string;
8
+ prompt: string;
9
+ }
10
+ /**
11
+ * Update a tracked agent's metadata (e.g., attach a storyId after spawning)
12
+ */
13
+ export declare function updateTrackedAgent(pid: number, update: {
14
+ storyId?: string;
15
+ }): void;
16
+ /**
17
+ * Get the status of a tracked agent by PID
18
+ */
19
+ export declare function getTrackedAgentStatus(pid: number): {
20
+ found: boolean;
21
+ running?: boolean;
22
+ agent?: AgentType;
23
+ outputFile?: string;
24
+ startTime?: number;
25
+ storyId?: string;
26
+ exitCode?: number | null;
27
+ tailOutput?: string;
28
+ };
29
+ /**
30
+ * List all tracked agents with their current status
31
+ */
32
+ export declare function listTrackedAgents(): Array<{
33
+ pid: number | undefined;
34
+ agent: AgentType;
35
+ outputFile: string;
36
+ startTime: number;
37
+ storyId?: string;
38
+ running: boolean;
39
+ elapsedSeconds: number;
40
+ }>;
2
41
  export interface SpawnOptions {
3
42
  agent: AgentType;
4
43
  prompt: string;
@@ -15,13 +54,11 @@ export interface SpawnResult {
15
54
  }
16
55
  /**
17
56
  * Spawn an AI agent as a subprocess
18
- * For agents requiring PTY, uses script command to allocate one
19
57
  */
20
58
  export declare function spawnAgent(options: SpawnOptions): Promise<SpawnResult>;
21
59
  /**
22
60
  * Spawn an agent in the background (non-blocking)
23
- * Uses safe prompt escaping to prevent command injection
24
- * Uses PTY allocation via `script` command for agents that require it (like Codex)
61
+ * Uses a Node.js wrapper script for cross-platform compatibility
25
62
  */
26
63
  export declare function spawnAgentBackground(options: SpawnOptions): {
27
64
  pid: number | undefined;
@@ -33,7 +70,7 @@ export declare function spawnAgentBackground(options: SpawnOptions): {
33
70
  */
34
71
  export declare function isAgentAvailable(agent: AgentType): Promise<boolean>;
35
72
  /**
36
- * Check if an agent can actually run (verifies PTY requirements are met)
73
+ * Check if an agent can actually run
37
74
  */
38
75
  export declare function canAgentRun(agent: AgentType): Promise<{
39
76
  available: boolean;
@@ -41,7 +78,7 @@ export declare function canAgentRun(agent: AgentType): Promise<{
41
78
  reason?: string;
42
79
  }>;
43
80
  /**
44
- * Get list of available agents with their run status
81
+ * Get list of available agents
45
82
  */
46
83
  export declare function getAvailableAgents(): Promise<AgentType[]>;
47
84
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-spawner.d.ts","sourceRoot":"","sources":["../src/agent-spawner.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAI/D,MAAM,WAAW,YAAY;IAE3B,KAAK,EAAE,SAAS,CAAC;IAEjB,MAAM,EAAE,MAAM,CAAC;IAEf,WAAW,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,OAAO,CAAC;CAEtB;AAID,MAAM,WAAW,WAAW;IAE1B,OAAO,EAAE,OAAO,CAAC;IAEjB,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,KAAK,CAAC,EAAE,MAAM,CAAC;CAEhB;AAuFD;;;GAGG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAsG5E;AAmJD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG;IAC3D,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAwHA;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAczE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC;IAC3D,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAyBD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAW/D;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAC7C,MAAM,CAAC,SAAS,EAAE;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAC5E,CAYA"}
1
+ {"version":3,"file":"agent-spawner.d.ts","sourceRoot":"","sources":["../src/agent-spawner.ts"],"names":[],"mappings":"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"}