@kyo-so/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.agents/skills/kyoso-review/SKILL.md +38 -0
  2. package/.agents/skills/kyoso-review/agents/openai.yaml +14 -0
  3. package/LICENSE +677 -0
  4. package/README.md +202 -0
  5. package/dist/acp/AcpAgentManager.d.ts +9 -0
  6. package/dist/acp/AcpAgentProcess.d.ts +9 -0
  7. package/dist/acp/FakeAgentManager.d.ts +9 -0
  8. package/dist/acp/normalize.d.ts +3 -0
  9. package/dist/acp/prompts.d.ts +2 -0
  10. package/dist/aggregate/aggregateFindings.d.ts +15 -0
  11. package/dist/aggregate/severity.d.ts +3 -0
  12. package/dist/audit/sanitize.d.ts +3 -0
  13. package/dist/audit/trace.d.ts +12 -0
  14. package/dist/bin/kyoso.js +199606 -0
  15. package/dist/cli/args.d.ts +8 -0
  16. package/dist/cli/doctor.d.ts +9 -0
  17. package/dist/cli/init.d.ts +4 -0
  18. package/dist/cli/io.d.ts +7 -0
  19. package/dist/cli/main.d.ts +1 -0
  20. package/dist/config/defaultConfig.d.ts +2 -0
  21. package/dist/config/defineConfig.d.ts +2 -0
  22. package/dist/config/loadConfig.d.ts +22 -0
  23. package/dist/config/schema.d.ts +117 -0
  24. package/dist/config/trustedConfig.d.ts +5 -0
  25. package/dist/config/tsConfigLoader.d.ts +7 -0
  26. package/dist/context/buildContext.d.ts +11 -0
  27. package/dist/context/pathPolicy.d.ts +3 -0
  28. package/dist/context/truncate.d.ts +6 -0
  29. package/dist/core/constants.d.ts +7 -0
  30. package/dist/core/errors.d.ts +4 -0
  31. package/dist/core/runReview.d.ts +12 -0
  32. package/dist/core/types.d.ts +154 -0
  33. package/dist/core/validateRequest.d.ts +2 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.js +189728 -0
  36. package/dist/judge/anthropic.d.ts +2 -0
  37. package/dist/judge/deterministicFallback.d.ts +3 -0
  38. package/dist/judge/openai.d.ts +2 -0
  39. package/dist/judge/prompt.d.ts +9 -0
  40. package/dist/judge/provider.d.ts +26 -0
  41. package/dist/mcp/formatMcpResponse.d.ts +7 -0
  42. package/dist/mcp/schemas.d.ts +38 -0
  43. package/dist/mcp/server.d.ts +6 -0
  44. package/dist/output/markdown.d.ts +7 -0
  45. package/dist/security/cisaGate.d.ts +2 -0
  46. package/dist/security/decision.d.ts +10 -0
  47. package/dist/security/recursionGuard.d.ts +1 -0
  48. package/dist/security/redact.d.ts +5 -0
  49. package/dist/security/sanitizeText.d.ts +3 -0
  50. package/dist/security/secretScan.d.ts +2 -0
  51. package/dist/utils/env.d.ts +5 -0
  52. package/dist/utils/ids.d.ts +1 -0
  53. package/dist/workspace/cleanup.d.ts +1 -0
  54. package/dist/workspace/createSnapshot.d.ts +11 -0
  55. package/examples/claude-code-mcp.json +13 -0
  56. package/examples/codex-config.toml +11 -0
  57. package/examples/kyoso.config.ts +22 -0
  58. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # Kyo-so
