mirror of
https://github.com/affaan-m/ECC.git
synced 2026-08-30 19:59:40 +02:00
Merge pull request #2566 from affaan-m/agent/readme-kimi-layout-20260724
Merge the aligned ECC entry cards, inline guide row, and documented Kimi/Itō self-hosting path after full CI and visual verification.
This commit is contained in:
+7
-5
@@ -2,12 +2,12 @@
|
||||
|
||||
This directory contains the ECC (Everything Claude Code) configuration for the Kimi Code CLI harness.
|
||||
|
||||
## What is installed
|
||||
## What Kimi Code discovers natively
|
||||
|
||||
- `rules/ecc/` — shared coding rules and guidelines
|
||||
- `skills/ecc/` — reusable skills
|
||||
- `commands/` — slash commands
|
||||
- `AGENTS.md` — agent instructions
|
||||
- `AGENTS.md` — project instructions loaded by Kimi Code's hierarchical instruction discovery
|
||||
- `skills/` — project skills loaded by Kimi Code's native Agent Skills discovery
|
||||
|
||||
ECC also copies shared rules, agents, and legacy command shims into `.kimi/` for portability and reference. Kimi Code's native invocation surface is Agent Skills (`/skill:<name>` and `/flow:<name>`), not arbitrary Markdown files in `commands/`.
|
||||
|
||||
## Manual install
|
||||
|
||||
@@ -20,6 +20,8 @@ bash ./install.sh --target kimi --profile minimal
|
||||
- The `kimi` target installs into the project-level `./.kimi/` directory.
|
||||
- Kimi Code CLI's own config (`~/.kimi-code/config.toml`, plugins) is **not** touched by ECC install.
|
||||
- Use `npx ecc doctor --target kimi` to check install health.
|
||||
- Kimi Code provider configuration remains separate. Use the [official providers and models guide](https://moonshotai.github.io/kimi-cli/en/configuration/providers.html) for Kimi API, OpenAI-compatible, Anthropic, or other supported endpoints.
|
||||
- Kimi Code's [Agent Skills guide](https://moonshotai.github.io/kimi-cli/en/customization/skills.html) documents the `.kimi/skills/` discovery contract.
|
||||
|
||||
## Self-hosted model compute
|
||||
|
||||
|
||||
@@ -50,32 +50,28 @@ ECC v2.0.0 adds the public Hermes operator story on top of that reusable layer:
|
||||
|
||||
---
|
||||
|
||||
<table>
|
||||
<table aria-label="ECC primary links" width="100%">
|
||||
<tr>
|
||||
<td width="25%" align="center">
|
||||
<td width="33%" align="center">
|
||||
<a href="https://ecc.tools/pricing">
|
||||
<strong> ECC Pro</strong><br />
|
||||
<sub>Private repos · GitHub App · $19/seat/mo</sub>
|
||||
</a>
|
||||
<img src="assets/ecc-icon.svg" height="42" alt="ECC Tools" /><br />
|
||||
<strong>ECC Pro + GitHub App</strong>
|
||||
</a><br />
|
||||
<sub><a href="https://github.com/apps/ecc-tools">Install free</a> · <a href="https://ecc.tools/pricing">Private repos from $19/seat/mo</a></sub>
|
||||
</td>
|
||||
<td width="25%" align="center">
|
||||
<td width="33%" align="center">
|
||||
<a href="https://github.com/sponsors/affaan-m">
|
||||
<strong> Sponsor</strong><br />
|
||||
<sub>Fund the OSS · From $5/mo</sub>
|
||||
</a>
|
||||
<img src="assets/images/community/heart.svg" height="42" alt="" /><br />
|
||||
<strong>Sponsor ECC</strong>
|
||||
</a><br />
|
||||
<sub>Fund the OSS · From $5/mo</sub>
|
||||
</td>
|
||||
<td width="25%" align="center">
|
||||
<a href="https://github.com/affaan-m/ECC/discussions">
|
||||
<td width="33%" align="center">
|
||||
<a href="https://discord.gg/36yGMHGFbR">
|
||||
<img src="assets/images/community/discord.svg" height="42" alt="Discord" /><br />
|
||||
<strong>Community</strong>
|
||||
<br />
|
||||
<sub>Discussions · Q&A · Show & Tell</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td width="25%" align="center">
|
||||
<a href="https://github.com/apps/ecc-tools">
|
||||
<strong> GitHub App</strong><br />
|
||||
<sub>Install · PR audits · Free tier</sub>
|
||||
</a>
|
||||
</a><br />
|
||||
<sub>Discord · Q&A · Show & Tell</sub>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -106,32 +102,31 @@ ECC v2.0.0 adds the public Hermes operator story on top of that reusable layer:
|
||||
|
||||
This repo is the raw code only. The guides explain everything.
|
||||
|
||||
<table>
|
||||
<table aria-label="ECC guides" width="100%">
|
||||
<tr>
|
||||
<td width="50%" align="center">
|
||||
<td width="33%" align="center">
|
||||
<a href="./the-shortform-guide.md">
|
||||
<img src="./assets/images/shortform/00-header.png" width="420" alt="The Shorthand Guide to ECC" /><br />
|
||||
<img src="./assets/images/shortform/00-header.png" height="120" alt="The Shorthand Guide to ECC" /><br />
|
||||
<b>The Shorthand Guide</b>
|
||||
</a>
|
||||
<br /><sub>Setup, foundations, philosophy. <b>Read this first.</b> (<a href="https://x.com/affaan/status/2012378465664745795">thread</a>)</sub>
|
||||
</td>
|
||||
<td width="50%" align="center">
|
||||
<td width="33%" align="center">
|
||||
<a href="./the-longform-guide.md">
|
||||
<img src="./assets/images/longform/01-header.png" width="420" alt="The Longform Guide to ECC" /><br />
|
||||
<img src="./assets/images/longform/01-header.png" height="120" alt="The Longform Guide to ECC" /><br />
|
||||
<b>The Longform Guide</b>
|
||||
</a>
|
||||
<br /><sub>Token optimization, memory persistence, evals, parallelization. (<a href="https://x.com/affaan/status/2014040193557471352">thread</a>)</sub>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div align="center">
|
||||
<td width="33%" align="center">
|
||||
<a href="./the-security-guide.md">
|
||||
<img src="./assets/images/security/security-guide-header.png" width="420" alt="The Shorthand Guide to Everything Agentic Security" /><br />
|
||||
<img src="./assets/images/security/security-guide-header.png" height="120" alt="The Shorthand Guide to Everything Agentic Security" /><br />
|
||||
<b>The Security Guide</b>
|
||||
</a>
|
||||
<br /><sub>Attack vectors, sandboxing, sanitization, CVEs, AgentShield. (<a href="https://x.com/affaan/status/2033263813387223421">thread</a>)</sub>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
| Topic | What You'll Learn |
|
||||
|-------|-------------------|
|
||||
@@ -144,6 +139,52 @@ This repo is the raw code only. The guides explain everything.
|
||||
|
||||
---
|
||||
|
||||
## Self-host Kimi with ECC + Itô compute
|
||||
|
||||
The Kimi Code harness and the model-serving layer are separate. ECC configures the agent harness; you bring an API endpoint or self-host an open-weight Kimi model on your own GPU capacity.
|
||||
|
||||
<table aria-label="Local Kimi model path" width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="center">
|
||||
<a href="https://compute.itomarkets.com">
|
||||
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/images/sponsors/ito-dark.svg" /><img src="assets/images/sponsors/ito.svg" width="180" alt="Itô Markets" /></picture><br />
|
||||
<strong>1. Get GPU capacity</strong>
|
||||
</a><br />
|
||||
<sub>Use Itô or any GPU provider.</sub>
|
||||
</td>
|
||||
<td width="33%" align="center">
|
||||
<a href="https://www.moonshot.ai">
|
||||
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/images/sponsors/moonshot-dark.png" /><img src="assets/images/sponsors/moonshot.png" width="126" alt="Moonshot AI — Kimi" /></picture><br />
|
||||
<strong>2. Serve Kimi</strong>
|
||||
</a><br />
|
||||
<sub>Expose the chosen checkpoint through a Kimi- or OpenAI-compatible endpoint.</sub>
|
||||
</td>
|
||||
<td width="33%" align="center">
|
||||
<a href=".kimi/README.md">
|
||||
<img src="assets/ecc-icon.svg" height="52" alt="ECC Tools" /><br />
|
||||
<strong>3. Run Kimi Code with ECC</strong>
|
||||
</a><br />
|
||||
<sub>Install project instructions and skills, then start <code>kimi</code>.</sub>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Configure the endpoint using Kimi Code's <a href="https://moonshotai.github.io/kimi-cli/en/configuration/providers.html">official provider guide</a>, then install the ECC project surface:
|
||||
|
||||
```bash
|
||||
bash ./install.sh --target kimi --profile minimal
|
||||
npx ecc doctor --target kimi
|
||||
kimi
|
||||
```
|
||||
|
||||
Kimi Code discovers the installed `.kimi/AGENTS.md` instructions and `.kimi/skills/` workflows natively. The installer dry-run and regression suite verify that the Kimi target stays inside the project-local `.kimi/` root.
|
||||
|
||||
Run or self-host any open-source model on owned or rented GPUs. Itô is ECC's preferred compute sponsor; any GPU provider works. The sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving. Separately, `ecc ito find` invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet.
|
||||
|
||||
<sub>This three-beat strip is also the video outline: capacity → serving endpoint → Kimi Code with ECC.</sub>
|
||||
|
||||
---
|
||||
|
||||
## What's New
|
||||
|
||||
### v2.0.0 — The Agent Harness Operating System (Jun 2026)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Discord</title>
|
||||
<path fill="#5865F2" d="M20.317 4.3698a19.7913 19.7913 0 0 0-4.8851-1.5152.0741.0741 0 0 0-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 0 0-.0785-.037 19.7363 19.7363 0 0 0-4.8852 1.515.0699.0699 0 0 0-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 0 0 .0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 0 0 .0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 0 0-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 0 1-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 0 1 .0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 0 1 .0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 0 1-.0066.1276 12.2986 12.2986 0 0 1-1.873.8914.0766.0766 0 0 0-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 0 0 .0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 0 0 .0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 0 0-.0312-.0286ZM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189Zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg role="img" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Support ECC</title>
|
||||
<path d="M32 54 10.8 34.1C-.9 23.1 6.4 8 19.2 8c5.5 0 10 3 12.8 7.2C34.8 11 39.3 8 44.8 8 57.6 8 64.9 23.1 53.2 34.1L32 54Z" fill="none" stroke="#F43F5E" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 330 B |
@@ -61,6 +61,7 @@
|
||||
"agent.yaml",
|
||||
"assets/ecc-icon.svg",
|
||||
"assets/hero.png",
|
||||
"assets/images/community/",
|
||||
"assets/images/sponsors/",
|
||||
"agents/",
|
||||
"commands/",
|
||||
|
||||
@@ -56,6 +56,31 @@ function assertExactComputeRoute(content) {
|
||||
);
|
||||
}
|
||||
|
||||
function assertExactHref(content, expectedHref) {
|
||||
const expected = new URL(expectedHref);
|
||||
const hrefs = [...content.matchAll(/\bhref="([^"]+)"/g)].map(match => match[1]);
|
||||
const properties = [
|
||||
'protocol',
|
||||
'hostname',
|
||||
'port',
|
||||
'username',
|
||||
'password',
|
||||
'pathname',
|
||||
'search',
|
||||
'hash',
|
||||
];
|
||||
const hasExactHref = hrefs.some((href) => {
|
||||
try {
|
||||
const candidate = new URL(href);
|
||||
return properties.every(property => candidate[property] === expected[property]);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(hasExactHref, `Should include the exact href ${expectedHref}`);
|
||||
}
|
||||
|
||||
function assertHonestComputeCopy(content) {
|
||||
assertExactComputeRoute(content);
|
||||
assert.match(content, /preferred compute sponsor/i);
|
||||
@@ -70,6 +95,16 @@ function assertHonestComputeCopy(content) {
|
||||
assert.doesNotMatch(content, /ECC only (?:links|provides this link)/i);
|
||||
}
|
||||
|
||||
function extractNamedTable(content, ariaLabel) {
|
||||
const escapedLabel = ariaLabel.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const match = content.match(
|
||||
new RegExp(`<table[^>]*aria-label="${escapedLabel}"[^>]*>([\\s\\S]*?)<\\/table>`)
|
||||
);
|
||||
|
||||
assert.ok(match, `Should include the "${ariaLabel}" table`);
|
||||
return match[1];
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('\n=== Testing Ito compute-sponsor surface ===\n');
|
||||
|
||||
@@ -128,6 +163,151 @@ function main() {
|
||||
|| url.startsWith('https://fonts.googleapis.com/css2?')
|
||||
)));
|
||||
}],
|
||||
['README keeps the three primary choices and all three guides inline', () => {
|
||||
const readme = read('README.md');
|
||||
const primaryLinks = extractNamedTable(readme, 'ECC primary links');
|
||||
const guides = extractNamedTable(readme, 'ECC guides');
|
||||
|
||||
assert.strictEqual((primaryLinks.match(/<td\b/g) || []).length, 3);
|
||||
assert.ok(primaryLinks.includes('assets/ecc-icon.svg'));
|
||||
assertExactHref(primaryLinks, 'https://github.com/apps/ecc-tools');
|
||||
assertExactHref(primaryLinks, 'https://ecc.tools/pricing');
|
||||
assertExactHref(primaryLinks, 'https://github.com/sponsors/affaan-m');
|
||||
assert.ok(primaryLinks.includes('assets/images/community/heart.svg'));
|
||||
assertExactHref(primaryLinks, 'https://discord.gg/36yGMHGFbR');
|
||||
assert.ok(primaryLinks.includes('assets/images/community/discord.svg'));
|
||||
|
||||
for (const iconPath of [
|
||||
'assets/images/community/heart.svg',
|
||||
'assets/images/community/discord.svg',
|
||||
]) {
|
||||
const icon = read(iconPath);
|
||||
assert.match(icon, /<svg\b/);
|
||||
assert.doesNotMatch(
|
||||
icon,
|
||||
/<script|<foreignObject|\son[a-z]+=|(?:href|xlink:href)=/i
|
||||
);
|
||||
}
|
||||
|
||||
assert.strictEqual((guides.match(/<td\b/g) || []).length, 3);
|
||||
assert.ok(guides.includes('./the-shortform-guide.md'));
|
||||
assert.ok(guides.includes('./the-longform-guide.md'));
|
||||
assert.ok(guides.includes('./the-security-guide.md'));
|
||||
}],
|
||||
['README shows the verified local Kimi via Ito path without claiming managed serving', () => {
|
||||
const readme = read('README.md');
|
||||
const localModelPath = extractNamedTable(readme, 'Local Kimi model path');
|
||||
|
||||
assert.strictEqual((localModelPath.match(/<td\b/g) || []).length, 3);
|
||||
assert.ok(localModelPath.includes('assets/images/sponsors/ito.svg'));
|
||||
assert.ok(localModelPath.includes('assets/images/sponsors/moonshot.png'));
|
||||
assert.ok(localModelPath.includes('assets/ecc-icon.svg'));
|
||||
assert.match(readme, /install\.sh --target kimi --profile minimal/);
|
||||
assert.match(readme, /npx ecc doctor --target kimi/);
|
||||
assert.match(readme, /\.kimi\/AGENTS\.md/);
|
||||
assert.match(readme, /\.kimi\/skills\//);
|
||||
assertExactHref(
|
||||
readme,
|
||||
'https://moonshotai.github.io/kimi-cli/en/configuration/providers.html'
|
||||
);
|
||||
assertHonestComputeCopy(readme);
|
||||
}],
|
||||
['Kimi install stays inside its project root and passes doctor with native instruction surfaces', () => {
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-kimi-home-'));
|
||||
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-kimi-project-'));
|
||||
|
||||
try {
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.join(REPO_ROOT, 'scripts', 'install-apply.js'),
|
||||
'--target',
|
||||
'kimi',
|
||||
'--profile',
|
||||
'minimal',
|
||||
'--dry-run',
|
||||
'--json',
|
||||
],
|
||||
{
|
||||
cwd: projectDir,
|
||||
env: { ...process.env, HOME: homeDir },
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 20 * 1024 * 1024,
|
||||
}
|
||||
);
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
|
||||
const plan = JSON.parse(result.stdout).plan;
|
||||
const targetRoot = path.resolve(plan.targetRoot);
|
||||
const destinations = plan.operations.map(operation => (
|
||||
path.resolve(operation.destinationPath)
|
||||
));
|
||||
const relativeDestinations = destinations.map(destination => (
|
||||
path.relative(targetRoot, destination).replaceAll(path.sep, '/')
|
||||
));
|
||||
|
||||
assert.strictEqual(plan.target, 'kimi');
|
||||
assert.strictEqual(plan.adapter.id, 'kimi-project');
|
||||
assert.strictEqual(plan.adapter.kind, 'project');
|
||||
assert.deepStrictEqual(plan.warnings, []);
|
||||
assert.ok(plan.operations.length > 0);
|
||||
assert.ok(destinations.every(destination => (
|
||||
destination === targetRoot || destination.startsWith(`${targetRoot}${path.sep}`)
|
||||
)));
|
||||
assert.ok(relativeDestinations.includes('AGENTS.md'));
|
||||
assert.ok(relativeDestinations.some(destination => destination.startsWith('skills/')));
|
||||
assert.ok(relativeDestinations.every(destination => (
|
||||
!/^\.(?:claude|codex|cursor|gemini|hermes|opencode|openclaw|qwen|zed)\//.test(destination)
|
||||
)));
|
||||
|
||||
const apply = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.join(REPO_ROOT, 'scripts', 'install-apply.js'),
|
||||
'--target',
|
||||
'kimi',
|
||||
'--profile',
|
||||
'minimal',
|
||||
'--json',
|
||||
],
|
||||
{
|
||||
cwd: projectDir,
|
||||
env: { ...process.env, HOME: homeDir },
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 30 * 1024 * 1024,
|
||||
}
|
||||
);
|
||||
assert.strictEqual(apply.status, 0, apply.stderr);
|
||||
assert.strictEqual(JSON.parse(apply.stdout).result.target, 'kimi');
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.kimi', 'AGENTS.md')));
|
||||
assert.ok(fs.readdirSync(path.join(projectDir, '.kimi', 'skills')).length > 0);
|
||||
|
||||
const doctor = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.join(REPO_ROOT, 'scripts', 'doctor.js'),
|
||||
'--target',
|
||||
'kimi',
|
||||
'--json',
|
||||
],
|
||||
{
|
||||
cwd: projectDir,
|
||||
env: { ...process.env, HOME: homeDir },
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 30 * 1024 * 1024,
|
||||
}
|
||||
);
|
||||
assert.strictEqual(doctor.status, 0, doctor.stderr);
|
||||
const doctorResult = JSON.parse(doctor.stdout).results.find(result => (
|
||||
result.adapter.target === 'kimi'
|
||||
));
|
||||
assert.ok(doctorResult);
|
||||
assert.strictEqual(doctorResult.exists, true);
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
}],
|
||||
['sponsor roster keeps Itô and Moonshot distinct from node tooling', () => {
|
||||
const sponsors = read('SPONSORS.md');
|
||||
assert.ok(sponsors.includes('[**Itô**]'));
|
||||
|
||||
@@ -88,6 +88,7 @@ function buildExpectedPublishPaths(repoRoot) {
|
||||
"VERSION",
|
||||
"assets/ecc-icon.svg",
|
||||
"assets/hero.png",
|
||||
"assets/images/community",
|
||||
"docs/CODEX-NAVIGATION-GUIDE.md",
|
||||
"docs/COMMAND-AGENT-MAP.md",
|
||||
"assets/images/sponsors",
|
||||
@@ -164,6 +165,8 @@ function main() {
|
||||
"plugins/ecc/.codex-plugin/plugin.json",
|
||||
"assets/ecc-icon.svg",
|
||||
"assets/hero.png",
|
||||
"assets/images/community/discord.svg",
|
||||
"assets/images/community/heart.svg",
|
||||
"docs/CODEX-NAVIGATION-GUIDE.md",
|
||||
"docs/COMMAND-AGENT-MAP.md",
|
||||
"schemas/install-state.schema.json",
|
||||
|
||||
Reference in New Issue
Block a user