pilotlynx 0.0.1 → 0.1.1
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/LICENSE +21 -0
- package/README.md +345 -0
- package/dist/agents/improve.agent.d.ts +2 -0
- package/dist/agents/improve.agent.js +54 -0
- package/dist/agents/improve.agent.js.map +1 -0
- package/dist/agents/project-add.agent.d.ts +2 -0
- package/dist/agents/project-add.agent.js +26 -0
- package/dist/agents/project-add.agent.js.map +1 -0
- package/dist/agents/project-create.agent.d.ts +2 -0
- package/dist/agents/project-create.agent.js +25 -0
- package/dist/agents/project-create.agent.js.map +1 -0
- package/dist/agents/run.agent.d.ts +3 -0
- package/dist/agents/run.agent.js +37 -0
- package/dist/agents/run.agent.js.map +1 -0
- package/dist/agents/secrets-migration.agent.d.ts +15 -0
- package/dist/agents/secrets-migration.agent.js +63 -0
- package/dist/agents/secrets-migration.agent.js.map +1 -0
- package/dist/agents/sync-template.agent.d.ts +2 -0
- package/dist/agents/sync-template.agent.js +21 -0
- package/dist/agents/sync-template.agent.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +66 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cost.d.ts +2 -0
- package/dist/commands/cost.js +96 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +39 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/env.d.ts +2 -0
- package/dist/commands/env.js +26 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/improve.d.ts +2 -0
- package/dist/commands/improve.js +43 -0
- package/dist/commands/improve.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +131 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/insights.d.ts +2 -0
- package/dist/commands/insights.js +45 -0
- package/dist/commands/insights.js.map +1 -0
- package/dist/commands/link.d.ts +2 -0
- package/dist/commands/link.js +27 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +75 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/project.d.ts +4 -0
- package/dist/commands/project.js +127 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/projects.d.ts +2 -0
- package/dist/commands/projects.js +22 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/relay.d.ts +2 -0
- package/dist/commands/relay.js +171 -0
- package/dist/commands/relay.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +49 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/schedule.d.ts +2 -0
- package/dist/commands/schedule.js +158 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +62 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +23 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/unlink.d.ts +2 -0
- package/dist/commands/unlink.js +26 -0
- package/dist/commands/unlink.js.map +1 -0
- package/dist/commands/verify.d.ts +2 -0
- package/dist/commands/verify.js +32 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/lib/agent-runner.d.ts +10 -0
- package/dist/lib/agent-runner.js +133 -0
- package/dist/lib/agent-runner.js.map +1 -0
- package/dist/lib/bash-security.d.ts +5 -0
- package/dist/lib/bash-security.js +83 -0
- package/dist/lib/bash-security.js.map +1 -0
- package/dist/lib/callbacks.d.ts +3 -0
- package/dist/lib/callbacks.js +77 -0
- package/dist/lib/callbacks.js.map +1 -0
- package/dist/lib/command-ops/doctor-ops.d.ts +8 -0
- package/dist/lib/command-ops/doctor-ops.js +197 -0
- package/dist/lib/command-ops/doctor-ops.js.map +1 -0
- package/dist/lib/command-ops/env-ops.d.ts +12 -0
- package/dist/lib/command-ops/env-ops.js +53 -0
- package/dist/lib/command-ops/env-ops.js.map +1 -0
- package/dist/lib/command-ops/improve-ops.d.ts +12 -0
- package/dist/lib/command-ops/improve-ops.js +77 -0
- package/dist/lib/command-ops/improve-ops.js.map +1 -0
- package/dist/lib/command-ops/link-ops.d.ts +17 -0
- package/dist/lib/command-ops/link-ops.js +74 -0
- package/dist/lib/command-ops/link-ops.js.map +1 -0
- package/dist/lib/command-ops/project-ops.d.ts +12 -0
- package/dist/lib/command-ops/project-ops.js +56 -0
- package/dist/lib/command-ops/project-ops.js.map +1 -0
- package/dist/lib/command-ops/run-ops.d.ts +10 -0
- package/dist/lib/command-ops/run-ops.js +59 -0
- package/dist/lib/command-ops/run-ops.js.map +1 -0
- package/dist/lib/command-ops/secrets-migration-ops.d.ts +29 -0
- package/dist/lib/command-ops/secrets-migration-ops.js +169 -0
- package/dist/lib/command-ops/secrets-migration-ops.js.map +1 -0
- package/dist/lib/command-ops/status-ops.d.ts +19 -0
- package/dist/lib/command-ops/status-ops.js +95 -0
- package/dist/lib/command-ops/status-ops.js.map +1 -0
- package/dist/lib/command-ops/sync-ops.d.ts +5 -0
- package/dist/lib/command-ops/sync-ops.js +15 -0
- package/dist/lib/command-ops/sync-ops.js.map +1 -0
- package/dist/lib/command-ops/verify-ops.d.ts +7 -0
- package/dist/lib/command-ops/verify-ops.js +12 -0
- package/dist/lib/command-ops/verify-ops.js.map +1 -0
- package/dist/lib/config.d.ts +36 -0
- package/dist/lib/config.js +118 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/cron.d.ts +3 -0
- package/dist/lib/cron.js +61 -0
- package/dist/lib/cron.js.map +1 -0
- package/dist/lib/env-loader.d.ts +1 -0
- package/dist/lib/env-loader.js +8 -0
- package/dist/lib/env-loader.js.map +1 -0
- package/dist/lib/global-config.d.ts +7 -0
- package/dist/lib/global-config.js +50 -0
- package/dist/lib/global-config.js.map +1 -0
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.js +26 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/observation.d.ts +3 -0
- package/dist/lib/observation.js +48 -0
- package/dist/lib/observation.js.map +1 -0
- package/dist/lib/policy.d.ts +3 -0
- package/dist/lib/policy.js +15 -0
- package/dist/lib/policy.js.map +1 -0
- package/dist/lib/project.d.ts +9 -0
- package/dist/lib/project.js +127 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/prompts.d.ts +3 -0
- package/dist/lib/prompts.js +49 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/registry.d.ts +12 -0
- package/dist/lib/registry.js +90 -0
- package/dist/lib/registry.js.map +1 -0
- package/dist/lib/relay/channel.d.ts +31 -0
- package/dist/lib/relay/channel.js +69 -0
- package/dist/lib/relay/channel.js.map +1 -0
- package/dist/lib/relay/chat.d.ts +2 -0
- package/dist/lib/relay/chat.js +77 -0
- package/dist/lib/relay/chat.js.map +1 -0
- package/dist/lib/relay/config.d.ts +5 -0
- package/dist/lib/relay/config.js +22 -0
- package/dist/lib/relay/config.js.map +1 -0
- package/dist/lib/relay/history.d.ts +3 -0
- package/dist/lib/relay/history.js +62 -0
- package/dist/lib/relay/history.js.map +1 -0
- package/dist/lib/relay/locks.d.ts +9 -0
- package/dist/lib/relay/locks.js +45 -0
- package/dist/lib/relay/locks.js.map +1 -0
- package/dist/lib/relay/notify.d.ts +6 -0
- package/dist/lib/relay/notify.js +168 -0
- package/dist/lib/relay/notify.js.map +1 -0
- package/dist/lib/relay/router.d.ts +2 -0
- package/dist/lib/relay/router.js +191 -0
- package/dist/lib/relay/router.js.map +1 -0
- package/dist/lib/relay/service.d.ts +9 -0
- package/dist/lib/relay/service.js +222 -0
- package/dist/lib/relay/service.js.map +1 -0
- package/dist/lib/relay/types.d.ts +47 -0
- package/dist/lib/relay/types.js +31 -0
- package/dist/lib/relay/types.js.map +1 -0
- package/dist/lib/sandbox.d.ts +24 -0
- package/dist/lib/sandbox.js +83 -0
- package/dist/lib/sandbox.js.map +1 -0
- package/dist/lib/schedule.d.ts +16 -0
- package/dist/lib/schedule.js +92 -0
- package/dist/lib/schedule.js.map +1 -0
- package/dist/lib/secrets-migration.d.ts +35 -0
- package/dist/lib/secrets-migration.js +119 -0
- package/dist/lib/secrets-migration.js.map +1 -0
- package/dist/lib/secrets.d.ts +1 -0
- package/dist/lib/secrets.js +45 -0
- package/dist/lib/secrets.js.map +1 -0
- package/dist/lib/shell-escape.d.ts +3 -0
- package/dist/lib/shell-escape.js +6 -0
- package/dist/lib/shell-escape.js.map +1 -0
- package/dist/lib/tools.d.ts +5 -0
- package/dist/lib/tools.js +26 -0
- package/dist/lib/tools.js.map +1 -0
- package/dist/lib/types.d.ts +156 -0
- package/dist/lib/types.js +56 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/validation.d.ts +4 -0
- package/dist/lib/validation.js +26 -0
- package/dist/lib/validation.js.map +1 -0
- package/package.json +75 -12
- package/prompts/improve.yaml +15 -0
- package/prompts/project-add.yaml +43 -0
- package/prompts/project-create.yaml +28 -0
- package/prompts/relay-chat.yaml +24 -0
- package/prompts/run.yaml +9 -0
- package/prompts/secrets-migration.yaml +35 -0
- package/prompts/sync-template.yaml +18 -0
- package/template/.claude/rules/.gitkeep +0 -0
- package/template/.claude/settings.json +17 -0
- package/template/.claude/skills/.gitkeep +0 -0
- package/template/.mcp.json +3 -0
- package/template/CLAUDE.md +79 -0
- package/template/PROJECT_BRIEF.md +22 -0
- package/template/RUNBOOK.md +45 -0
- package/template/artifacts/.gitkeep +0 -0
- package/template/logs/.gitkeep +0 -0
- package/template/memory/MEMORY.md +15 -0
- package/template/schedule.yaml +9 -0
- package/template/workflows/daily_feedback.ts +24 -0
- package/template/workflows/project_review.ts +24 -0
- package/template/workflows/task_execute.ts +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 PilotLynx Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# PilotLynx
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/pilotlynx)
|
|
4
|
+
[](https://github.com/pilotlynx/pilotlynx/actions/workflows/ci.yml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://nodejs.org/)
|
|
7
|
+
|
|
8
|
+
Local monorepo orchestration for Claude Agent SDK workflows. One CLI to manage project scaffolding, policy-gated secrets, cron scheduling, and cross-project self-improvement.
|
|
9
|
+
|
|
10
|
+
## What Makes PilotLynx Different
|
|
11
|
+
|
|
12
|
+
Three features that don't exist in other AI workflow tools:
|
|
13
|
+
|
|
14
|
+
### Cron Ping
|
|
15
|
+
|
|
16
|
+
Define cron schedules per project. PilotLynx uses tick-based scheduling — no daemon, no background process. You run `plynx schedule tick` from a system cron entry and it figures out what's due.
|
|
17
|
+
|
|
18
|
+
**`schedule.yaml`** (in each project):
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
schedules:
|
|
22
|
+
- workflow: daily_feedback
|
|
23
|
+
cron: "0 9 * * *"
|
|
24
|
+
timezone: America/New_York
|
|
25
|
+
catchUpPolicy: run_latest
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**How a tick works:**
|
|
29
|
+
|
|
30
|
+
1. Read every project's `schedule.yaml`
|
|
31
|
+
2. Compare cron expressions against last recorded run times
|
|
32
|
+
3. Apply the catch-up policy to any missed runs
|
|
33
|
+
4. Execute due workflows and record the new last-run time
|
|
34
|
+
|
|
35
|
+
**Catch-up policies** (when the machine was off or tick didn't fire):
|
|
36
|
+
|
|
37
|
+
| Policy | Behavior |
|
|
38
|
+
|--------|----------|
|
|
39
|
+
| `run_latest` | Run only the most recent missed occurrence (default) |
|
|
40
|
+
| `run_all` | Run every missed occurrence in order |
|
|
41
|
+
| `skip` | Discard all missed runs, wait for the next future occurrence |
|
|
42
|
+
|
|
43
|
+
Missed runs older than **7 days** are always discarded regardless of policy.
|
|
44
|
+
|
|
45
|
+
`plynx init` auto-installs a system cron entry (`*/15 * * * *`) so scheduling works out of the box. Each tick also runs the self-improvement loop automatically (once per 24h, configurable).
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
plynx schedule status myproject # see what's scheduled, last/next runs
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Self-Improvement Loop
|
|
52
|
+
|
|
53
|
+
`plynx improve` triggers a two-phase cycle that makes projects learn from their own run history:
|
|
54
|
+
|
|
55
|
+
**Phase 1 — Observation (Lynx-owned, read-only):** Reads conversation logs, user feedback, and run outcomes across all projects. Produces per-project summaries and cross-project insights (stored in `pilotlynx/shared/insights/`).
|
|
56
|
+
|
|
57
|
+
**Phase 2 — Improvement (project-owned, Lynx-triggered):** Invokes each project's `daily_feedback` workflow with the distilled summary. The project's own agent decides what to update — brief, runbook, skills, or memory.
|
|
58
|
+
|
|
59
|
+
Key design constraint: **Lynx never writes project files.** The orchestrator observes and triggers; only the project's own agent modifies its files.
|
|
60
|
+
|
|
61
|
+
Auto-runs via `schedule tick` once per 24h. Manual trigger anytime with `plynx improve`. Toggle in `plynx.yaml`:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
autoImprove:
|
|
65
|
+
enabled: false # default: true
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
plynx insights # view cross-project insights
|
|
70
|
+
plynx insights --since 2025-01-10 # filter by date
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Shared Env
|
|
74
|
+
|
|
75
|
+
One `.env` file, per-project allowlists. A project sees only the secrets its policy permits — injected at runtime, never written to files.
|
|
76
|
+
|
|
77
|
+
**`pilotlynx/shared/policies/secrets-access.yaml`:**
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
version: 1
|
|
81
|
+
shared:
|
|
82
|
+
- ANTHROPIC_API_KEY # every project gets this
|
|
83
|
+
|
|
84
|
+
projects:
|
|
85
|
+
my-web-app:
|
|
86
|
+
allowed:
|
|
87
|
+
- GITHUB_TOKEN
|
|
88
|
+
- DATABASE_URL
|
|
89
|
+
mappings:
|
|
90
|
+
SLACK_URL: SLACK_WEBHOOK # project sees SLACK_URL, sourced from .env's SLACK_WEBHOOK
|
|
91
|
+
|
|
92
|
+
my-cli-tool:
|
|
93
|
+
allowed:
|
|
94
|
+
- GITHUB_TOKEN
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Inspect and export:**
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
plynx env myproject # dotenv format
|
|
101
|
+
plynx env myproject --export # export KEY=value (eval-able)
|
|
102
|
+
plynx env myproject --json # {"KEY": "value"}
|
|
103
|
+
plynx link myproject --direnv # generate .envrc for MCP server ${VAR} expansion
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Auto-migration:** When you adopt an existing project with `plynx project add`, PilotLynx detects secrets in the project's `.env` and `.mcp.json` literals, consolidates them into the central store, and updates the policy — no manual copy-paste.
|
|
107
|
+
|
|
108
|
+
**Default is deny-all.** No policy file = zero secrets injected. See [`docs/secrets-and-mcp.md`](docs/secrets-and-mcp.md) for the full guide.
|
|
109
|
+
|
|
110
|
+
## Why PilotLynx
|
|
111
|
+
|
|
112
|
+
PilotLynx occupies a specific niche: **workspace-level orchestration of isolated Claude Agent SDK projects**. No single existing tool covers this combination. Here's how it compares:
|
|
113
|
+
|
|
114
|
+
| Tool | What it solves | What PilotLynx adds |
|
|
115
|
+
|------|---------------|---------------------|
|
|
116
|
+
| [Claude Agent SDK](https://docs.anthropic.com/en/docs/agents) | Build individual AI agents in TypeScript | Multi-project orchestration, scaffolding, shared secrets, scheduling |
|
|
117
|
+
| [OpenClaw](https://github.com/openclaw/openclaw) | General-purpose personal AI assistant (email, calendar, web) with 20+ messaging integrations | Developer-focused CLI for code projects, policy-gated secrets, template-based scaffolding, cross-project self-improvement |
|
|
118
|
+
| [CrewAI](https://github.com/crewAIInc/crewAI) | Multi-agent collaboration with role-based agents (Python) | File-based durable state in git, project isolation, TypeScript-native with Agent SDK |
|
|
119
|
+
| [LangGraph](https://github.com/langchain-ai/langgraph) | Stateful multi-step agent graphs | Workspace-level concerns: secrets policy, cron scheduling, cross-project insights |
|
|
120
|
+
| [Turborepo](https://turbo.build/repo) | Monorepo build orchestration and caching | AI workflow orchestration, not build — schedules agents, injects secrets, tracks run logs |
|
|
121
|
+
| [AgentStack](https://github.com/AgentOps-AI/AgentStack) | Scaffolding for CrewAI/LangGraph projects | Claude Agent SDK native, multi-project workspace, self-improvement loop |
|
|
122
|
+
| [Infisical](https://infisical.com/) | Secrets management platform | Lightweight file-based secrets with per-project allowlists, no external service |
|
|
123
|
+
|
|
124
|
+
**What PilotLynx uniquely combines:**
|
|
125
|
+
- CLI-first developer workflow (not conversation-first, not GUI-first)
|
|
126
|
+
- Claude Agent SDK native — every CLI command is an agent
|
|
127
|
+
- Multi-project isolation with shared infrastructure (secrets, policies, insights)
|
|
128
|
+
- Tick-based cron scheduling with catch-up policies
|
|
129
|
+
- Cross-project self-improvement loop
|
|
130
|
+
- All state in committed files — no database, no external service
|
|
131
|
+
|
|
132
|
+
## Requirements
|
|
133
|
+
|
|
134
|
+
- **Node.js** 20 or later
|
|
135
|
+
- **Authentication** (one of the following):
|
|
136
|
+
- **Anthropic API key** — set `ANTHROPIC_API_KEY` in `pilotlynx/.env`
|
|
137
|
+
- **Claude Code subscription** (Pro / Max / Teams) — run `claude login` once. No API key needed; the Agent SDK reads OAuth tokens from `~/.claude/` automatically.
|
|
138
|
+
- **Claude Code** (optional) — PilotLynx works standalone, but each CLI command also maps to a Claude Code skill for in-editor use
|
|
139
|
+
|
|
140
|
+
## Install
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npm install -g pilotlynx
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
> **Permission denied?** If you see `EACCES` errors, either prefix with `sudo` or (recommended) use a Node version manager like [nvm](https://github.com/nvm-sh/nvm) / [fnm](https://github.com/Schniz/fnm) which installs to user-owned directories. You can also run without installing globally:
|
|
147
|
+
>
|
|
148
|
+
> ```bash
|
|
149
|
+
> npx pilotlynx <command>
|
|
150
|
+
> ```
|
|
151
|
+
|
|
152
|
+
## Quick Start
|
|
153
|
+
|
|
154
|
+
### 1. Create a workspace
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
mkdir my-agents && cd my-agents
|
|
158
|
+
plynx init --name my-agents
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
This creates:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
my-agents/
|
|
165
|
+
pilotlynx/ # config directory
|
|
166
|
+
plynx.yaml # workspace marker
|
|
167
|
+
projects.yaml # project registry (name → path)
|
|
168
|
+
template/ # project scaffold template
|
|
169
|
+
shared/policies/ # secrets + tool access policies
|
|
170
|
+
shared/docs/ # shared documentation
|
|
171
|
+
shared/insights/ # cross-project learnings
|
|
172
|
+
.gitignore
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
It also writes a global config at `~/.config/pilotlynx/config.yaml` (Linux) so the CLI works from any directory, and installs a cron entry for `plynx schedule tick` every 15 minutes.
|
|
176
|
+
|
|
177
|
+
### 2. Create or add a project
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Create a new project from template
|
|
181
|
+
plynx project create myproject
|
|
182
|
+
|
|
183
|
+
# Or adopt an existing directory (at any path)
|
|
184
|
+
plynx project add myrepo --path /path/to/existing/repo
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`create` scaffolds from the template into `myproject/` (at the workspace root) with:
|
|
188
|
+
- `CLAUDE.md` — project rules
|
|
189
|
+
- `PROJECT_BRIEF.md` — goals and decisions
|
|
190
|
+
- `RUNBOOK.md` — operational procedures
|
|
191
|
+
- `workflows/` — TypeScript Agent SDK workflow files
|
|
192
|
+
- `memory/` — durable knowledge (committed to git)
|
|
193
|
+
|
|
194
|
+
`add` adopts an existing directory: adds missing scaffolding files without overwriting anything, registers the project, migrates detected secrets into the central store, then runs an interactive agent that examines the existing code and helps fill in project docs.
|
|
195
|
+
|
|
196
|
+
Both commands register the project in `pilotlynx/projects.yaml` and prompt for secrets access configuration.
|
|
197
|
+
|
|
198
|
+
### 3. Run a workflow
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
plynx run myproject daily_feedback
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Loads secrets from `.env` per the project's allowlist, then executes the workflow.
|
|
205
|
+
|
|
206
|
+
### 4. Check project structure
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
plynx verify myproject
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Reports missing files or directories.
|
|
213
|
+
|
|
214
|
+
## Commands
|
|
215
|
+
|
|
216
|
+
| Command | What it does |
|
|
217
|
+
|---------|-------------|
|
|
218
|
+
| `plynx init` | Create a new workspace |
|
|
219
|
+
| `plynx project create <name>` | Scaffold a project from template |
|
|
220
|
+
| `plynx project add <name> --path <dir>` | Add an existing directory as a project |
|
|
221
|
+
| `plynx projects list` | List all projects with paths |
|
|
222
|
+
| `plynx run <project> <workflow>` | Run a workflow with secrets injection |
|
|
223
|
+
| `plynx verify <project>` | Validate project structure |
|
|
224
|
+
| `plynx improve` | Run self-improvement loop across projects |
|
|
225
|
+
| `plynx schedule tick` | Run due scheduled workflows |
|
|
226
|
+
| `plynx schedule status <project>` | Show schedules, last/next run times, auto-improve state |
|
|
227
|
+
| `plynx logs <project>` | View recent run logs (`--last`, `--workflow`, `--failures`) |
|
|
228
|
+
| `plynx insights` | View cross-project insights (`--last`, `--since`) |
|
|
229
|
+
| `plynx sync template <project>` | Apply template updates to a project |
|
|
230
|
+
| `plynx env <project>` | Output policy-filtered secrets (`--export`, `--json`, `--envrc`) |
|
|
231
|
+
| `plynx link <project>` | Configure a project for direct access (`--direnv` for `.envrc`) |
|
|
232
|
+
| `plynx unlink <project>` | Remove direct-access configuration |
|
|
233
|
+
|
|
234
|
+
## Other Features
|
|
235
|
+
|
|
236
|
+
- Every CLI command is a Claude Agent SDK agent — the CLI is a thin wrapper with no business logic
|
|
237
|
+
- Bounded workflows with clear start/end — no long-lived sessions, failed runs rerun deterministically
|
|
238
|
+
- All state is committed files — briefs, runbooks, skills, memory in git, zero dependence on session state
|
|
239
|
+
- Scoped context — workflows see only their project directory plus shared docs/insights
|
|
240
|
+
- No external plugins — all skills are local, committed, and code-reviewable
|
|
241
|
+
- Tool access policies independent from secrets policies (defense-in-depth)
|
|
242
|
+
- Filesystem sandboxing via bwrap (Linux) and sandbox-exec (macOS)
|
|
243
|
+
|
|
244
|
+
## Architecture: CLI = Agent SDK
|
|
245
|
+
|
|
246
|
+
The CLI is a thin wrapper around Claude Agent SDK agents. Every `plynx` command invokes a dedicated agent, making the CLI a convenience layer rather than the primary execution surface.
|
|
247
|
+
|
|
248
|
+
- **Each command = one agent.** `plynx project create foo` runs a "project-create" agent that scaffolds the directory from the template.
|
|
249
|
+
- **Most CLI commands have corresponding Claude Code skills** for use inside projects.
|
|
250
|
+
- **Business logic lives in agents.** Exception: `plynx init` scaffolds the workspace directly since no workspace exists yet for agent context.
|
|
251
|
+
|
|
252
|
+
## Working Directly in a Project
|
|
253
|
+
|
|
254
|
+
PilotLynx stores its config location in a global file (`~/.config/pilotlynx/config.yaml` on Linux, OS-appropriate on macOS/Windows) so the CLI works from any directory — no need to be inside the workspace.
|
|
255
|
+
|
|
256
|
+
For MCP servers that need secrets via `${VAR}` expansion, use [direnv](https://direnv.net/):
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
plynx link myproject --direnv # generates .envrc with policy-filtered secrets
|
|
260
|
+
cd myproject && direnv allow # activate
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The `.envrc` is gitignored. Regenerate it when secrets change.
|
|
264
|
+
|
|
265
|
+
## Project Registry
|
|
266
|
+
|
|
267
|
+
Projects are tracked in `pilotlynx/projects.yaml`:
|
|
268
|
+
|
|
269
|
+
```yaml
|
|
270
|
+
version: 1
|
|
271
|
+
projects:
|
|
272
|
+
my-app:
|
|
273
|
+
path: my-app # relative to workspace root
|
|
274
|
+
external-repo:
|
|
275
|
+
path: /home/user/repos/external-repo # absolute path
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Paths under the workspace root are stored as relative; paths outside are stored as absolute. This keeps the registry portable — move the workspace and relative paths still resolve.
|
|
279
|
+
|
|
280
|
+
## Project Structure
|
|
281
|
+
|
|
282
|
+
Every project follows the same layout:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
myproject/
|
|
286
|
+
CLAUDE.md # project-specific agent rules
|
|
287
|
+
PROJECT_BRIEF.md # goals, decisions, constraints
|
|
288
|
+
RUNBOOK.md # how to operate this project
|
|
289
|
+
.mcp.json # MCP server config
|
|
290
|
+
.claude/settings.json # shared project permissions
|
|
291
|
+
.claude/skills/ # project-scoped skills
|
|
292
|
+
.claude/rules/ # modular topic-specific rules
|
|
293
|
+
workflows/ # TypeScript Agent SDK workflows
|
|
294
|
+
memory/MEMORY.md # durable knowledge entrypoint (git-tracked)
|
|
295
|
+
artifacts/ # output files (gitignored)
|
|
296
|
+
logs/ # run logs (gitignored)
|
|
297
|
+
schedule.yaml # cron schedules for workflows
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Workflows
|
|
301
|
+
|
|
302
|
+
Each project has workflows under `workflows/` — TypeScript scripts that run Claude Agent SDK.
|
|
303
|
+
|
|
304
|
+
### Execution Model
|
|
305
|
+
|
|
306
|
+
- Bounded, isolated runs with a clear start and end.
|
|
307
|
+
- Each run produces a logged outcome: success or failure, plus a short summary.
|
|
308
|
+
- Failed workflows support deterministic rerun with the same inputs.
|
|
309
|
+
- Retries are bounded and explicit — no infinite retry loops.
|
|
310
|
+
|
|
311
|
+
### Standard Workflows
|
|
312
|
+
|
|
313
|
+
Each project should support these baseline workflows:
|
|
314
|
+
|
|
315
|
+
| Workflow | Purpose |
|
|
316
|
+
|----------|---------|
|
|
317
|
+
| `daily_feedback` | Review recent activity and update project memory |
|
|
318
|
+
| `task_execute` | Execute a specific task from prompt input |
|
|
319
|
+
| `project_review` | Produce a short project status update |
|
|
320
|
+
|
|
321
|
+
## Security Model
|
|
322
|
+
|
|
323
|
+
- Project workflows operate inside their project folder and must not access other project directories.
|
|
324
|
+
- Secrets are injected via env and never stored in committed files.
|
|
325
|
+
- No external skills marketplace — all skills are local and committed.
|
|
326
|
+
- Tool access is policy-gated — secrets allowlists and tool allowlists are independent controls (defense-in-depth).
|
|
327
|
+
|
|
328
|
+
## Claude Code Compatibility
|
|
329
|
+
|
|
330
|
+
- The workspace can be opened directly in Claude Code.
|
|
331
|
+
- `plynx` works from the workspace root, from project directories (via global config), and from any other location.
|
|
332
|
+
- `plynx link --direnv` generates `.envrc` for MCP servers that need secrets via `${VAR}` expansion.
|
|
333
|
+
- Each CLI command maps to a Claude Code skill — same agent, same behavior.
|
|
334
|
+
|
|
335
|
+
## Design Decisions
|
|
336
|
+
|
|
337
|
+
**Minimal dependencies (11 total).** Each dependency earns its place: `commander` for CLI parsing, `chalk` for terminal colors, `cli-table3` for table output, `croner` for cron parsing, `yaml`/`zod` for config, `dotenv` for secrets loading, `env-paths` for OS-appropriate config paths, `proper-lockfile` for concurrent tick safety, `grammy` for Telegram relay, and `@anthropic-ai/claude-agent-sdk` for the core runtime. No ORMs, no template engines, no framework overhead.
|
|
338
|
+
|
|
339
|
+
**File-based state over databases.** All state — project briefs, runbooks, skills, memory, run logs, schedule state — lives in committed files. This makes workspaces portable, git-friendly, and inspectable with standard tools. No database to provision or migrate.
|
|
340
|
+
|
|
341
|
+
**Simple template interpolation over template engines.** Project scaffolding uses direct file copying with string replacement rather than Handlebars/EJS/etc. This avoids a class of injection vulnerabilities and keeps templates readable as plain files.
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
MIT
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getWorkspaceRoot, ENV_FILE } from '../lib/config.js';
|
|
2
|
+
import { loadPrompt, loadSystemPrompt } from '../lib/prompts.js';
|
|
3
|
+
import { resolve, dirname } from 'node:path';
|
|
4
|
+
function improveToolCallback() {
|
|
5
|
+
const envFile = resolve(ENV_FILE());
|
|
6
|
+
const envDir = dirname(envFile);
|
|
7
|
+
return async (toolName, input) => {
|
|
8
|
+
const filePath = input?.file_path ?? input?.path;
|
|
9
|
+
if (filePath) {
|
|
10
|
+
const resolved = resolve(filePath);
|
|
11
|
+
// Deny access to .env files in config root
|
|
12
|
+
if (resolved === envFile || /[/\\]\.env(\..+)?$/.test(resolved)) {
|
|
13
|
+
if (resolved.startsWith(envDir)) {
|
|
14
|
+
return { behavior: 'deny', message: 'Cannot access .env files' };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { behavior: 'allow', updatedInput: input };
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function getImproveAgentConfig(logSummaries) {
|
|
22
|
+
const summaryText = Object.entries(logSummaries)
|
|
23
|
+
.map(([project, summary]) => `## ${project}\n${summary}`)
|
|
24
|
+
.join('\n\n');
|
|
25
|
+
return {
|
|
26
|
+
prompt: loadPrompt('improve', 'improve_analyze', { summaryText }),
|
|
27
|
+
cwd: getWorkspaceRoot(),
|
|
28
|
+
allowedTools: ['Read', 'Glob', 'Grep'],
|
|
29
|
+
// Intentional: uses string systemPrompt (not preset 'claude_code') because
|
|
30
|
+
// this agent is read-only and doesn't need CLAUDE.md context or Claude Code tools.
|
|
31
|
+
systemPrompt: loadSystemPrompt('improve', 'improve_analyze'),
|
|
32
|
+
maxTurns: 10,
|
|
33
|
+
canUseTool: improveToolCallback(),
|
|
34
|
+
outputFormat: {
|
|
35
|
+
type: 'json_schema',
|
|
36
|
+
schema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
projectFeedback: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
description: 'Map of project name to feedback string',
|
|
42
|
+
additionalProperties: { type: 'string' },
|
|
43
|
+
},
|
|
44
|
+
crossProjectInsights: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'Abstract cross-project learnings, no project names or secrets',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['projectFeedback', 'crossProjectInsights'],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=improve.agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"improve.agent.js","sourceRoot":"","sources":["../../src/agents/improve.agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAc,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,SAAS,mBAAmB;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,KAAK,EAAE,QAAgB,EAAE,KAAc,EAA6B,EAAE;QAC3E,MAAM,QAAQ,GAAI,KAAa,EAAE,SAAS,IAAK,KAAa,EAAE,IAAI,CAAC;QACnE,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACnC,2CAA2C;YAC3C,IAAI,QAAQ,KAAK,OAAO,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChE,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,YAAoC;IACxE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;SAC7C,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,OAAO,KAAK,OAAO,EAAE,CAAC;SACxD,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,WAAW,EAAE,CAAC;QACjE,GAAG,EAAE,gBAAgB,EAAE;QACvB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QACtC,2EAA2E;QAC3E,mFAAmF;QACnF,YAAY,EAAE,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,CAAE;QAC7D,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,mBAAmB,EAAE;QACjC,YAAY,EAAE;YACZ,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,eAAe,EAAE;wBACf,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,wCAAwC;wBACrD,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACzC;oBACD,oBAAoB,EAAE;wBACpB,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,+DAA+D;qBAC7E;iBACF;gBACD,QAAQ,EAAE,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;aACtD;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getProjectDir, POLICIES_DIR } from '../lib/config.js';
|
|
2
|
+
import { loadPrompt } from '../lib/prompts.js';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { projectSetupCallback } from '../lib/callbacks.js';
|
|
5
|
+
export function getProjectAddAgentConfig(name, availableSecretKeys, currentSecretsPolicy, migrationSummary) {
|
|
6
|
+
const projectDir = getProjectDir(name);
|
|
7
|
+
return {
|
|
8
|
+
prompt: loadPrompt('project-add', 'project_add', {
|
|
9
|
+
name,
|
|
10
|
+
projectDir,
|
|
11
|
+
availableSecretKeys: availableSecretKeys.join(', ') || '(none configured)',
|
|
12
|
+
currentSecretsPolicy,
|
|
13
|
+
secretsPolicyPath: join(POLICIES_DIR(), 'secrets-access.yaml'),
|
|
14
|
+
migrationSummary: migrationSummary || '',
|
|
15
|
+
}),
|
|
16
|
+
cwd: projectDir,
|
|
17
|
+
additionalDirectories: [POLICIES_DIR()],
|
|
18
|
+
allowedTools: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'AskUserQuestion'],
|
|
19
|
+
settingSources: ['project'],
|
|
20
|
+
systemPrompt: { type: 'preset', preset: 'claude_code' },
|
|
21
|
+
permissionMode: 'acceptEdits',
|
|
22
|
+
maxTurns: 20,
|
|
23
|
+
canUseTool: projectSetupCallback(projectDir, POLICIES_DIR()),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=project-add.agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-add.agent.js","sourceRoot":"","sources":["../../src/agents/project-add.agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,UAAU,wBAAwB,CACtC,IAAY,EACZ,mBAA6B,EAC7B,oBAA4B,EAC5B,gBAAyB;IAEzB,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,aAAa,EAAE,aAAa,EAAE;YAC/C,IAAI;YACJ,UAAU;YACV,mBAAmB,EAAE,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,mBAAmB;YAC1E,oBAAoB;YACpB,iBAAiB,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,qBAAqB,CAAC;YAC9D,gBAAgB,EAAE,gBAAgB,IAAI,EAAE;SACzC,CAAC;QACF,GAAG,EAAE,UAAU;QACf,qBAAqB,EAAE,CAAC,YAAY,EAAE,CAAC;QACvC,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC;QAClF,cAAc,EAAE,CAAC,SAAS,CAAC;QAC3B,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE;QACvD,cAAc,EAAE,aAAa;QAC7B,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,oBAAoB,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getProjectDir, POLICIES_DIR } from '../lib/config.js';
|
|
2
|
+
import { loadPrompt } from '../lib/prompts.js';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { projectSetupCallback } from '../lib/callbacks.js';
|
|
5
|
+
export function getProjectCreateAgentConfig(name, availableSecretKeys = [], currentSecretsPolicy = '') {
|
|
6
|
+
const projectDir = getProjectDir(name);
|
|
7
|
+
return {
|
|
8
|
+
prompt: loadPrompt('project-create', 'project_create', {
|
|
9
|
+
name,
|
|
10
|
+
projectDir,
|
|
11
|
+
availableSecretKeys: availableSecretKeys.join(', ') || '(none configured)',
|
|
12
|
+
currentSecretsPolicy: currentSecretsPolicy || 'version: 1\nshared: []\nprojects: {}\n',
|
|
13
|
+
secretsPolicyPath: join(POLICIES_DIR(), 'secrets-access.yaml'),
|
|
14
|
+
}),
|
|
15
|
+
cwd: projectDir,
|
|
16
|
+
additionalDirectories: [POLICIES_DIR()],
|
|
17
|
+
allowedTools: ['Read', 'Write', 'Edit', 'Glob', 'Bash', 'AskUserQuestion'],
|
|
18
|
+
settingSources: ['project'],
|
|
19
|
+
systemPrompt: { type: 'preset', preset: 'claude_code' },
|
|
20
|
+
permissionMode: 'acceptEdits',
|
|
21
|
+
maxTurns: 20,
|
|
22
|
+
canUseTool: projectSetupCallback(projectDir, POLICIES_DIR()),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=project-create.agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-create.agent.js","sourceRoot":"","sources":["../../src/agents/project-create.agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,UAAU,2BAA2B,CACzC,IAAY,EACZ,sBAAgC,EAAE,EAClC,uBAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,gBAAgB,EAAE,gBAAgB,EAAE;YACrD,IAAI;YACJ,UAAU;YACV,mBAAmB,EAAE,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,mBAAmB;YAC1E,oBAAoB,EAAE,oBAAoB,IAAI,wCAAwC;YACtF,iBAAiB,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,qBAAqB,CAAC;SAC/D,CAAC;QACF,GAAG,EAAE,UAAU;QACf,qBAAqB,EAAE,CAAC,YAAY,EAAE,CAAC;QACvC,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC;QAC1E,cAAc,EAAE,CAAC,SAAS,CAAC;QAC3B,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE;QACvD,cAAc,EAAE,aAAa;QAC7B,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,oBAAoB,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getProjectDir, SHARED_DOCS_DIR, INSIGHTS_DIR } from '../lib/config.js';
|
|
2
|
+
import { buildProjectTools } from '../lib/tools.js';
|
|
3
|
+
import { loadPrompt } from '../lib/prompts.js';
|
|
4
|
+
import { detectSandbox } from '../lib/sandbox.js';
|
|
5
|
+
import { pathEnforcementCallback } from '../lib/callbacks.js';
|
|
6
|
+
export { pathEnforcementCallback } from '../lib/callbacks.js';
|
|
7
|
+
export function getRunAgentConfig(project, workflow, projectEnv, feedbackPrompt) {
|
|
8
|
+
const projectDir = getProjectDir(project);
|
|
9
|
+
const toolPolicy = buildProjectTools(project);
|
|
10
|
+
const promptName = feedbackPrompt ? 'run_with_feedback' : 'run_default';
|
|
11
|
+
const vars = { workflow };
|
|
12
|
+
if (feedbackPrompt)
|
|
13
|
+
vars.feedback = feedbackPrompt;
|
|
14
|
+
const prompt = loadPrompt('run', promptName, vars);
|
|
15
|
+
const sandbox = detectSandbox();
|
|
16
|
+
if (sandbox.level === 'kernel') {
|
|
17
|
+
console.error(`[plynx] Filesystem sandbox: ${sandbox.mechanism} (kernel-level isolation)`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
console.error('[plynx] Filesystem sandbox: regex-only (bwrap not available)');
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
prompt,
|
|
24
|
+
cwd: projectDir,
|
|
25
|
+
additionalDirectories: [SHARED_DOCS_DIR(), INSIGHTS_DIR()],
|
|
26
|
+
env: projectEnv,
|
|
27
|
+
allowedTools: toolPolicy.allowedTools.length > 0 ? toolPolicy.allowedTools : undefined,
|
|
28
|
+
disallowedTools: toolPolicy.disallowedTools.length > 0 ? toolPolicy.disallowedTools : undefined,
|
|
29
|
+
settingSources: ['project'],
|
|
30
|
+
systemPrompt: { type: 'preset', preset: 'claude_code' },
|
|
31
|
+
permissionMode: 'bypassPermissions',
|
|
32
|
+
allowDangerouslySkipPermissions: true,
|
|
33
|
+
maxTurns: 50,
|
|
34
|
+
canUseTool: pathEnforcementCallback(projectDir, [SHARED_DOCS_DIR(), INSIGHTS_DIR()]),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=run.agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.agent.js","sourceRoot":"","sources":["../../src/agents/run.agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,QAAgB,EAChB,UAAkC,EAClC,cAAuB;IAEvB,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,aAAa,CAAC;IACxE,MAAM,IAAI,GAA2B,EAAE,QAAQ,EAAE,CAAC;IAClD,IAAI,cAAc;QAAE,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC;IACnD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IAEnD,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,IAAI,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,+BAA+B,OAAO,CAAC,SAAS,2BAA2B,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAChF,CAAC;IAED,OAAO;QACL,MAAM;QACN,GAAG,EAAE,UAAU;QACf,qBAAqB,EAAE,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,CAAC;QAC1D,GAAG,EAAE,UAAU;QACf,YAAY,EAAE,UAAU,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;QACtF,eAAe,EAAE,UAAU,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;QAC/F,cAAc,EAAE,CAAC,SAAS,CAAC;QAC3B,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE;QACvD,cAAc,EAAE,mBAAmB;QACnC,+BAA+B,EAAE,IAAI;QACrC,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,uBAAuB,CAAC,UAAU,EAAE,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;KACrF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AgentConfig } from '../lib/types.js';
|
|
2
|
+
import type { MigrationPlan } from '../lib/secrets-migration.js';
|
|
3
|
+
export interface MigrationAgentOutput {
|
|
4
|
+
approved: boolean;
|
|
5
|
+
conflictResolutions: Record<string, {
|
|
6
|
+
action: 'skip' | 'rename' | 'overwrite';
|
|
7
|
+
newName?: string;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
interface SecretsMigrationInput {
|
|
11
|
+
projectName: string;
|
|
12
|
+
plan: MigrationPlan;
|
|
13
|
+
}
|
|
14
|
+
export declare function getSecretsMigrationAgentConfig(input: SecretsMigrationInput): AgentConfig;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { loadPrompt, loadSystemPrompt } from '../lib/prompts.js';
|
|
2
|
+
function formatKeyList(keys) {
|
|
3
|
+
if (keys.length === 0)
|
|
4
|
+
return '(none)';
|
|
5
|
+
return keys.map(k => `- ${k.key} (from ${k.source})`).join('\n');
|
|
6
|
+
}
|
|
7
|
+
export function getSecretsMigrationAgentConfig(input) {
|
|
8
|
+
const { projectName, plan } = input;
|
|
9
|
+
const newKeys = plan.keys.filter(k => k.category === 'new');
|
|
10
|
+
const deduped = plan.keys.filter(k => k.category === 'deduplicated');
|
|
11
|
+
const conflicts = plan.keys.filter(k => k.category === 'conflicting');
|
|
12
|
+
const mcpNote = plan.rewrittenMcpJson
|
|
13
|
+
? 'Literal values in .mcp.json will be replaced with ${VAR} references for migrated keys.'
|
|
14
|
+
: '';
|
|
15
|
+
return {
|
|
16
|
+
prompt: loadPrompt('secrets-migration', 'secrets_migration_confirm', {
|
|
17
|
+
projectName,
|
|
18
|
+
totalMigratable: String(plan.keys.length),
|
|
19
|
+
newKeysCount: String(newKeys.length),
|
|
20
|
+
newKeysList: formatKeyList(newKeys),
|
|
21
|
+
dedupedCount: String(deduped.length),
|
|
22
|
+
dedupedList: formatKeyList(deduped),
|
|
23
|
+
conflictsCount: String(conflicts.length),
|
|
24
|
+
conflictsList: formatKeyList(conflicts),
|
|
25
|
+
mcpNote,
|
|
26
|
+
}),
|
|
27
|
+
systemPrompt: loadSystemPrompt('secrets-migration', 'secrets_migration_confirm'),
|
|
28
|
+
allowedTools: ['AskUserQuestion'],
|
|
29
|
+
maxTurns: 8,
|
|
30
|
+
outputFormat: {
|
|
31
|
+
type: 'json_schema',
|
|
32
|
+
schema: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
approved: {
|
|
36
|
+
type: 'boolean',
|
|
37
|
+
description: 'Whether the user approved the migration',
|
|
38
|
+
},
|
|
39
|
+
conflictResolutions: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
description: 'Resolution for each conflicting key',
|
|
42
|
+
additionalProperties: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
action: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
enum: ['skip', 'rename', 'overwrite'],
|
|
48
|
+
},
|
|
49
|
+
newName: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'New key name when action is rename',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
required: ['action'],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
required: ['approved', 'conflictResolutions'],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=secrets-migration.agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets-migration.agent.js","sourceRoot":"","sources":["../../src/agents/secrets-migration.agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAgBjE,SAAS,aAAa,CAAC,IAAuC;IAC5D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACvC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,KAA4B;IACzE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAEpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC;IAEtE,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB;QACnC,CAAC,CAAC,wFAAwF;QAC1F,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,mBAAmB,EAAE,2BAA2B,EAAE;YACnE,WAAW;YACX,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YACzC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YACpC,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC;YACnC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YACpC,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC;YACnC,cAAc,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;YACxC,aAAa,EAAE,aAAa,CAAC,SAAS,CAAC;YACvC,OAAO;SACR,CAAC;QACF,YAAY,EAAE,gBAAgB,CAAC,mBAAmB,EAAE,2BAA2B,CAAC;QAChF,YAAY,EAAE,CAAC,iBAAiB,CAAC;QACjC,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE;YACZ,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,QAAQ,EAAE;wBACR,IAAI,EAAE,SAAS;wBACf,WAAW,EAAE,yCAAyC;qBACvD;oBACD,mBAAmB,EAAE;wBACnB,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,qCAAqC;wBAClD,oBAAoB,EAAE;4BACpB,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,MAAM,EAAE;oCACN,IAAI,EAAE,QAAQ;oCACd,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC;iCACtC;gCACD,OAAO,EAAE;oCACP,IAAI,EAAE,QAAQ;oCACd,WAAW,EAAE,oCAAoC;iCAClD;6BACF;4BACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;yBACrB;qBACF;iBACF;gBACD,QAAQ,EAAE,CAAC,UAAU,EAAE,qBAAqB,CAAC;aAC9C;SACF;KACF,CAAC;AACJ,CAAC"}
|