2
+
3
+ Kyo-so (Kyoso / 協奏) is an MCP-native, ACP-powered multi-agent review gate for AI coding workflows.
4
+
5
+ The Japanese word 協奏 translates to concerto in English: multiple independent players performing one coordinated piece.
6
+
7
+ It coordinates Codex and Claude reviewers for:
8
+
9
+ - implementation plan review
10
+ - security review with CISA Secure by Design gates
11
+ - diff review after implementation
12
+
13
+ Kyoso does not apply code changes.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ bunx @kyo-so/cli mcp
19
+ npx @kyo-so/cli mcp
20
+ ```
21
+
22
+ Naming note: the npm package is `@kyo-so/cli` (matching the product name Kyo-so), while the installed CLI command is the shorter `kyoso`.
23
+
24
+ For local development:
25
+
26
+ ```bash
27
+ safe-chain bun install
28
+ safe-chain bun run typecheck
29
+ safe-chain bun test
30
+ safe-chain bun run build
31
+ ```
32
+
33
+ Requires Node.js 20 or newer when running the packaged CLI.
34
+
35
+ Known distribution risk: `@modelcontextprotocol/server` has no stable release yet; Kyoso currently pins a prerelease API, so MCP SDK API changes may require a follow-up release.
36
+
37
+ ## CLI
38
+
39
+ ```bash
40
+ kyoso plan --goal "Review this OAuth callback plan" --plan plan.md
41
+ kyoso security --goal "Review this auth diff" --diff changes.patch
42
+ kyoso diff --base main --head HEAD
43
+ kyoso doctor
44
+ kyoso init
45
+ ```
46
+
47
+ ## Usage Examples
48
+
49
+ Review an implementation plan with selected code:
50
+
51
+ ```bash
52
+ kyoso plan \
53
+ --goal "Review the OAuth callback implementation plan" \
54
+ --plan plan.md \
55
+ --file src/auth/callback.ts
56
+ ```
57
+
58
+ Read the result from the top down: `Decision` is the deterministic gate outcome, `Findings` are the required changes, and `Tests to Add` are the regression checks Kyoso expects before approval.
59
+
60
+ Run a CISA Secure by Design security review against a patch:
61
+
62
+ ```bash
63
+ kyoso security \
64
+ --goal "Review auth changes for tenant isolation and secure defaults" \
65
+ --diff changes.patch \
66
+ --json
67
+ ```
68
+
69
+ In JSON output, `cisaSecureByDesign` shows the four gate dimensions. A `fail` in customer security outcomes blocks the review; warning-level dimensions usually produce `approve_with_changes`.
70
+
71
+ Register Kyoso with Codex or Claude Code as an MCP server, then call `plan_review` from the client:
72
+
73
+ ```toml
74
+ # See examples/codex-config.toml
75
+ [mcp_servers.kyoso]
76
+ command = "kyoso"
77
+ args = ["mcp", "--network", "model_only"]
78
+ ```
79
+
80
+ Example client request:
81
+
82
+ ```text
83
+ Use Kyoso plan_review on this plan and the selected auth files. I need a second opinion before implementing.
84
+ ```
85
+
86
+ ## MCP
87
+
88
+ ```bash
89
+ kyoso mcp --network model_only
90
+ ```
91
+
92
+ When `--network` is omitted, Kyoso uses `model_only`. This means Kyoso expects only model-provider traffic from backend agents. It is a policy-level constraint, not OS-level network isolation.
93
+
94
+ Kyoso exposes exactly these MCP tools:
95
+
96
+ - `plan_review`
97
+ - `security_review`
98
+ - `diff_review`
99
+
100
+ MCP stdout is reserved for protocol messages. Logs go to stderr or local audit traces.
101
+
102
+ ## Safety Model
103
+
104
+ Kyoso MVP uses a disposable temporary snapshot and policy-level write denial. It is not a full OS sandbox. Do not run Kyoso against untrusted repositories unless you understand the risk.
105
+
106
+ Secret detection is best-effort. If Kyoso detects a likely secret in the request, selected files, or diff, it redacts the value and blocks before backend agents run by default.
107
+
108
+ Kyoso does not store provider credentials. Child agent environment variables are allowlisted.
109
+
110
+ Repository content, plans, diffs, and selected files are treated as untrusted data in backend prompts. Kyoso wraps them in `<untrusted-content>` tags and tells agents not to follow instructions found inside. Final decisions are derived from schema-constrained findings; agents cannot write files or run commands, and the judge cannot change the deterministic decision.
111
+
112
+ ## Agent Auth
113
+
114
+ Codex uses the local `codex` login when available. No API key is required for the default subscription-backed path.
115
+
116
+ Claude supports two auth paths:
117
+
118
+ - `ANTHROPIC_API_KEY`: direct Anthropic API billing
119
+ - `CLAUDE_CODE_OAUTH_TOKEN`: subscription auth from `claude setup-token`
120
+
121
+ If both Claude credentials are set, Kyoso forwards only `CLAUDE_CODE_OAUTH_TOKEN` to the Claude child agent by default. Set `agents.claude.auth.preferApiKey: true` to forward only `ANTHROPIC_API_KEY`.
122
+
123
+ Default child-agent env allowlist:
124
+
125
+ | Agent | Provider env |
126
+ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
127
+ | Codex | `CODEX_API_KEY`, `OPENAI_API_KEY`, `CODEX_HOME`, `CODEX_ACCESS_TOKEN` |
128
+ | Claude | `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`, `ANTHROPIC_MODEL`, `ANTHROPIC_BASE_URL`, `CLAUDE_CONFIG_DIR`, `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY` |
129
+
130
+ Kyoso also forwards minimal runtime env needed to launch subprocesses: `PATH`, `HOME`, `TMPDIR`, `TEMP`, `TMP`, `LANG`, `LC_ALL`, `SHELL`, `USER`, `USERNAME`, and `SystemRoot`.
131
+
132
+ ## Agent Models
133
+
134
+ Omit `agents.<name>.model` to use each agent's own default. Codex uses the local Codex config, such as `~/.codex/config.toml`; Claude uses the adapter default.
135
+
136
+ ```ts
137
+ export default defineConfig({
138
+ agents: {
139
+ codex: {
140
+ model: "gpt-5.5",
141
+ },
142
+ claude: {
143
+ model: "claude-sonnet-5",
144
+ },
145
+ },
146
+ });
147
+ ```
148
+
149
+ Kyoso maps model pins to adapter-supported configuration:
150
+
151
+ - Claude: sets `ANTHROPIC_MODEL` when not already set in `agents.claude.env` or a whitelisted parent env.
152
+ - Codex: sets `CODEX_CONFIG={"model":"..."}` when `CODEX_CONFIG` is not already set. To combine other Codex session config with a model pin, set `agents.codex.env.CODEX_CONFIG` directly.
153
+
154
+ ## Audit
155
+
156
+ Audit traces are written to:
157
+
158
+ ```text
159
+ .kyoso/traces/<yyyy-mm-dd>/<traceId>.jsonl
160
+ ```
161
+
162
+ Raw agent output and raw file contents are disabled by default.
163
+
164
+ Keep `.kyoso/traces/` out of Git. `kyoso init` adds `.kyoso/` to `.gitignore`, and this repository does the same. If `audit.includeRawAgentOutput` is enabled, traces may persist sensitive review output; delete old traces regularly according to your local retention policy.
165
+
166
+ ## Config
167
+
168
+ `kyoso.config.ts` is loaded only after trust-on-first-use approval. Trusted hashes are stored in `~/.kyoso/trusted-configs.json`.
169
+
170
+ TypeScript config files can execute arbitrary code. In a TTY, Kyoso prompts before executing an untrusted config. In non-interactive mode such as MCP or CI, untrusted config is skipped and defaults are used. Pass `--trust-config` to explicitly trust the current config hash, or `--ignore-config` to always use defaults.
171
+
172
+ Default agent timeouts are Codex 120 seconds and Claude 240 seconds. MCP clients should allow at least 360 seconds for tool calls.
173
+
174
+ Judge LLMs are optional. Set `OPENAI_API_KEY` or `CODEX_API_KEY` to use the OpenAI judge, or `ANTHROPIC_API_KEY` to use the Anthropic judge. Optional overrides:
175
+
176
+ - `OPENAI_BASE_URL`: OpenAI-compatible API base URL
177
+ - `KYOSO_OPENAI_JUDGE_MODEL`: OpenAI judge model, default `gpt-5.4-mini`
178
+ - `KYOSO_ANTHROPIC_JUDGE_MODEL`: Anthropic judge model, default `claude-haiku-4-5`
179
+
180
+ Judge defaults intentionally use lightweight models. For a stronger judge, set `KYOSO_ANTHROPIC_JUDGE_MODEL` to a Sonnet-class model such as `claude-sonnet-5`.
181
+
182
+ Subscription-only setup:
183
+
184
+ - Codex: use local `codex` login
185
+ - Claude: run `claude setup-token`, then set `CLAUDE_CODE_OAUTH_TOKEN`
186
+ - Judge: set no API keys, so Kyoso uses `deterministic_fallback`
187
+ - To avoid OpenAI judge calls when `OPENAI_API_KEY` is present, set `judgeProvider: "none"`
188
+
189
+ Team admins should also check organization Usage credits. If credits are enabled, billing behavior beyond subscription limits is controlled outside Kyoso.
190
+
191
+ ## Development
192
+
193
+ - `KYOSO_TEST_FAKE_AGENTS=1`: test-only fake ACP agents; do not set in production.
194
+ - `KYOSO_KEEP_TEMP=1`: keep temporary snapshots for local debugging.
195
+
196
+ ## License
197
+
198
+ Kyoso is licensed under the GNU Affero General Public License v3.0 or later (`AGPL-3.0-or-later`).
199
+
200
+ Kyoso is intended to be used as a separate CLI or MCP server process. Embedding, importing, or linking Kyoso into another program may have different license implications.
201
+
202
+ Copyright (C) 2026 Hokuto TAKEMIYA (hokupod).
@@ -0,0 +1,9 @@
1
+ import type { AgentRunInput, AgentRunResult } from "../core/types.js";
2
+ export interface AcpAgentManager {
3
+ runAgent(input: AgentRunInput): Promise<AgentRunResult>;
4
+ runAll(inputs: AgentRunInput[]): Promise<AgentRunResult[]>;
5
+ }
6
+ export declare abstract class BaseAcpAgentManager implements AcpAgentManager {
7
+ abstract runAgent(input: AgentRunInput): Promise<AgentRunResult>;
8
+ runAll(inputs: AgentRunInput[]): Promise<AgentRunResult[]>;
9
+ }
@@ -0,0 +1,9 @@
1
+ import type { KyosoConfig } from "../config/schema.js";
2
+ import type { AgentRunInput, AgentRunResult } from "../core/types.js";
3
+ import { BaseAcpAgentManager } from "./AcpAgentManager.js";
4
+ export declare class SubprocessAcpAgentManager extends BaseAcpAgentManager {
5
+ private readonly config;
6
+ constructor(config: KyosoConfig);
7
+ runAgent(input: AgentRunInput): Promise<AgentRunResult>;
8
+ }
9
+ export declare function readWorkspaceFile(workspaceDir: string, requestedPath: string, line?: number | null, limit?: number | null): Promise<string>;
@@ -0,0 +1,9 @@
1
+ import type { AgentRunInput, AgentRunResult } from "../core/types.js";
2
+ import { BaseAcpAgentManager } from "./AcpAgentManager.js";
3
+ export type FakeAgentScenario = "success" | "markdown_json" | "timeout" | "malformed" | "auth_failure" | "permission_request" | "write_attempt";
4
+ export declare class FakeAgentManager extends BaseAcpAgentManager {
5
+ private readonly scenarios;
6
+ readonly calls: AgentRunInput[];
7
+ constructor(scenarios?: Partial<Record<"codex" | "claude", FakeAgentScenario>>);
8
+ runAgent(input: AgentRunInput): Promise<AgentRunResult>;
9
+ }
@@ -0,0 +1,3 @@
1
+ import type { AgentName, AgentRole, NormalizedAgentOpinion } from "../core/types.js";
2
+ export declare function normalizeAgentOutput(agent: AgentName, role: AgentRole, rawText: string): NormalizedAgentOpinion;
3
+ export declare function extractFirstJsonObject(text: string): string | undefined;
@@ -0,0 +1,2 @@
1
+ import type { KyosoReviewRequest, ReviewTool } from "../core/types.js";
2
+ export declare function buildAgentPrompt(tool: ReviewTool, request: KyosoReviewRequest, agent: "codex" | "claude"): string;
@@ -0,0 +1,15 @@
1
+ import type { AgentRunResult, KyosoFinding } from "../core/types.js";
2
+ export type AggregatedReview = {
3
+ findings: KyosoFinding[];
4
+ testsToAdd: string[];
5
+ residualRisks: string[];
6
+ disagreements: Array<{
7
+ topic: string;
8
+ positions: Array<{
9
+ agent: "codex" | "claude";
10
+ opinion: string;
11
+ }>;
12
+ judgeComment: string;
13
+ }>;
14
+ };
15
+ export declare function aggregateAgentResults(results: AgentRunResult[]): AggregatedReview;
@@ -0,0 +1,3 @@
1
+ import type { Severity } from "../core/types.js";
2
+ export declare function compareSeverity(a: Severity, b: Severity): number;
3
+ export declare function maxSeverity(a: Severity, b: Severity): Severity;
@@ -0,0 +1,3 @@
1
+ export declare function sanitizeForAudit(value: unknown, options?: {
2
+ includeRawAgentOutput?: boolean;
3
+ }): unknown;
@@ -0,0 +1,12 @@
1
+ export type TraceWriter = {
2
+ tracePath?: string;
3
+ warnings: string[];
4
+ write(event: Record<string, unknown>): Promise<void>;
5
+ };
6
+ export declare function createTraceWriter(options: {
7
+ enabled: boolean;
8
+ directory: string;
9
+ traceId: string;
10
+ cwd: string;
11
+ includeRawAgentOutput?: boolean;
12
+ }): TraceWriter;